Sunday, November 12, 2023

Ham Radio Assembly Language for Browsers

<!-- HAL -->
<!DOCTYPE html>
<html>
<!-- Hi I am a comment -->
  <style >
body {background-color: gray;}
  td { overflow='clip';}
  textarea
  {background-color: green; color: white; font-size: 25px; padding = 10px}
  canvas {background-color=navy;}
  th { color:black}
  select { color:black;background-color : lime}
  table  {color: blue; text-align: center; border : 2px;}
  button {background-color : red }
  h1 {background-color : green; font-size : 24px; }
  ul {background-color : blue; color : white; border : 4px ; text-align : center}
  caption {background-color : yellow;font-size:20px;}
  p {background-color : yellow; color: black;font-size: 15px;
   text-align: center; vertical-align : top; width " 70"; hidden=true}
</style>
   <h1 align='center'>HAL</h1>
  <form id = 'dummy' >
    <button onclick ='ok()'>OK</button>
<button onclick ='cancel()'>Cancel</button>
<textarea cols=50 rows = 3 font-size = 14px>Javascript libraries use this part of the screen for user input. The dialog docking area.  Operators hide this window as desired.</textarea>


</form>
   <div align = left>
<div>
  <table >
        <caption>Simple Menu System V1.77</caption>
    <tbody >
    <tr>
      <td>
        <textarea id = 'selectedItem' cols=10 rows=1>Top</textarea>
      </td>
      <td>
        <button id ='menuNext' >Next</button>
        <button id ='menuDown' >Down</button>
        <button id ='menuUp' >Up</button>
      </td>
      <td width=200></td>

</tr>
</tbody>
</table>
</div>

</div>
<br>
<table id = 'Display1' align = left>
    <caption>Incoming Connection Reports</caption>
    <tbody class = 'Display' id = 'Displays' >
      <tr>
        <td ><textarea  class = 'Display' cols=15 id = "D1">  Frequ 10</textarea></td>
        <td><textarea  class = 'Display' cols=15 id = "D2">  Power 10</textarea>
        </td>

        
      </tr>
       <tr>
         <td id = 'connectTop'>
           <button  name = 'B11'  > B11</button><button  name = 'B12'  > B12</button><button  name = 'B13'> B13</button> <button name = 'B14'> B14</button>
       </td>
       <td id = 'connectBottom'>
         <button  name = 'B21'  > B21</button><button  name = 'B22'  > B22</button><button  name = 'B23'  > B23</button><button name = 'B24'>B24</button>
        </td>
     
       </tr>
    </tbody>

  </table>

<div >

<table >
  <colgroup>
    <col valign=top/>
    <col valign=top/>
  </colgroup>
  <caption>Ham Assembly Language</caption>
  <tbody >
    <tr>
      <th id= 'contexts'>
      <select name= "textMethods" onchange = "actionText(this)">
        <option  onclick = 'saveText()'>Save</option>
        <option  onclick = 'closeText()'>Close</option>
        <option  onclick = 'openText()'>Open</option>
        <option  onclick = 'createText()'>Create</option>
      </select>
    </th>
    <th>Log</th>
      <th id = 'sources' contenteditable=true>Sources</th>
    </tr>
      <tr id = 'textareas' valign=top>
           <td>
      <ul class = 'visible' id = 'macroList'></ul>
    </td>
      <td>
      <textarea class = 'visible' id = 'logger' cols="35" rows="25" border = 2  >Logger </textarea>
      </td>
      <td id = "textanchor"></td>
    <td>

  </td>
 
  </tr>
  </tbody>
  </table>

  </div>

  <ul  class = 'top' id = 'simpleMenu' hidden>
    <ul class = 'Debugger'>
    <li class = 'debug' onclick = 'DebugStep(INIT)'>Init</li>
    <li class = 'debug' onclick = 'DebugStep(TOKEN)'>Token</li>
    <li class = 'debug' onclick = 'DebugStep(LINE)'>Line</li>
  </ul>
  <ul  class= "usb">
      <li class = "method"  onclick ="USBConnect(current)">Connect</li>
      <li class = "method"  onclick = "openport()">open</li>
      <li class = "method"  onclick ="getports()">Ports</li>
      <li class = "method"  onclick ="getport()">Port</li>
      <li class = "method"  onclick ="readport()">Read</li>
      <li class = "method"  onclick ="writeport()">Write</li>
      <li class = "method"  onclick ="closeport()">Close</li>
      <li class = "method"  onclick ="infoport()">Info</li>
      <li class = "method"  onclick ="freeport()">Free</li>
    </ul>
    <li class = 'Exec' onclick ="ExecSource(current);">RUN</li>
   
    <ul class = 'Assembler'>
      <li class = 'list' onclick ="listLibrary()">Library</li>
      <li class = 'list' onclick ="listOpcodes()">Opcodes</li>
      <li class = 'list' onclick ="listSysOps();">Sysops</li>
      <li class = 'list' onclick ="listSymbols();">Symbols</li>
    </ul>


  </ul>

<div id = 'startcode'>


#log nice start;
  add r0 hope;
#log end;
hope sub r0 r2;
#log done it;
</div>

  <script>
//tokens
// tokens can have various types
// with precedances
//  / scoping rules
const NEWLINE = 32;
const LITERAL = 20;
const VAL = 19; const NUM = 18; const REG = 17;
const MUL = 16; const DIV = 15;
const ADD = 14; const SUB = 13;
const LP = 12; const RP = 11;
const COMMA = 10;
const MACRO = 9;
const OP = 8; const SEMI = 7;
const ALPHA = 6;
const SYSOP = 5
const DISCARD = 4;
const QUOTE = 3;

// return status
const OK = 101; const DONE =102; // normal or source done
const WAIT = 103; const ERROR = -3; // forward reference or syntax error

// symbol classes
const USER = 40; const HAL = 41; const CONST = 42;
const EMBED = 43; const MODULE = 44; const LIB = 45;
// step indicators
const TEST = 56; const INIT = 55; const INDEX = 54;
const LINE = 53; const TOKEN = 52; const OFF = 51;

// symbol,states
const NULL = -1; const UNDEF = -2;
const DEF = 202; const PREDEF = 203;
const LOG = document.getElementById('logger');
</script>
<script id='halinone'>
  
  //bigtable

