gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

xpos.go (5109B)


      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 // This file implements the compressed encoding of source
      6 // positions using a lookup table.
      7 
      8 package src
      9 
     10 // XPos is a more compact representation of Pos.
     11 type XPos struct {
     12 	index int32
     13 	lico
     14 }
     15 
     16 // NoXPos is a valid unknown position.
     17 var NoXPos XPos
     18 
     19 // IsKnown reports whether the position p is known.
     20 // XPos.IsKnown() matches Pos.IsKnown() for corresponding
     21 // positions.
     22 func (p XPos) IsKnown() bool {
     23 	return p.index != 0 || p.Line() != 0
     24 }
     25 
     26 // Before reports whether the position p comes before q in the source.
     27 // For positions with different bases, ordering is by base index.
     28 func (p XPos) Before(q XPos) bool {
     29 	n, m := p.index, q.index
     30 	return n < m || n == m && p.lico < q.lico
     31 }
     32 
     33 // SameFile reports whether p and q are positions in the same file.
     34 func (p XPos) SameFile(q XPos) bool {
     35 	return p.index == q.index
     36 }
     37 
     38 // SameFileAndLine reports whether p and q are positions on the same line in the same file.
     39 func (p XPos) SameFileAndLine(q XPos) bool {
     40 	return p.index == q.index && p.lico.SameLine(q.lico)
     41 }
     42 
     43 // After reports whether the position p comes after q in the source.
     44 // For positions with different bases, ordering is by base index.
     45 func (p XPos) After(q XPos) bool {
     46 	n, m := p.index, q.index
     47 	return n > m || n == m && p.lico > q.lico
     48 }
     49 
     50 // WithNotStmt returns the same location to be marked with DWARF is_stmt=0
     51 func (p XPos) WithNotStmt() XPos {
     52 	p.lico = p.lico.withNotStmt()
     53 	return p
     54 }
     55 
     56 // WithDefaultStmt returns the same location with undetermined is_stmt
     57 func (p XPos) WithDefaultStmt() XPos {
     58 	p.lico = p.lico.withDefaultStmt()
     59 	return p
     60 }
     61 
     62 // WithIsStmt returns the same location to be marked with DWARF is_stmt=1
     63 func (p XPos) WithIsStmt() XPos {
     64 	p.lico = p.lico.withIsStmt()
     65 	return p
     66 }
     67 
     68 // WithBogusLine returns a bogus line that won't match any recorded for the source code.
     69 // Its use is to disrupt the statements within an infinite loop so that the debugger
     70 // will not itself loop infinitely waiting for the line number to change.
     71 // gdb chooses not to display the bogus line; delve shows it with a complaint, but the
     72 // alternative behavior is to hang.
     73 func (p XPos) WithBogusLine() XPos {
     74 	if p.index == 0 {
     75 		// See #35652
     76 		panic("Assigning a bogus line to XPos with no file will cause mysterious downstream failures.")
     77 	}
     78 	p.lico = makeBogusLico()
     79 	return p
     80 }
     81 
     82 // WithXlogue returns the same location but marked with DWARF function prologue/epilogue
     83 func (p XPos) WithXlogue(x PosXlogue) XPos {
     84 	p.lico = p.lico.withXlogue(x)
     85 	return p
     86 }
     87 
     88 // LineNumber returns a string for the line number, "?" if it is not known.
     89 func (p XPos) LineNumber() string {
     90 	if !p.IsKnown() {
     91 		return "?"
     92 	}
     93 	return p.lico.lineNumber()
     94 }
     95 
     96 // FileIndex returns a smallish non-negative integer corresponding to the
     97 // file for this source position.  Smallish is relative; it can be thousands
     98 // large, but not millions.
     99 func (p XPos) FileIndex() int32 {
    100 	return p.index
    101 }
    102 
    103 func (p XPos) LineNumberHTML() string {
    104 	if !p.IsKnown() {
    105 		return "?"
    106 	}
    107 	return p.lico.lineNumberHTML()
    108 }
    109 
    110 // AtColumn1 returns the same location but shifted to column 1.
    111 func (p XPos) AtColumn1() XPos {
    112 	p.lico = p.lico.atColumn1()
    113 	return p
    114 }
    115 
    116 // A PosTable tracks Pos -> XPos conversions and vice versa.
    117 // Its zero value is a ready-to-use PosTable.
    118 type PosTable struct {
    119 	baseList []*PosBase
    120 	indexMap map[*PosBase]int
    121 	nameMap  map[string]int // Maps file symbol name to index for debug information.
    122 }
    123 
    124 // XPos returns the corresponding XPos for the given pos,
    125 // adding pos to t if necessary.
    126 func (t *PosTable) XPos(pos Pos) XPos {
    127 	m := t.indexMap
    128 	if m == nil {
    129 		// Create new list and map and populate with nil
    130 		// base so that NoPos always gets index 0.
    131 		t.baseList = append(t.baseList, nil)
    132 		m = map[*PosBase]int{nil: 0}
    133 		t.indexMap = m
    134 		t.nameMap = make(map[string]int)
    135 	}
    136 	i, ok := m[pos.base]
    137 	if !ok {
    138 		i = len(t.baseList)
    139 		t.baseList = append(t.baseList, pos.base)
    140 		t.indexMap[pos.base] = i
    141 		if _, ok := t.nameMap[pos.base.symFilename]; !ok {
    142 			t.nameMap[pos.base.symFilename] = len(t.nameMap)
    143 		}
    144 	}
    145 	return XPos{int32(i), pos.lico}
    146 }
    147 
    148 // Pos returns the corresponding Pos for the given p.
    149 // If p cannot be translated via t, the function panics.
    150 func (t *PosTable) Pos(p XPos) Pos {
    151 	var base *PosBase
    152 	if p.index != 0 {
    153 		base = t.baseList[p.index]
    154 	}
    155 	return Pos{base, p.lico}
    156 }
    157 
    158 // FileIndex returns the index of the given filename(symbol) in the PosTable, or -1 if not found.
    159 func (t *PosTable) FileIndex(filename string) int {
    160 	if v, ok := t.nameMap[filename]; ok {
    161 		return v
    162 	}
    163 	return -1
    164 }
    165 
    166 // FileTable returns a slice of all files used to build this package.
    167 func (t *PosTable) FileTable() []string {
    168 	// Create a LUT of the global package level file indices. This table is what
    169 	// is written in the debug_lines header, the file[N] will be referenced as
    170 	// N+1 in the debug_lines table.
    171 	fileLUT := make([]string, len(t.nameMap))
    172 	for str, i := range t.nameMap {
    173 		fileLUT[i] = str
    174 	}
    175 	return fileLUT
    176 }