github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/compile/internal/gc/lex.go (about) 1 // Copyright 2009 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 package gc 6 7 import ( 8 "cmd/compile/internal/syntax" 9 "cmd/internal/objabi" 10 "cmd/internal/src" 11 "fmt" 12 "strings" 13 ) 14 15 // lineno is the source position at the start of the most recently lexed token. 16 // TODO(gri) rename and eventually remove 17 var lineno src.XPos 18 19 func makePos(base *src.PosBase, line, col uint) src.XPos { 20 return Ctxt.PosTable.XPos(src.MakePos(base, line, col)) 21 } 22 23 func isSpace(c rune) bool { 24 return c == ' ' || c == '\t' || c == '\n' || c == '\r' 25 } 26 27 func isQuoted(s string) bool { 28 return len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' 29 } 30 31 const ( 32 // Func pragmas. 33 Nointerface syntax.Pragma = 1 << iota 34 Noescape // func parameters don't escape 35 Norace // func must not have race detector annotations 36 Nosplit // func should not execute on separate stack 37 Noinline // func should not be inlined 38 CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all 39 UintptrEscapes // pointers converted to uintptr escape 40 41 // Runtime-only func pragmas. 42 // See ../../../../runtime/README.md for detailed descriptions. 43 Systemstack // func must run on system stack 44 Nowritebarrier // emit compiler error instead of write barrier 45 Nowritebarrierrec // error on write barrier in this or recursive callees 46 Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees 47 48 // Runtime-only type pragmas 49 NotInHeap // values of this type must not be heap allocated 50 ) 51 52 func pragmaValue(verb string) syntax.Pragma { 53 switch verb { 54 case "go:nointerface": 55 if objabi.Fieldtrack_enabled != 0 { 56 return Nointerface 57 } 58 case "go:noescape": 59 return Noescape 60 case "go:norace": 61 return Norace 62 case "go:nosplit": 63 return Nosplit 64 case "go:noinline": 65 return Noinline 66 case "go:systemstack": 67 return Systemstack 68 case "go:nowritebarrier": 69 return Nowritebarrier 70 case "go:nowritebarrierrec": 71 return Nowritebarrierrec | Nowritebarrier // implies Nowritebarrier 72 case "go:yeswritebarrierrec": 73 return Yeswritebarrierrec 74 case "go:cgo_unsafe_args": 75 return CgoUnsafeArgs 76 case "go:uintptrescapes": 77 // For the next function declared in the file 78 // any uintptr arguments may be pointer values 79 // converted to uintptr. This directive 80 // ensures that the referenced allocated 81 // object, if any, is retained and not moved 82 // until the call completes, even though from 83 // the types alone it would appear that the 84 // object is no longer needed during the 85 // call. The conversion to uintptr must appear 86 // in the argument list. 87 // Used in syscall/dll_windows.go. 88 return UintptrEscapes 89 case "go:notinheap": 90 return NotInHeap 91 } 92 return 0 93 } 94 95 // pragcgo is called concurrently if files are parsed concurrently. 96 func (p *noder) pragcgo(pos syntax.Pos, text string) { 97 f := pragmaFields(text) 98 99 verb := strings.TrimPrefix(f[0], "go:") 100 f[0] = verb 101 102 switch verb { 103 case "cgo_export_static", "cgo_export_dynamic": 104 switch { 105 case len(f) == 2 && !isQuoted(f[1]): 106 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]): 107 default: 108 p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf(`usage: //go:%s local [remote]`, verb)}) 109 return 110 } 111 case "cgo_import_dynamic": 112 switch { 113 case len(f) == 2 && !isQuoted(f[1]): 114 case len(f) == 3 && !isQuoted(f[1]) && !isQuoted(f[2]): 115 case len(f) == 4 && !isQuoted(f[1]) && !isQuoted(f[2]) && isQuoted(f[3]): 116 f[3] = strings.Trim(f[3], `"`) 117 if objabi.GOOS == "aix" && f[3] != "" { 118 // On Aix, library pattern must be "lib.a/object.o" 119 n := strings.Split(f[3], "/") 120 if len(n) != 2 || !strings.HasSuffix(n[0], ".a") || !strings.HasSuffix(n[1], ".o") { 121 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["lib.a/object.o"]]`}) 122 return 123 } 124 } 125 default: 126 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_dynamic local [remote ["library"]]`}) 127 return 128 } 129 case "cgo_import_static": 130 switch { 131 case len(f) == 2 && !isQuoted(f[1]): 132 default: 133 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_import_static local`}) 134 return 135 } 136 case "cgo_dynamic_linker": 137 switch { 138 case len(f) == 2 && isQuoted(f[1]): 139 f[1] = strings.Trim(f[1], `"`) 140 default: 141 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_dynamic_linker "path"`}) 142 return 143 } 144 case "cgo_ldflag": 145 switch { 146 case len(f) == 2 && isQuoted(f[1]): 147 f[1] = strings.Trim(f[1], `"`) 148 default: 149 p.error(syntax.Error{Pos: pos, Msg: `usage: //go:cgo_ldflag "arg"`}) 150 return 151 } 152 default: 153 return 154 } 155 p.pragcgobuf = append(p.pragcgobuf, f) 156 } 157 158 // pragmaFields is similar to strings.FieldsFunc(s, isSpace) 159 // but does not split when inside double quoted regions and always 160 // splits before the start and after the end of a double quoted region. 161 // pragmaFields does not recognize escaped quotes. If a quote in s is not 162 // closed the part after the opening quote will not be returned as a field. 163 func pragmaFields(s string) []string { 164 var a []string 165 inQuote := false 166 fieldStart := -1 // Set to -1 when looking for start of field. 167 for i, c := range s { 168 switch { 169 case c == '"': 170 if inQuote { 171 inQuote = false 172 a = append(a, s[fieldStart:i+1]) 173 fieldStart = -1 174 } else { 175 inQuote = true 176 if fieldStart >= 0 { 177 a = append(a, s[fieldStart:i]) 178 } 179 fieldStart = i 180 } 181 case !inQuote && isSpace(c): 182 if fieldStart >= 0 { 183 a = append(a, s[fieldStart:i]) 184 fieldStart = -1 185 } 186 default: 187 if fieldStart == -1 { 188 fieldStart = i 189 } 190 } 191 } 192 if !inQuote && fieldStart >= 0 { // Last field might end at the end of the string. 193 a = append(a, s[fieldStart:]) 194 } 195 return a 196 }