// const USER,OP,SYSOP,EMBED,MODULE,LIB  / scoping rules
// All symbols in one table, sysops, opodes, user symbols
const Symbol = {str : "",expr : 0,type : 0,value : 0,handle : null}
var symtable = [
  {str : 'R0',expr : RegExp(/R0/,'i'),type : USER, value : 0,handle : 0},
  {str : 'R1',expr : RegExp(/R1/,'i'),type : USER, value : 1,handle : null},
  {str : 'R2',expr : RegExp(/R2/,'i'),type : USER, value : 2,handle : null},
  {str : 'R3',expr : RegExp(/R3/,'i'),type : USER, value : 3,handle : null},
  {str : 'define',  expr : RegExp(/define/), type : SYSOP, value : 0,handle :  function(){return define()}},
  {str : 'assign',  expr : RegExp(/assign/), type : SYSOP,value : 0,handle :  function(){return assign() }},
  {str : 'include', expr : RegExp(/include/),type : SYSOP,value : 0,handle :  function(){return include()}},
  {str : 'end',     expr : RegExp(/end/), type : SYSOP,value : 0,handle :  function(){return OK}},
  {str : 'log',     expr : RegExp(/log/), type : SYSOP,value : 0,handle :  function(){return log()}},
  {str : 'ifdef',   expr : RegExp(/ifdef/), type : SYSOP,value : 0,handle :  function(){return OK }},
  {str : 'else',    expr : RegExp(/else/) , type : SYSOP,value : 0,handle :
    function(){return OK }},
  {str : 'seg',     expr : RegExp(/seg/) , type : SYSOP,value : 0,handle :
    function(){return OK }},
  {str : 'add', expr : RegExp(/add/), type : OP, value : 0,handle : null},
  {str : 'sub', expr : RegExp(/sub/), type : OP, value : 0,handle : null},
  {str : 'mul' ,expr : RegExp(/mul/), type : OP, value : 0,handle : null},
  {str : 'div' ,expr : RegExp(/div/), type : OP, value : 0,handle : null},
  {str : 'shft',expr : RegExp(/shft/),type : OP, value : 0,handle : null},
  {str : 'and', expr : RegExp(/and/), type : OP, value : 0,handle : null},
  {str : 'or'  ,expr : RegExp(/or/),  type : OP, value : 0,handle : null},
  {str : 'xor' ,expr : RegExp(/xor/), type : OP, value : 0,handle : null},
  {str : 'addi',expr : RegExp(/addi/),type : OP, value : 0,handle : null},
  {str : 'subi',expr : RegExp(/subi/),type : OP, value : 0,handle : null},
  {str : 'ori', expr : RegExp(/ori/), type : OP, value : 0,handle : null},
  {str : 'xori',expr : RegExp(/xori/),type : OP, value : 0,handle : null},
  {str : 'clr' ,expr : RegExp(/clr/), type : OP, value : 0,handle : null},
  {str : 'comp',expr : RegExp(/comp/),type : OP, value : 0,handle : null},
  {str : 'jmp' ,expr : RegExp(/jmp/), type : OP, value : 0,handle : null},
  {str : 'call',expr : RegExp(/call/),type : OP, value : 0,handle : null},
  {str : 'bre' ,expr : RegExp(/br/) , type : OP, value : 0,handle : null},
  {str : 'brn' ,expr : RegExp(/brn/), type : OP, value : 0,handle : null},
  {str : 'br'  ,expr : RegExp(/brp/), type : OP, value : 0,handle : null},
  {str : 'ret' ,expr : RegExp(/ret/), type : OP, value : 0,handle : null},
  {str : 'btst',expr : RegExp(/btst/),type : OP, value : 0,handle : null},
  {str : 'bset',expr : RegExp(/bset/),type : OP, value : 0,handle : null},
  {str : 'ld'  ,expr : RegExp(/ld/),  type : OP, value : 0,handle : null},
  {str : 'ldm' ,expr : RegExp(/stm/), type : OP, value : 0,handle : null},
  {str : 'ldw' ,expr : RegExp(/ldw/), type : OP, value : 0,handle : null},
  {str : 'st'  ,expr : RegExp(/st/),  type : OP, value : 0,handle : null},
  {str : 'stm' ,expr : RegExp(/stm/), type : OP, value : 0,handle : null},
  {str : 'stw' ,expr : RegExp(/stw/), type : OP, value : 0,handle : null}
  ]
  var symLength = symtable.length;

 function listSymbols(type) {
   clearLog();
  strLog('\n  Symbols ');
  for(let i=0; i < symtable.length;i++)
    if(symtable[i] = type)
  strLog('\n: ' + i +' '  + symtable[i].str + ' '+symtable[i].expr +' '+symtable[i].value );
  }

function symValue(index) {
   if(index == false) index =0;
  if((index< 0) || (index > symtable.length)) return syntaxError('Bad index');
  return symtable[index].value;
}

function addSym(name,type,value) {
  var index = findSym(name)
  if(index > -1) {
    symtable[index].expr = RegExp(name);
    symtable[inde].type = type
    symtable[index].value = value;
    }
  else{
    var sym = Object(Symbol);
    sym.str =name;
    sym.expr = RegExp(name)
    sym.type = type;
    sym.value = value;
    symtable.push(sym);
  }
  return OK;
}
function findSym(name) {
    len = name.length;
    for(let i =0; i < symtable.length;i++) {
      if(len == symtable[i].str.length)
        if(symtable[i].expr.test(name)) {
        return i;
        }
    }
      return UNDEF;
}
// Drop entries from  user symbols
 function delSym() {
  do {
    if(nextToken() < 0) return syntaxError('No token')
    if(index = findSym(cc.slice) < 0)
      break;
    var type = cc.type;
    if(type == SEMI) break;
    symtable.splice(index,1);
  } while(type != SEMI);
  return endOfLine();
}


  // assembler found a symbol
  // a finite string of alpha numerics
  // that begins with an alpha
function symbol(opContext) {
  var index;
  if(arguments.length == 0) {// symbol defined
    console.log('New symbol');
    index=newSym(cc.slice(),cc.line())
    symtable[index].state = DEF;
    symtable[index].value = cc.line();
    return waitService(i);
  } else  { // this maybe a wait
    if( (index = findSym(cc.slice())) < 0){
      opContext.index =newSym(cc.slice());
      return waitRequest(opContext); // opcode context pushed onto wait stack
    } else {
      if(symtable[index].state == UNDEF) {
        opContext.index = index;
        return waitRequest(opContext); // opcode context pushed onto wait stace
      } else {
        cc.setIndex(symtable[index].value)
        cc.setType(VAL); //resolved
        return OK
        }
      }
    }
}
// text
 function clearLog() {
  LOG.textContent = ' ';
}
// send string to log
function strLog(str){
  LOG.textContent+=  str;
  }
 // send string to log
