package llvm import "strings" const ( // decimal specifies the decimal digit characters. decimal = "0123456789" // upper specifies the uppercase letters. upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" // lower specifies the lowercase letters. lower = "abcdefghijklmnopqrstuvwxyz" // alpha specifies the alphabetic characters. alpha = upper + lower // head is the set of valid characters for the first character of an // identifier. head = alpha + "$-._" // tail is the set of valid characters for the remaining characters of an // identifier (i.e. all characters in the identifier except the first). All // characters of a label may be from the tail set, even the first character. tail = head + decimal // quotedIdent is the set of valid characters in quoted identifiers, which // excludes ASCII control characters, double quote, backslash and extended // ASCII characters. quotedIdent = " !#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_`abcdefghijklmnopqrstuvwxyz{|}~" ) func EscapeIdent (s string) string { replace := false extra := 0 for i := 0; i < len(s); i++ { if strings.IndexByte(tail, s[i]) == -1 { // Check if a replacement is required. // // Note, there are characters which are not valid in an identifier // (e.g. '#') but are valid in a quoted identifier, and therefore // require a replacement (i.e. quoted identifier), but no extra // characters for the escape sequence. replace = true } if strings.IndexByte(quotedIdent, s[i]) == -1 { // Two extra bytes are required for each byte not valid in a quoted // identifier; e.g. // // "\t" -> `\09` // "世" -> `\E4\B8\96` extra += 2 } } if !replace { return s } // Replace invalid characters. const hextable = "0123456789ABCDEF" buf := make([]byte, len(s)+extra) j := 0 for i := 0; i < len(s); i++ { b := s[i] if strings.IndexByte(quotedIdent, b) != -1 { buf[j] = b j++ continue } buf[j] = '\\' buf[j+1] = hextable[b>>4] buf[j+2] = hextable[b&0x0F] j += 3 } // Add surrounding quotes. return `"` + string(buf) + `"` } func Escape (s []byte, valid func(b byte) bool) string { // Check if a replacement is required. extra := 0 for i := 0; i < len(s); i++ { if !valid(s[i]) { // Two extra bytes are required for each invalid byte; e.g. // "#" -> `\23` // "世" -> `\E4\B8\96` extra += 2 } } if extra == 0 { return string(s) } // Replace invalid characters. const hextable = "0123456789ABCDEF" buf := make([]byte, len(s)+extra) j := 0 for i := 0; i < len(s); i++ { b := s[i] if valid(b) { buf[j] = b j++ continue } buf[j] = '\\' buf[j+1] = hextable[b>>4] buf[j+2] = hextable[b&0x0F] j += 3 } return string(buf) } func EscapeString (s []byte) string { valid := func(b byte) bool { return ' ' <= b && b <= '~' && b != '"' && b != '\\' } return string(Escape(s, valid)) } func EncodeTypeName (name string) string { return "%" + EscapeIdent(name) } func EncodeRegisterName (name string) string { return "%" + EscapeIdent(name) } func EncodeGlobalName (name string) string { return "@" + EscapeIdent(name) } func EncodeFunctionName (name string) string { return EncodeGlobalName(name) } func EncodeLabelName (name string) string { return EscapeIdent(name) + ":" } func EscapeQuoteString (s []byte) string { return `"` + string(EscapeString(s)) + `"` }