This method is used to submit any SAS code. It returns the Log and Listing as a python dictionary.
      code    - the SAS statements you want to execute
      results - format of results, HTML is default, TEXT is the alternative
      prompt  - dict of names:flags to prompt for; create macro variables (used in submitted code), then keep or delete
                The keys are the names of the macro variables and the boolean flag is to either hide what you type and delete
                the macros, or show what you type and keep the macros (they will still be available later)
                for example (what you type for pw will not be displayed, user and dsname will):

                results = sas.submit(
                   """
                   libname tera teradata server=teracop1 user=&user pw=&pw;
                   proc print data=tera.&dsname (obs=10); run;
                   """ ,
                   prompt = {'user': False, 'pw': True, 'dsname': False}
                   )

      Returns - a Dict containing two keys:values, [LOG, LST]. LOG is text and LST is 'results' (HTML or TEXT)

      NOTE: to view HTML results in the ipykernel, issue: from IPython.display import HTML  and use HTML() instead of print()
      i.e,: results = sas.submit("data a; x=1; run; proc print;run')
            print(results['LOG'])
            HTML(results['LST'])

def submit(self, code: str, results: str ="html", prompt: dict = None) -> dict:
      '''
      This method is used to submit any SAS code. It returns the Log and Listing as a python dictionary.
      code    - the SAS statements you want to execute
      results - format of results, HTML is default, TEXT is the alternative
      prompt  - dict of names:flags to prompt for; create macro variables (used in submitted code), then keep or delete
                The keys are the names of the macro variables and the boolean flag is to either hide what you type and delete
                the macros, or show what you type and keep the macros (they will still be available later)
                for example (what you type for pw will not be displayed, user and dsname will):

                results = sas.submit(
                   """
                   libname tera teradata server=teracop1 user=&user pw=&pw;
                   proc print data=tera.&dsname (obs=10); run;
                   """ ,
                   prompt = {'user': False, 'pw': True, 'dsname': False}
                   )

      Returns - a Dict containing two keys:values, [LOG, LST]. LOG is text and LST is 'results' (HTML or TEXT)

      NOTE: to view HTML results in the ipykernel, issue: from IPython.display import HTML  and use HTML() instead of print()
      i.e,: results = sas.submit("data a; x=1; run; proc print;run')
            print(results['LOG'])
            HTML(results['LST'])
      '''
      prompt = prompt if prompt is not None else {}

      #odsopen  = b"ods listing close;ods html5 (id=saspy_internal) file=STDOUT options(bitmap_mode='inline') device=svg; ods graphics on / outputfmt=png;\n"
      odsopen  = b"ods listing close;ods "+self.sascfg.output.encode()+ \
                 b" (id=saspy_internal) file="+self._tomods1+b" options(bitmap_mode='inline') device=svg style="+self._sb.HTML_Style.encode()+ \
                 b"; ods graphics on / outputfmt=png;\n"
      odsclose = b"ods "+self.sascfg.output.encode()+b" (id=saspy_internal) close;ods listing;\n"
      ods      = True;
      mj       = b";*\';*\";*/;"
      lstf     = b''
      logf     = b''
      bail     = False
      eof      = 5
      bc       = False
      done     = False
      logn     = self._logcnt()
      logcodei = "%put E3969440A681A24088859985" + logn + ";"
      logcodeo = b"\nE3969440A681A24088859985" + logn.encode()
      pcodei   = ''
      pcodeiv  = ''
      pcodeo   = ''
      pgm      = b''

      if self.pid == None:
         self._sb.SASpid = None
         print("No SAS process attached. SAS process has terminated unexpectedly.")
         return dict(LOG="No SAS process attached. SAS process has terminated unexpectedly.", LST='')

      if os.name == 'nt':
         try:
            rc = self.pid.wait(0)
            self.pid = None
            self._sb.SASpid = None
            return dict(LOG='SAS process has terminated unexpectedly. RC from wait was: '+str(rc), LST='')
         except:
            pass
      else:
         if self.pid == None:
            self._sb.SASpid = None
            return "No SAS process attached. SAS process has terminated unexpectedly."
         #rc = os.waitid(os.P_PID, self.pid, os.WEXITED | os.WNOHANG)
         rc = os.waitpid(self.pid, os.WNOHANG)
         #if rc != None:
         if rc[1]:
            self.pid = None
            self._sb.SASpid = None
            return dict(LOG='SAS process has terminated unexpectedly. Pid State= '+str(rc), LST='')

      # to cover the possibility of an _asubmit w/ lst output not read; no known cases now; used to be __flushlst__()
      # removing this and adding comment in _asubmit to use _getlst[txt] so this will never be necessary; delete later
      #while(len(self.stdout.read1(4096)) > 0):
      #   continue

      if results.upper() != "HTML":
         ods = False

      if len(prompt):
         pcodei += 'options nosource nonotes;\n'
         pcodeo += 'options nosource nonotes;\n'
         for key in prompt:
            gotit = False
            while not gotit:
               var = self.sascfg._prompt('Please enter value for macro variable '+key+' ', pw=prompt[key])
               if var is None:
                  raise KeyboardInterrupt
               if len(var) > 0:
                  gotit = True
               else:
                  print("Sorry, didn't get a value for that variable.")
            if prompt[key]:
               pcodei += '%let '+key+'='+var+';\n'
               pcodeo += '%symdel '+key+';\n'
            else:
               pcodeiv += '%let '+key+'='+var+';\n'
         pcodei += 'options source notes;\n'
         pcodeo += 'options source notes;\n'

      if ods:
         pgm += odsopen

      pgm += mj+b'\n'+pcodei.encode()+pcodeiv.encode()
      pgm += code.encode()+b'\n'+pcodeo.encode()+b'\n'+mj

      if ods:
         pgm += odsclose

      pgm += b'\n'+logcodei.encode()+b'\n'
      self.stdin[0].send(pgm+b'tom says EOL='+logcodeo+b'\n')

      while not done:
         try:
             while True:
                 if os.name == 'nt':
                    try:
                       rc = self.pid.wait(0)
                       self.pid = None
                       self._sb.SASpid = None
                       log = logf.partition(logcodeo)[0]+b'\nSAS process has terminated unexpectedly. RC from wait was: '+str(rc).encode()
                       return dict(LOG=log.decode(errors='replace'), LST='')
                    except:
                       pass
                 else:
                    #rc = os.waitid(os.P_PID, self.pid, os.WEXITED | os.WNOHANG)
                    rc = os.waitpid(self.pid, os.WNOHANG)
                    #if rc is not None:
                    if rc[1]:
                       self.pid = None
                       self._sb.SASpid = None
                       log = logf.partition(logcodeo)[0]+b'\nSAS process has terminated unexpectedly. Pid State= '+str(rc).encode()
                       return dict(LOG=log.decode(errors='replace'), LST='')

                 if bail:
                    if lstf.count(logcodeo) >= 1:
                       x = lstf.rsplit(logcodeo)
                       lstf = x[0]
                       if len(x[1]) > 7 and b"_tomods" in x[1]:
                          self._tomods1 = x[1]
                          #print("Tomods is now "+ self._tomods1.decode())
                       break
                 try:
                    lst = self.stdout[0].recv(4096)
                 except (BlockingIOError):
                    lst = b''

                 if len(lst) > 0:
                    #print("LIST = \n"+lst)
                    lstf += lst
                 else:
                    sleep(0.1)
                    try:
                       log = self.stderr[0].recv(4096)
                    except (BlockingIOError):
                       log = b''

                    if len(log) > 0:
                       #print("LOG = \n"+log)
                       logf += log
                       if logf.count(logcodeo) >= 1:
                          bail = True
                       if not bail and bc:
                          self.stdin[0].send(odsclose+logcodei.encode()+b'tom says EOL='+logcodeo+b'\n')
                          bc = False
             done = True

         except (ConnectionResetError):
             rc = 0
             if os.name == 'nt':
                try:
                   rc = self.pid.wait()
                except:
                   pass
             else:
                rc = os.waitpid(self.pid, 0)

             self.pid = None
             self._sb.SASpid = None
             log =logf.partition(logcodeo)[0]+b'\nConnection Reset: SAS process has terminated unexpectedly. Pid State= '+str(rc).encode()
             return dict(LOG=log.decode(errors='replace'), LST='')

         except (KeyboardInterrupt, SystemExit):
             print('Exception caught!')
             ll = self._breakprompt(logcodeo)

             if ll.get('ABORT', False):
                return ll

             logf += ll['LOG']
             lstf += ll['LST']
             bc    = ll['BC']

             if not bc:
                print('Exception handled :)\n')
             else:
                print('Exception ignored, continuing to process...\n')

             self.stdin[0].send(odsclose+logcodei.encode()+b'tom says EOL='+logcodeo+b'\n')

      try:
         lstf = lstf.decode()
      except UnicodeDecodeError:
         try:
            lstf = lstf.decode(self.sascfg.encoding)
         except UnicodeDecodeError:
            lstf = lstf.decode(errors='replace')

      logf = logf.decode(errors='replace')

      trip = lstf.rpartition("/*]]>*/")
      if len(trip[1]) > 0 and len(trip[2]) < 100:
         lstf = ''

      self._log += logf
      final = logf.partition(logcodei)
      z = final[0].rpartition(chr(10))
      prev = '%08d' %  (self._log_cnt - 1)
      zz = z[0].rpartition("\nE3969440A681A24088859985" + prev +'\n')
      logd = zz[2].replace(mj.decode(), '')

      lstd = lstf.replace(chr(12), chr(10)).replace('<body class="c body">',
                                                    '<body class="l body">').replace("font-size: x-small;",
                                                                                     "font-size:  normal;")
      return dict(LOG=logd, LST=lstd)