function strPrependLog(str){
  LOG.textContent =  str + LOG.textContent;
  }
function srcCharByIndex(node,index) {
  var ch = node.textContent.charAt(index);
  return ch
}
 function tokenText(str) {
  var s= String();
  s =  '|'+cc.slice()+'|';
  //s.replace(/\n/,'X')
  if(arguments > 1) s += str;
  strPrependLog(
  '\nTok ' + s + ' ' + ' t: ' + cc.type()+' s: '+cc.start()+ ' e: ' + cc.end()+'\n' );
}

// generic find a name among
// a list of html children
function findItemByName(items,name) {
  for(i=0;i < items.length;i++)
    if(items[i].name == name)
      return items[i];
  return null;
}
function findText(name) {
  items = document.getElementById('textanchor').children;
  return findItemByName(items,name);
}

function findListItem(name) {
  items = document.getElementsByClassName('openmacro');
  return findItemByName(items,name);
}
// when the user clicks on a macro list item
function setListEvent(node) {
  node.addEventListener('click', () => {
  showText(node.name);
  blinkListItems(node.name);
  //console.log('Set up ' +node.name)
  });
}
function newListItem(name) {
  var list = document.createElement('li')
  list.name = name;
  list.className = 'openmacro'
  list.textContent = name
  //console.log('NewItem '+ name);
  setListEvent(list);
  document.getElementById('macroList').appendChild(list);
  showText(name);
  }
function delListItem(name) {
  parent = document.getElementById('macroList');
  node = findName(name,parent.children);
  parents.removeChild(node);
}
////////////// Methods to manage textareas////////////////
function listTexts() {
  var items = document.getElementById('textanchor').children;
  for(let i =0; i < items.length;i++) {
    strLog(': '+ items[i].name);
  }
}
function saveText() {
  strPrependLog('Save\n');
  var nameNode =  document.getElementById('sources');
  var textNode = findTextByName(nameNode.textContent);
  if(textNode.hidden == false) {// The macro in focus
    localStorage.setItem(nameNode.name,textNode.textContent);
    nameSelector();
  }
  return;
}
// th element as editable input
function newText(name) {
  strPrependLog('New\n');
  if(name == null)
    name = document.findElementByID('sources').textContent;
  addText(name);
}
function openText(name) {
  strPrependLog('Open\n');
}
function closeText() { strPrependLog('Close\n');
  parent = document.getElementById('macroList');
  name = document.getElementById('sources').textContent;
  node = nodeFindByName(parent.chldren,name);
  parent.removeChild(node);
  parent = documemt.getElementById('textanchor');
  node = nodeFindByName(parent.chldren,name);
  parent.removeChild(node);
}
function showText(name) {
  items = document.getElementById('textanchor').children;
  for(i=0;i < items.length;i++) {
    if(items[i].name == name)
      items[i].hidden=false;
    else
      items[i].hidden=true;
    document.getElementById('sources').textContent = name;
  }
}
function createText(name) {
  var td = document.getElementById('textanchor');
  var text = document.createElement('textarea');
  text.hidden = false;
  text.cols =30
  text.rows = 15
  if(name == null)
  text.name = document.getElementById('sources').textContent;
  else
  text.name = name;
  text.className = 'invisible';
  td.appendChild(text);
  showText(text.name);
  return text;
  }
  function context() {
    this.hidden = true;
    this.nextSibling().hidden = false;
    //this.parent.onchange();
  }
function actionText(node) {
  var items = node.children;
  for(i=0;i < items.length;i++)
    if(items[i].selected) {
      items[i].onclick(items[i].value);
      return;}
  }

function blinkListItems(name) {
  items = document.getElementById('macroList').children;
  radioButtons(name,items);
}

function source(name) {
  getElementById('sources').textContent=name;
  showTextArea(name);
  console.log('arrived');
}

// Make a name list from local storage
function nameSelector() {
  var len = localStorage.length;
  parent = document.getElementById('sources');
  var  sel = document.createElement('select');
  sel.hidden = true;
  sel.onchange = 'source()'.
  parent.append(sel);
  for(let i = 0;i < len;i++) {
    name = localStorage.key(i);
    var opt = document.createElement('option');
    opt.textContent = name;
    sel.appendChild(opt)
  }
  opt = document.createElement('option');
  opt.textContent='rename';
  sel.appendChild(opt);
}


function listLibrary() {
  clearLog();
  var len = localStorage.length;
  strLog('\nLocal storage ' + len)
  for(let i =0;i < len;i++) {
    var name = localStorage.key(i);
    value = localStorage.getItem(name);
    strLog('\n '+i+': ' +name + ' '+ value);
    }
  }
  // sysops

  //Install a module from local storage
// put up a selector for it, add its own
// text area, and install the name
// on the sysop table
function installModule(name,str) {
    console.log('Install');
    if(arguments.length == 2)
      localStorage.setItem(name,str);
    var index =  findSym(name);  // is it installed?
    if((index > -1) && (index < builtinsLength))
        return syntaxError('Opcode  redefined i '+index+' '+builtinsLength+'|'+name+'|')
    if(index >= 0) {  // already in the opcode table
      node= findListItem(name);
      if(node==null) syntaxError('Library misorder')
      node = findText(name)
      if(node== 0) syntaxError('Set up wrong')
    } else { // new set up
      strPrependLog('\nNew set '+name);
      node = createText(name);
      console.log('Installed  '+node.name + ' '+name);
      addSym(name);
      newListItem(name);
    }
    node.textContent=localStorage.getItem(name);
    return OK;
}

// drop an entry in the sysop table
 function undef() {
   remove(delSys); }
// in user table
function remove() {
   remove(delSym); }

function define() {
  do {
    if(nextToken() < 0) return syntaxError('No token')
      newSysop(cc.slice());
    }while(cc.type() != SEMI)
}
// manipulate the user symbol table
function assign(){
  do {
    if(nextToken() < 0) return syntaxError('No token')
    type = cc.type();
    if(type() == SEMI) break;
    token1 = cc.slice();
    if(nextToken() > 0) {
      type = cc.type()
      if(type ==ARG)
        newSym(token1,args.pop());
      else if(type = NUM)
        newSym(token1,JSON.parse(cc.slice()));
    } else
    newSym(token1,UNDEF);
    strPrependLog('Define: '+ token1 + ' ' + symValue(findSym(token1))+'\n')
  } while(cc.type() != SEMI);
  //nextToken(); //pass the semi
  return endOfLine();
}

