text: # Copyright 2012 Jeff Trawick, http://emptyhammock.com/
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     http://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  #
  
  import re
  
  from stacktraces.native import collect
  import stacktraces.process_model
  
  
  class Pstack:
  
      def __init__(self, **kwargs):
          self.corefile = kwargs.get('corefile')
          self.exe = kwargs.get('exe')
          self.hdr = None
          self.pstackout = kwargs.get('debuglog')
          self.proc = kwargs.get('proc')
          if not self.proc:
              self.proc = stacktraces.process_model.Process()
          self.pid = self.proc.get_pid()
  
      def parse(self):
          if not self.pstackout:
              self.get_output()
          thr = None
          if collect.is_hdr(self.pstackout[0]):
              self.hdr = self.pstackout[0]
              self.pstackout = self.pstackout[1:]
          if 'REM /usr/bin/pstack' in self.pstackout[0]:
              self.pstackout = self.pstackout[1:]
          m = re.search('^(\d+):[ \t]+(/[^ ]+)', self.pstackout[0])
          if m:
              self.pid = m.group(1)
              self.exe = m.group(2)
          else:
              m = re.search('^core +.* of (\d+):[ \t]+([^ ]+)', self.pstackout[0])
              if not m:
                  raise Exception('could not parse >%s<' % self.pstackout[0])
              self.pid = m.group(1)
              self.exe = m.group(2)
          frameno = -1
          for l in self.pstackout[1:]:
              if 'REM ' in l and l[0:3] == 'REM ':
                  break
              m = re.search('^-+ +lwp# +\d+ +/ +thread# +(\d+) +', l)
              if m:
                  thr = stacktraces.process_model.Thread(m.group(1))
                  self.proc.add_thread(thr)
                  frameno = 0
                  continue
              m = re.search('^ +([\da-f]+) +([^ ]+) +(\([^)]*\))', l)
              if m:
                  # addr = m.group(1)
                  fn = m.group(2)
                  fnargs = m.group(3)
                  assert frameno >= 0  # i.e., frameno found
                  frameno += 1
                  fr = stacktraces.process_model.Frame(frameno, fn, fnargs)
                  thr.add_frame(fr)
                  continue
              m = re.search('^ +([\da-f]+) +([^ ]+) *(\([^)]*\)), exit value =', l)
              if m:
                  thr.set_exited()
          if self.pid and not self.proc.pid:
              self.proc.pid = self.pid
          if self.exe and not self.proc.exe:
              self.proc.exe = self.exe
  
      def get_output(self):
          self.pstackout = collect.pstack_collect(None, self.pid, self.corefile)
  