function log(ptr){
  var start,end;
  var eol = endOfLine(); // move the newline pointer
  //console.log('log ' + newline.lastIndex + ' '+ SRC.textContent.length);
  start = cc.end();
  if(newline.lastIndex !== 0)
    end = newline.lastIndex-1;
  else
    end = cc.node().textContent.length;
  strPrependLog('\n '+ cc.slice(start,end)+'\n');
  return eol;
}
  function newSysop(name) {
  var i=0;
  var symbol = new Object(opCode);
  i = findSym(name,optable)
  console.log('New sys  '+name + ' '+i)
  if(i < 0) {// New entry
    symbol.str = name;
    symbol.expr = RegExp(name);
    symbol.idx=optable.length+1;
    optable.push(symbol);
    opcodesLength = optable.length;
  }
  return OK;
}
function delsysop(name) {
  i = findSym(name,optable);
  if(i < 0) return OK;
  optable.splice(i,1);
  return OK;
}

function include(){
  var node;
    console.log('Include');
    do {
      r=nextToken()
      var type = cc.type();
      if(type == SEMI)
        break; // move the newline pointer
      if(r < 0) return syntaxError('No token');
      if(type != ALPHA) return syntaxError('Expected Name');
      var name = cc.slice();
      installsysop(name);
      strPrependLog('Add sysop '+ name+'\n')
    } while(type != SEMI);
  return OK;
}
// Bracket quoted HAL must be valid
// Should end with end; pseudo opcode
function macro() {
  var index = nextToken();
  if(index > -1) syntaxError('cannot redefine');
  token = cc.slice();
  nextToken();
  if(cc.type() != LB) syntaxError('No start');
  newOpcode(token,cc.end());
  while(true) {
    nextToken()
    if(cc.type() == RB)
      break;
    endOfLine(); // skip the line
  }
}
</script>


<script>
  
// sneak in a fake source on startup
function sneak() {
  var str = document.getElementById('startcode').textContent
  installModule('source',str);
}
sneak();
</script>
<script>
 // exec

//Define a context of some type  of token
// must include the node holding textContent,
// and a start, end, lastIndex
// scanned in a  textArea of node, possibly
//having a symbol index pointing into the symbol table
// .
const Context = { start : 0, end : 0, type : 0,
                  node : 0,index : 0,line:1,lastIndex:0}
var CS = Array();

const cc = {
  k : -1,
  version : function(){ strPrependLog('V1.0\n')},
  length : function(){ return CS[this.k].end - CS[this.k].start;},
  get : function() {return CS[this.k]},
  clear : function(){CS.length =0; this.k =-1;},
  incLine : function(){ CS[this.k].line++;return CS[this.k].line;},
  line : function(){ return CS[this.k].line;},
  push : function(x){ this.k++; return CS.push(x)},
  pop : function(){ this.k--; return CS.pop()},
  startChar : function(){ return CS[this.k].node.textContent.charAt(CS[this.k].start)},
  endChar   : function(){ return CS[this.k].node.textContent.charAt(CS[this.k].end)},
  indexChar : function(index) { return CS[this.k].node.textContent.charAt(index);},
  setStart : function(start) {CS[this.k].start =start;},
  incStart : function(start) {CS[this.k].start++;},
  setLastIndex : function() {CS[this.k].lastIndex =CS[this.k].end;},
  start : function(start) {return  CS[this.k].start;},
  setIndex : function(index) {CS[this.k].index =index;},
  setEnd : function(end) { CS[this.k].end =end;},
  end : function() {return CS[this.k].end;},
  node : function() {return CS[this.k].node;},
  setType : function(type) { CS[this.k].type =type;},
  type : function() {return CS[this.k].type;},
  text : function() { return CS[this.k.node.textContent];},
  slice : function(start,end){
    var s,e;
    var i = this.k;
    if(arguments.length > 0)  s = start; else s = CS[this.k].start;
    if(arguments.length > 1) e = end; else e =CS[this.k].end;
    return CS[this.k].node.textContent.slice(s,e);
  },
  twoChars : function(){
    var s = CS[this.k].end;  // aftr the newline
    return CS[this.k].node.textContent.slice(s,s+2);
  }
}

// Initialize the assembler
function initHal() {
  tokend.lastIndex =0;
  newline.lastIndex =0;//
  clearLog();
  resetRpn();
  //resetWaits();
  return OK;
}
function endOfLine() {
  newline.lastIndex = tokend.lastIndex;
  newline.exec(cc.node().textContent)
  if(newline.lastIndex !== 0) {
// Do not allow parser to chew past arguments
    tokend.lastIndex = newline.lastIndex;
   return OK;
  }else return DONE;
  }
  // everything needed to process textContent
function newContext(node) {
  var p = new Object(CONTEXT);
  var x =0;
  p.lastIndex = 0;
  p.line = 1;
  p.start = 0;
  p.end = 0;
  p.type = DISCARD;
  p.node = node;
  p.name = node.name;
  cc.push(p);
  // Newline required here
  if(cc.indexChar(0) != '\n') return syntaxError('No starting newline');
  strLog('New Context ' + node.name);
  return endOfLine();
}
function execLines(){
  var result=OK;
  var count = 0;
  while( (result == OK) || (result == WAIT))  {
    count++;
    result = firstColumn();
    if(result==DONE)
      return strPrependLog('\nSource done');
    }
    syntaxAlert('Assembly error ' + result)
  }
  
function ExecSource() {
  node = findText('source')
  if(node == null) return syntaxError('Nosource');
  initHal();
  console.log('CC ' +cc.k)
  newContext(node);
  execLines();
  return OK;
}



function listToken() {
  var result = nextToken();
  if(result == OK)
    tokenText();
  return result;
}
function listTokens() {
  var result=OK;
  var str;
  clearLog()
  strPrependLog('\n...All tokens....');
  cc.setStart(0);
  cc.setEnd(1);
  tokstart.lastIndex =0;
  tokend.lastIndex = 0;
  newline.lastIndex =0;
  //endOfLine(); // to starting line
  do result = listToken();  while(result == OK);
  strPrependLog('End of source');
  return result;
}
function DebugStep(as) {
  var result;
  switch(as) {
    case TEST:
      e = findText('source');
      if(e.hidden == 1) delete e.hidden;
      else e.hidden = 1;
      break;
    case TOKEN :
      if(listToken() == DONE) InitHal();
    break;+tokend.lastIndex
    case LINE :
      if(nextToken() != DONE);
        result = firstColumn();
      //console.log('col end |'+cc.slice()+'|'+tokend.lastIndex);
    break;
    case INDEX:
    break;
    case INIT:
      var node = findText('source');
      if(node == null) console.log('Nosource');
      initHal();
      newContext(node);
    break;
  }
}

// forward reference array
var waits = new Array();
function waitService(index) {
  var n = waits.length;
  console.log('Wait service len ' + n)
  for(let i = 0; i < n;i++)
    if(waits[i].index == index) {
      cc.push(waits[i]);
      console.log('Service '+tokenText())
      waits.splice(i,1);
      argsProcess();
      CS.pop();
      }
    return OK;
  }
function waitRequest(context,index) {
  console.log('Wait request');
  context.index =index;
  waits.push(context);
  return WAIT;
}
function opProcess(token){}
function funProcess(token) {
  var result = 0;
  var textNodes = document.getElementsByClassName('invisible');
  var el = findName(textNodes,optable[token.index].str);
  initHal();
  result = newContext(el);
  while(result != DONE) {
      result = firstColumn();
  }
  return OK;
}

 //
// Global and local  regx
const newline = RegExp(/\n/ ,'g'); // a regx to find end of line
const tokstart = RegExp(/\S|\n/, 'g');
const semi =  RegExp(/;/,'g');
const tokend =  RegExp(/\W/,'g'); // no alpha or numeric
const quote =  RegExp(/\"/,'g'); // open literal
const bracket =  RegExp(/\{\}/,'g'); // open literal
// local operators

const alum =  RegExp(/\w/); // alpha or numeric
const space =  RegExp(/\t| /); // valid separators
const nospace =  RegExp(/\S/); // drk
const operator = RegExp(/[;\*\\\+\-#\(\)]/);
const white = RegExp(/\s/);  //not words

const primes = [
{ str : 'register', expr :  RegExp(/r\d/), type : REG},
{ str : 'alpha',    expr :  RegExp(/[a-zA-Z]/),type : ALPHA},
{ str : 'number',   expr :  RegExp(/[0-9]/),type : NUM},
{ str : 'sysop',    expr :  RegExp(/#/),type : SYSOP},
{ str : 'muliply',  expr :  RegExp(/[\*]/),type : MUL},
{ str : 'divide',   expr:   RegExp(/[\\]/),type : DIV},
{ str : 'add',      expr :  RegExp(/[\+]/),type : ADD},
{ str : 'sub',      expr :  RegExp(/[\-]/),type : SUB},
{ str : 'comma',    expr :  RegExp(/\,/),type : COMMA},
{ str : 'semi',     expr :  RegExp(/;/),type : SEMI},
{ str : 'left',     expr :  RegExp(/\(/),type : LP},
{ str : 'right',    expr :  RegExp(/\)/),type : RP},
{ str : 'newline',  expr :  RegExp(/\n/),type : NEWLINE}
]
const primeLength = primes.length;

function regtest(regx,str){
  
  let x = regx.test(str);
  return x;
}
 // errors
function syntaxAlert(msg) {
    var l;
    alert(msg +' type '+cc.type()+' '+cc.start()+' '+cc.end()+' '+cc.slice()+'\n')
    return OK;
  }
  // errors
function syntaxError(msg) {
    var l;
    strPrependLog(msg +' '+cc.start()+' '+cc.end()+' '+cc.slice()+'\n')
    return ERROR;
  }
function typeGet(index,str){
  let x = primes[index].expr.test(str);
  if(x) return primes[index].type;
  else return ERROR;
}
function updateToken(index) {
  var type,ch;
    ch = cc.indexChar(index);

    for(i=0;i < primeLength;i++)
      if( (type = typeGet(i,ch)) >  -1){
        cc.setType(type);
        return  cc.type();
      }
    return syntaxError('No type |'+ch+'|' );
  }

//args process found a quote character
function literal() {
  cc.setStart(cc.end());
  quote.lastIndex = cc.start();
  quote.exec(cc.text());
  if( (quote.lastIndex ==0) || (quote.lastIndex >= newlne.lastIndex) )
    return syntaxError('missing quote');
  cc.setEnd(quote.lastIndex-1);
  rpn();
  return OK;
  }
  
// The function sets the start and end indices
// for a token of three classes:
//  numeric, alphanumeric and single char operators
// New lin3 is a valid operator, right associated.
// It changes assmbler state based on the next two chars.
  function nextToken() {
    SRC= cc.node();
    if(SRC ===null) syntaxError('No source');
    var ch,index,result;
    tokstart.lastIndex = tokend.lastIndex-1; // get end of last token
    if(regtest(space,SRC.textContent.charAt(tokstart.lastIndex) )){
      tokstart.exec(cc.node().textContent)
      if(tokstart.lastIndex == 0) return DONE;
      } else tokstart.lastIndex++;
    updateToken(tokstart.lastIndex-1);
    tokend.lastIndex = tokstart.lastIndex;  // get start of current token
    if(regtest(alum,SRC.textContent.charAt(tokend.lastIndex-1)) ){
      tokend.exec(SRC.textContent);
      if(tokend.lastIndex == 0) return syntaxError('No line terminator')
      } else tokend.lastIndex++;  //must be a single char
    cc.setStart(tokstart.lastIndex-1);
    cc.setEnd(tokend.lastIndex-1);
    return OK;
    }
//First argument always an opcode
// handle opcode and multiple arguments
// symbol argument, literals, end of line
function argsProcess() {
  opContext = cc.get(); // restart here on forward reference
  if(nextToken() == DONE) return DONE;
  if(cc.type() == NEWLINE) { //blank line
    return OK;
  }
  // opcode required here
  index = findSym(cc.slice());
  if( index< 0) return syntaxError('\nNo op ' + cc.slice())
  rpn(); // process opcode
  let type = cc.type();
  while((type !=  SEMI) && (type != NEWLINE )) {
    if(nextToken() == ERROR) return syntaxError('Or a bug'); // line done
    type = cc.type();
    if(type == QUOTE) { // literals shipped as is.
      literal(); // one literal per line
      break;
    } else if(type == ALPHA)
        if(symbol(opContext ) == WAIT ) {
          return endOfLine(); // fludh to end of line
        }
 // ready to activate rpn)
    if(type > OP )
     rpn();
  }
  return OK;
  //endOfLine();
}
//the currnt token is newline
// which triggers  first column call
 function  firstColumn() {
  var result;
  if(cc.type() != NEWLINE) return syntaxError('Col bug');
  var twochars = cc.twoChars();

  // arrive here once per line and never more
  cc.incLine();  // Every context keeps its own line counter
  if(white.test(twochars)) // if no column one work
    return argsProcess(); // pass it on
  console.log('after args |'+cc.slice()+'|'+tokend.lastIndex);
  nextToken(); // there is column one work
  if(cc.type() == SYSOP) {
    if(nextToken() < 0)return syntaxError('No sysop ');
      let index = findMacro(cc.slice());
      if(index < 0)
        return syntaxError('Undefined sysop ');
      else {
        //console.log('Sysop '+cc.slice())
        return mactable[index].handle();
      }
      }
    // source defines symbol
    else if(cc.type() == ALPHA) {
      // we just set the symbol to the current lineZ
      symbol();
      return argsProcess();
      }
    else
      return syntaxError('Illegal char ');
}
if ("serial" in navigator) {
  // The Web Serial API is supported.
}
var port;

async function getport() {
  console.log('get port')
  port = await navigator.serial.requestPort();
  if(port)
    var info = port.getInfo();
  else console.log('no port')
  console.log('info '+ info)
}
// Get all serial ports the user has previously granted the website access to.
async function getports() {
 ports = await navigator.serial.getPorts();
 console.log('Get ports ' + ports.length)
 console.log(ports[0])
}

async function closeport() {
  await port.close();
}

// Filter on devices with te Arduino Uno USB Vendor/Product IDs.
const filters = [
  { usbVendorId: 0x2341, usbProductId: 0x0043 },
  { usbVendorId: 0x2341, usbProductId: 0x0001 }
];

// Prompt user to select an Arduino Uno device.
async function getPort() {
port = await navigator.serial.requestPort([filters]);
if(port)
 var info = port.getInfo();
}

// Wait for the serial port to open.
async function openport() {
await port.open({ baudRate: 9600 });
}
//After the serial port connection is established, the readable and writable properties //from the SerialPort object return a ReadableStream and a WritableStream. Those will be //used to receive data from and send data to the serial device. Both use Uint8Array //instances for data transfer.

//When new data arrives from the serial device, port.readable.getReader().read() returns //two properties asynchronously: the value and a done boolean. If done is true, the serial //port has been closed or there is no more data coming in. Calling //port.readable.getReader() creates a reader and locks readable to it. While readable is //locked, the serial port can't be closed.

async function readport() {
reader = port.readable.getReader();
  console.log('read '+  reader);
// Listen to data coming from the serial device.
while (true) {

  var { value, done } = await reader.read();
  if (done)
  {
    console.log('Value ' + value.length)
    // Allow the serial port to be closed later.
    reader.releaseLock();
    break;
  }
  // value is a Uint8Array.
}
  console.log('Done '+value.length);
}
function freeport(){
  if(reader)
    reader.releaseLock();
  if(writer)
    writr.relaseLock();
}

async function writeport() {
  var writer = port.writable.getWriter();
  var data = new Uint8Array([104, 101, 108, 108, 111,010,013]); // hello
  await writer.write(data);
  console.log('Written ');
  // Allow the serial port to be closed later.
  writer.releaseLock();
}
function getreader() {
const textDecoder = new TextDecoderStream();
const readableStreamClosed = port.readable.pipeTo(textDecoder.writable);
reader = textDecoder.readable.getReader();
}

// menu
var iCount=-1;
    var current;
    var selected =  document.getElementById("selectedItem")
    var menuItems =  document.getElementById('simpleMenu').childNodes
    current= menuItems[0];
    parent=current.parentNode;
    
 function radioButtons(name,items){
  for(i=0;i < items.length;i++) {
    if(items[i].name == name)
      items[i].style.backgroundColor = "orange";
    else
      items[i].style.backgroundColor = "navy";
  }
}
   
    // set up the radio buttons
function setRadioEvent(element) {
  element.addEventListener('click', () => {
  element.style.backgroundColor = 'red'
  let items=element.parentNode.children;
    radioButtons(element.name,items);
    //for(i=0;i<items.length;i++)
      // if(items[i].name != element.name)
        // items[i].style.backgroundColor = "blue"
    });
  }

 
function setConnects(str) {
  var element = document.getElementById(str)
  var items = element.children
  for(i=0; i < items.length;i++) setRadioEvent(items[i]);
  }
   
button = document.getElementById("menuNext")
 button.addEventListener('click', () => {

        do{
        iCount++
        if(menuItems.length == iCount) iCount = 0;
        current =  menuItems[iCount];
          if(current.nodeName=="UL")
            selected.textContent= current.className;
          else if(current.nodeName=="LI")
            selected.textContent= current.textContent;
      } while(current.nodeType !=1)
  
      });
   
   
   
  button = document.getElementById("menuDown")
  button.addEventListener('click', () => {
    if(current.nodeName == "UL") {
        parent=current;
        menuItems = parent.childNodes;
        current =  menuItems[0];
        iCount=-1
        if(current.nodeName=="UL")
              selected.textContent= current.className
        }
        else {
          selected.textContent= current.textContent;
          current.onclick()
        }
   });

 button = document.getElementById("menuUp")
 button.addEventListener('click', () => {
    if(parent.nodeName =="UL") {
      current = parent
      parent = current.parentNode;
      menuItems = parent.childNodes;
      iCount=-1
      selected.textContent= current.className
    } else
    console.log('To level')

   });
      setConnects('connectTop')
      setConnects('connectBottom')
      
      // resolve
objectCode = new Uint8Array(100);
arg = new Array();
oper = new Array();
function resetRpn() {
  arg.length = 0;
  oper.length = 0;}

function operLast()  {
  return oper[oper.length-1]}
function argLast()  {
  return arg[arg.length-1]}
  
function OpProcess(index) {
  var result = 0;
  switch(optable[index].type) {
    case MODULE:
      var str = optable[index].str;
      var node = findTextarea(str);
      newContext(node);
      execLines();
      cc.pop();
    break
    case MACRO:
      var state = nextToken();
      while(state != DONE)
      executeLine();
    break
    case END:
     return DONE;
     break;
}
  if(index < builtinsLength) processOpcode(index)
  else { // must be a module
    var str = optable[index].str;
    var node = findText(str);
    newContext(node);
    execLines();
    CS.pop();
  }

  return OK;
}
function flushLiteral(addr) {
  start = cc.start();
  end = start + cc.length;
  node=cc.node();
  while(start < end) {
    objectCode[addr] = node.textContent[start];
    start++;addr++;
  }
}
function flushNum(n,addr) {
  var list = String('0123456789abcdef')
  var out = String(' ');
  bit = 1;
  while(bit < n) {
    var r = 0;
    var t = 1;
    for(j=0;j < 4;j++) { // for each bit
      if(n & bit)
        r += t;
      t *=2;
      bit *=2;
    }
    out = list[r] +out;
  }
  for(j=0;j < out.length;j++){
    objectCode[addr] = out[j];
    addr++;
  }
    return addr;
}
// numbers or operators
function flushExpression(arg,addr) {
  var len = expr.length;
  var x;
  var y;
  var z;
  console.log('flush');
  while(arg.length>2) {  // there should remain one resolved literal
    x = arg.pop();
    y = arg.pop();
    z = 0;
      switch(lastOper.type) {
        case MUL:
          z = (x*y);
        break;
        case DIV:
          z =(x/y);
          break;
        case ADD:
          z =(x+y);
          break;
        case SUB:
          z =(x-y)
          break;
      }
      arg.push(z);
      arg.splice(0,1)
    }
    flushNum(z);
    return OK;
  }
// make the source line shunted
// evaluate arg expressions
// separat arguments
var addr=0;
function rpn()
{
  strLog('\nrpn ' + cc.slice());
  var type = cc.type();
    switch(type) {
      case LITERAL:
        addr=flushLiteral(addr);
      break;
      case VAL:
        arg.push(cc.index());
        break;
      case NUM:
        x = JSON.parse(cc.slice());
        arg.push(x);
     break;
      case RP:
        while(oper.length > 0 )
          if (type = lastOper.type != LP)
            arg.push(oper.pop().type)
          else
            addr = flushExpression(addr);
          if(oper.length == 0)return syntaxError('no left parenth')
          oper.pop();
        break;
      case SEMI:  // The last argument
      if(oper.length==0) return(syntaxError('Semi-colon mismatch'));
        addr = flushExpression(addr);  // one last arg
        type = oper.pop().type;
        if((type != OP) && (type != MACRO))
          return(sytaxError('Line not closed'));
        // call the OP or MACRO process
        processOpcode(cc.index());
        break;
      break;
      case COMMA:
       addr = flushExpression(addr);
       break
      case ALPHA:
      case SYSOP:
        return syntaxError('Not prime');
      break;
      default:
        while( (oper.length != 0) &&  (operLast.type > type)  )
          arg.push(oper.pop().type);
    }
    return OK;
  }
</script>

  </html>

Monday, September 25, 2023

Progressive politicians on the take

 

Busted! Adam Schiff Funneled Millions To Defense Contractors After Taking Donations


Gavin Newsom, Liz Warren, Nancy and Diane, Menendez.  All of them believe they are allowed to steal from the poor.

Sunday, September 24, 2023

Commie rats are control freaks

EXCLUSIVE: Xi Jinping's centralisation of China's economy appears to be causing a stall - something which could spell doom for the CCP, a former senior White House official told Daily Express US.


Sounds a lot like California where the teacher's union rules the ship.

Tuesday, September 5, 2023

Cannot disrespect the great color genderizor

 

Biden Allies Say It Would Be Racist For Gavin Newsom To Run In 2024


The Kamalatic, a new kitchen tool we have to try out.  It may, in fact, be illegal in California for Gavin to run this term.  I think his unions have jurisdiction in this case. and they will vote for the color/genderizor.

Wednesday, August 30, 2023

Srokes in mid conference

Mitch McConnell freezes again during a press conference

Brains in the Swamp are turning to silly putty.

Tuesday, August 8, 2023

Prolife Reubs plan to spend trillions on artificial wombs

 The GOP awakened a broad coalition to turn out to vote against their referendum designed to hinder abortion. It could be a massive problem for the party for a long time.

It is like signaling that the Dems do.  The artificial wombs are just a few years away, it is easy to abort a fetus alive.  Put those two together and the most massive miscalculation ever was letting the Supremes treat women as womb slaves. An incredible level os stupidity that sets the Repubs back for many years.

No more attacking Mickey Mouse


Florida man flounders.

Learning the difference between signaling and intending

Dem Governor Declares Emergency Over Migrants, Calls On Biden Admin For Urgent Help

She will be more careful next time.

Sunday, August 6, 2023

Friday, August 4, 2023

Two welfare bums

 

Putin is likely counting on Trump to win the 2024 election in hopes that the US will cut support to Ukraine, officials say


Always run to some government authority for mutual bailout of their central plans.

Thursday, August 3, 2023

Sorry, but the NAACP called it

‘Be Very Careful’: Chicago Mayor Brandon Johnson Defends Teen Looters From ‘Mob Action’ AllegationsBrandon Johnson defends teen looters

They are mobs of Black teenagers. 

I have come up with all sorts of round abouts avoiding the specific ethnic.  That tie is gone.  These Black Teens in the inner city are losing badly in the next layerr of information revolution.

Sunday, July 30, 2023

Witness tampering by Joe

 

DOJ Trying To Jail Star Witness Against Hunter Biden On Eve Of Congressional Testimony

We can go to school and learn to be good slaves!

Will Hurd slams DeSantis over Florida slavery curriculum: ‘Mean and hateful’

Myself? I am studying to be an internet bot.

And my tax relief

 

Democrats Propose Eliminating Student Loan Interest


Dems should always remember that the middle class gets a big tax cut along with student loan relief.

I'm all scaredy pooh





White House takes the gloves off ahead of 2024

Joe with his 'ball and chain'.  She has a smile while Joe looks all meany.  A candidate who asks permission from his politburo before he can exit the stage? The man is demented and held by strings like a puppet.

Joe hasn't died yet

Why Kamala Harris Is A Better VP Than You Think

Her best quality is that he is not president. We need to keep it that way.

Tuesday, July 25, 2023

Gun lovers are sexual deviants.

Gilgo Beach murders: Police finish search at Rex Heuermann's Long Island home

Our founding fathers wants deranged gun lovers to have weapons?  No, the founders never wanted these idiots to have guns.

Friday, July 21, 2023

The alternative is worse

Are half of all Americans really considering a third-party vote in 2024?

How does President Kamala sound?  How about Trump the Second?

Trumpsters are pretty dumb about this, but the rest of us are saying no to these two boneheads. Joe is no better and he is a walking corpse anyway.

Thursday, July 20, 2023

Mrs. Desantis dresses like a transgender

 

Ron don't like drag, how does his wife get away with it?

Send them all to Nancy Pelosi's house.

Massachusetts asks homeowners to take in illegal migrants

Nancy has been inviting migrants to Massachusetts for 30 years.  I never hear Mass voters complain.

Beach party on Cuban beaches?

 

Immediate actions to address the China-Cuba axis at America’s doorstep

When thinking about Cuba, my first reaction.
If I am a government bureaucrat and tasked with the Cuba-China problem,all my solutions would include a beach party in Cuba.  If we are not having beach parties in Cuba, then what is the point?

Tuesday, July 18, 2023

Tucker wants audience numbers not truth

Tucker Carlson Lends Credence to the Stolen-Election Story He Dismissed As a Lie

He takes a stupid pill now and then to attract Trumpsters.  RFK is doing some of the same.

Saturday, July 15, 2023

Cornel corners the Black protest vote.


The Electoral College is the big factor in a third-party nightmare for Democrats

Academic Cornel West is jockeying for the Green Party nomination.

Thursday, July 13, 2023

Whodunnit?

Officials at the White House know who handled a packet of cocaine that was found inside the Executive Mansion, and have confirmed that finding via fingerprint evidence, according to sources with direct knowledge of the investigation. “We know who handled it,” one security source said. “We’ve known since last week.”

Officials also hope the culprit is Kamala giving them a golden opportunity to cut the old 'BallnChain' 

Tuesday, July 11, 2023

Lower demand for diversity pros

 High-profile exits spark fears that Hollywood diversity pledges are just ‘PR’


The races and sexes are easier to tell apart than we thought.

Friday, July 7, 2023

The other problem? We may have already lost California to the cartels

The Biden administration is set to form a global coalition of countries to target fentanyl trafficking, but it doesn’t appear that China, a major source of the synthetic drug, will participate.

California is the center of distribution I suspect.   

Tuesday, July 4, 2023

Oh VDH dear? Your founding fathers were Franciscan monks.

Victor Davis Hanson: What The Fourth Of July Was Not

Your independence day is celebrated on Oct 4, the feast of Sr Francis.

Call me when you actually read history.

Saturday, July 1, 2023

Wednesday, June 28, 2023

Increasingly Mongol is the better term

Russia Looks Increasingly Medieval After the Coup That Wasn't

Putin'd personal army is the National Guard.  Wagner has his corporate army. And with a few other armies, the Mongolian game of chicken is on.

Monday, June 26, 2023

One of her many records

Poll: Kamala Harris sets record low for Vice President net favorability

Also the first VP appointed by a teachers union.

Quotas for whom?

 The Woke come for MLB - demand more black players


The MLB competes with the NFL for good black players.

Wednesday, June 21, 2023

Who let the bitches out?

Marjorie Taylor Greene Reportedly Called Lauren Boebert a ‘Little B*tch’ On the House Floor as Feud Escalates

Here is a real test of my censor.

More Kamala

California voters may again vote on whether to bring back affirmative action, but in limited form

My favorite leftist, in the news.

 Can You Define Leftism?

Not me.

She has on her business sit, good choice, but ditch the lip stick.  Black slacks are a good replacement for the skirt.  

She seems to be the sane one among the group. She can take that look far, then put some of her brain power to realism.

Thursday, June 15, 2023

I go with the standard: This, that, thing

Pronouns are "exhausting" 

As in: "If you want this thing then point at it."

Sunday, June 11, 2023

The problem is Scalia, and he is dead

 

Gavin Newsom Wants To 'Permanently Enshrine' Gun Control in the U.S. Constitution

If Newsom wants a rewrite all he gets is a repeat of the Second.  He has to guarantee access to public and private regulated cops.  That means he has to allow these cops a gun industry.

It was Scalia who, for some reason, went looking for an excuse to evict 'regulated militia'.  He was a dunce and thrashed the Second into a useless tautology that makes every teenage nut case NRA fool have the power of regulated militia. Look no further than Texas and that fool Abbot.

Misgendering in what direction?

California Bill Would Punish Parents For Misgendering Children

This law i a nightmare for interpretation.  We have 'don't care', girlish and boyish. And for young children, the latter two classes do not make sense.   

Then we have dress codes, who sets the code?  The standard wear in California is tennies and jeans with some kind of sweatshirt.  Do the dress cops go by shoe size?  This law is all over the map  nutty.

Thursday, June 8, 2023

Wednesday, June 7, 2023

I never minded being banned

Twitter Silences Critical Voices With Search Bans


I deserve the ban mostly as I am wrong about a lot of things, and I lie for the sake of humor, make up fake headlines. Worse, I have little expressed opinion as that ruins the art and cavalier I seem.   

Tuesday, June 6, 2023

The national dumping ground

Newsom threatens DeSantis with kidnapping charges after migrants flown to Sacramento

It is more of an unkidnapping case.  California invites them the other states send them. Maybe the better term is domestic refugees.

Friday, June 2, 2023

The governor of Arkansas is going full Banana

 

Pissed Librarians Come for Sarah Huckabee Sanders’ Kids Book Ban

Her name gives it away. She is appealing to us Kentuck Mountain grown and fed citizens, the core of all that is good and gentle in the USA.

That is her political platform, putting the US capital at risk.


Greene flips on public release of Jan. 6 tapes, claims it could ‘put the security of the Capitol at risk’


But we shouldn't forget her narrowing skull. The farther up, the less white matter.

Make teachers wear uniforms

 Parents protesting Pride Day clash with police at L.A. school where trans teacher’s flag was burned


Like hospitals.  I have no idea how adult body decorations became a subject for grammar schools.  Teachers haf free time on their own  to dress up. at the school it is strictly uniform..

What is one of the California gals pushed him down the stairs

 

Then blame it on the dog. Who's to know?

Wednesday, May 31, 2023

The malwafe is going to need blow torches

New Russian malware could bring down the US power grid

The grid is made of steel towers.

Otherwise all sorts of wierd crap causes software problms, especially when you are installing new software.  Easy to stop malwar if you first stop NSA back doors.

Monday, May 29, 2023

Regulated Militia standing their ground in Florida

At least 9 shot along Hollywood Beach boardwalk in Florida: Police

Crowded boardwalk requires lots of ground standing.

Let us see how this works with the google censor.

Transgender dummies work just fine

 

Congress prods Biden administration on female crash dummies


Put a dress on the dummies and risk a google censorship.