fixing bugs related mostly to extension handling
This commit is contained in:
		@@ -282,7 +282,7 @@ func (e *FieldRef) String() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *FieldRef) Initialize(p *Protocol) {
 | 
			
		||||
	e.Name = SrcName(e.Name)
 | 
			
		||||
	e.Name = SrcName(p, e.Name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type EnumRef struct {
 | 
			
		||||
@@ -309,7 +309,7 @@ func (e *EnumRef) String() string {
 | 
			
		||||
 | 
			
		||||
func (e *EnumRef) Initialize(p *Protocol) {
 | 
			
		||||
	e.EnumKind = e.EnumKind.(*Translation).RealType(p)
 | 
			
		||||
	e.EnumItem = SrcName(e.EnumItem)
 | 
			
		||||
	e.EnumItem = SrcName(p, e.EnumItem)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SumOf struct {
 | 
			
		||||
@@ -337,5 +337,5 @@ func (e *SumOf) String() string {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (e *SumOf) Initialize(p *Protocol) {
 | 
			
		||||
	e.Name = SrcName(e.Name)
 | 
			
		||||
	e.Name = SrcName(p, e.Name)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ type SingleField struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *SingleField) Initialize(p *Protocol) {
 | 
			
		||||
	f.srcName = SrcName(f.XmlName())
 | 
			
		||||
	f.srcName = SrcName(p, f.XmlName())
 | 
			
		||||
	f.Type = f.Type.(*Translation).RealType(p)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -138,7 +138,7 @@ func (f *ListField) Size() Size {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *ListField) Initialize(p *Protocol) {
 | 
			
		||||
	f.srcName = SrcName(f.XmlName())
 | 
			
		||||
	f.srcName = SrcName(p, f.XmlName())
 | 
			
		||||
	f.Type = f.Type.(*Translation).RealType(p)
 | 
			
		||||
	if f.LengthExpr != nil {
 | 
			
		||||
		f.LengthExpr.Initialize(p)
 | 
			
		||||
@@ -173,7 +173,7 @@ func (f *ExprField) Size() Size {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *ExprField) Initialize(p *Protocol) {
 | 
			
		||||
	f.srcName = SrcName(f.XmlName())
 | 
			
		||||
	f.srcName = SrcName(p, f.XmlName())
 | 
			
		||||
	f.Type = f.Type.(*Translation).RealType(p)
 | 
			
		||||
	f.Expr.Initialize(p)
 | 
			
		||||
}
 | 
			
		||||
@@ -230,8 +230,8 @@ func (f *ValueField) ListLength() Size {
 | 
			
		||||
 | 
			
		||||
func (f *ValueField) Initialize(p *Protocol) {
 | 
			
		||||
	f.MaskType = f.MaskType.(*Translation).RealType(p)
 | 
			
		||||
	f.MaskName = SrcName(f.MaskName)
 | 
			
		||||
	f.ListName = SrcName(f.ListName)
 | 
			
		||||
	f.MaskName = SrcName(p, f.MaskName)
 | 
			
		||||
	f.ListName = SrcName(p, f.ListName)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type SwitchField struct {
 | 
			
		||||
@@ -260,7 +260,7 @@ func (f *SwitchField) Size() Size {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (f *SwitchField) Initialize(p *Protocol) {
 | 
			
		||||
	f.Name = SrcName(f.Name)
 | 
			
		||||
	f.Name = SrcName(p, f.Name)
 | 
			
		||||
	f.Expr.Initialize(p)
 | 
			
		||||
	for _, bitcase := range f.Bitcases {
 | 
			
		||||
		bitcase.Expr.Initialize(p)
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,8 @@ var NameMap = map[string]string{}
 | 
			
		||||
 | 
			
		||||
// Base types
 | 
			
		||||
func (b *Base) Define(c *Context) {
 | 
			
		||||
	c.Putln("// Skipping definition for base type '%s'", SrcName(b.XmlName()))
 | 
			
		||||
	c.Putln("// Skipping definition for base type '%s'",
 | 
			
		||||
		SrcName(c.protocol, b.XmlName()))
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -81,7 +82,8 @@ func (enum *Enum) Define(c *Context) {
 | 
			
		||||
 | 
			
		||||
// Resource types
 | 
			
		||||
func (res *Resource) Define(c *Context) {
 | 
			
		||||
	c.Putln("// Skipping resource definition of '%s'", SrcName(res.XmlName()))
 | 
			
		||||
	c.Putln("// Skipping resource definition of '%s'",
 | 
			
		||||
		SrcName(c.protocol, res.XmlName()))
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,11 +64,15 @@ func (e *Error) ImplementsError(c *Context) {
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("func (err %s) BadId() Id {", e.ErrType())
 | 
			
		||||
	c.Putln("return Id(err.BadValue)")
 | 
			
		||||
	if c.protocol.Name == "xproto" {
 | 
			
		||||
		c.Putln("return Id(err.BadValue)")
 | 
			
		||||
	} else {
 | 
			
		||||
		c.Putln("return 0")
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("func (err %s) Error() string {", e.ErrType())
 | 
			
		||||
	FieldString(c, e.Fields, e.ErrConst())
 | 
			
		||||
	ErrorFieldString(c, e.Fields, e.ErrConst())
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
}
 | 
			
		||||
@@ -119,14 +123,14 @@ func (e *ErrorCopy) ImplementsError(c *Context) {
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("func (err %s) Error() string {", e.ErrType())
 | 
			
		||||
	FieldString(c, e.Old.(*Error).Fields, e.ErrConst())
 | 
			
		||||
	ErrorFieldString(c, e.Old.(*Error).Fields, e.ErrConst())
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// FieldString works for both Error and ErrorCopy. It assembles all of the
 | 
			
		||||
// ErrorFieldString works for both Error and ErrorCopy. It assembles all of the
 | 
			
		||||
// fields in an error and formats them into a single string.
 | 
			
		||||
func FieldString(c *Context, fields []Field, errName string) {
 | 
			
		||||
func ErrorFieldString(c *Context, fields []Field, errName string) {
 | 
			
		||||
	c.Putln("fieldVals := make([]string, 0, %d)", len(fields))
 | 
			
		||||
	c.Putln("fieldVals = append(fieldVals, \"NiceName: \" + err.NiceName)")
 | 
			
		||||
	c.Putln("fieldVals = append(fieldVals, " +
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,9 @@
 | 
			
		||||
package main
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Event types
 | 
			
		||||
func (e *Event) Define(c *Context) {
 | 
			
		||||
	c.Putln("// Event definition %s (%d)", e.SrcName(), e.Number)
 | 
			
		||||
@@ -36,6 +40,10 @@ func (e *Event) Define(c *Context) {
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("func (v %s) String() string {", e.EvType())
 | 
			
		||||
	EventFieldString(c, e.Fields, e.SrcName())
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
 | 
			
		||||
	// Let's the XGB event loop read this event.
 | 
			
		||||
	c.Putln("func init() {")
 | 
			
		||||
@@ -115,6 +123,10 @@ func (e *EventCopy) Define(c *Context) {
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("func (v %s) String() string {", e.EvType())
 | 
			
		||||
	EventFieldString(c, e.Old.(*Event).Fields, e.SrcName())
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
 | 
			
		||||
	// Let's the XGB event loop read this event.
 | 
			
		||||
	c.Putln("func init() {")
 | 
			
		||||
@@ -137,3 +149,42 @@ func (e *EventCopy) Write(c *Context) {
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// EventFieldString works for both Event and EventCopy. It assembles all of the
 | 
			
		||||
// fields in an event and formats them into a single string.
 | 
			
		||||
func EventFieldString(c *Context, fields []Field, evName string) {
 | 
			
		||||
	c.Putln("fieldVals := make([]string, 0, %d)", len(fields))
 | 
			
		||||
	if evName != "KeymapNotify" {
 | 
			
		||||
		c.Putln("fieldVals = append(fieldVals, " +
 | 
			
		||||
			"sprintf(\"Sequence: %s\", v.Sequence))", "%d")
 | 
			
		||||
	}
 | 
			
		||||
	for _, field := range fields {
 | 
			
		||||
		switch f := field.(type) {
 | 
			
		||||
		case *PadField:
 | 
			
		||||
			continue
 | 
			
		||||
		case *SingleField:
 | 
			
		||||
			switch f.Type.(type) {
 | 
			
		||||
			case *Base:
 | 
			
		||||
			case *Resource:
 | 
			
		||||
			case *TypeDef:
 | 
			
		||||
			default: continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch field.SrcType() {
 | 
			
		||||
			case "string":
 | 
			
		||||
				format := fmt.Sprintf("sprintf(\"%s: %s\", v.%s)",
 | 
			
		||||
					field.SrcName(), "%s", field.SrcName())
 | 
			
		||||
				c.Putln("fieldVals = append(fieldVals, %s)", format)
 | 
			
		||||
			case "bool":
 | 
			
		||||
				format := fmt.Sprintf("sprintf(\"%s: %s\", v.%s)",
 | 
			
		||||
					field.SrcName(), "%t", field.SrcName())
 | 
			
		||||
				c.Putln("fieldVals = append(fieldVals, %s)", format)
 | 
			
		||||
			default:
 | 
			
		||||
				format := fmt.Sprintf("sprintf(\"%s: %s\", v.%s)",
 | 
			
		||||
					field.SrcName(), "%d", field.SrcName())
 | 
			
		||||
				c.Putln("fieldVals = append(fieldVals, %s)", format)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("return \"%s {\" + stringsJoin(fieldVals, \", \") + \"}\"", evName)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -8,21 +8,24 @@ import (
 | 
			
		||||
func (r *Request) Define(c *Context) {
 | 
			
		||||
	c.Putln("// Request %s", r.SrcName())
 | 
			
		||||
	c.Putln("// size: %s", r.Size(c))
 | 
			
		||||
	c.Putln("type %s cookie", r.CookieName())
 | 
			
		||||
	c.Putln("type %s struct {", r.CookieName())
 | 
			
		||||
	c.Putln("*cookie")
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	if r.Reply != nil {
 | 
			
		||||
		c.Putln("func (c *Conn) %s(%s) %s {",
 | 
			
		||||
			r.SrcName(), r.ParamNameTypes(), r.CookieName())
 | 
			
		||||
		c.Putln("cookie := c.newCookie(true, true)")
 | 
			
		||||
		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s(cookie)", r.CookieName())
 | 
			
		||||
		c.Putln("c.newRequest(c.%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s{cookie}", r.CookieName())
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
 | 
			
		||||
		c.Putln("func (c *Conn) %sUnchecked(%s) %s {",
 | 
			
		||||
			r.SrcName(), r.ParamNameTypes(), r.CookieName())
 | 
			
		||||
		c.Putln("cookie := c.newCookie(false, true)")
 | 
			
		||||
		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s(cookie)", r.CookieName())
 | 
			
		||||
		c.Putln("c.newRequest(c.%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s{cookie}", r.CookieName())
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
 | 
			
		||||
@@ -32,20 +35,24 @@ func (r *Request) Define(c *Context) {
 | 
			
		||||
		c.Putln("func (c *Conn) %s(%s) %s {",
 | 
			
		||||
			r.SrcName(), r.ParamNameTypes(), r.CookieName())
 | 
			
		||||
		c.Putln("cookie := c.newCookie(false, false)")
 | 
			
		||||
		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s(cookie)", r.CookieName())
 | 
			
		||||
		c.Putln("c.newRequest(c.%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s{cookie}", r.CookieName())
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
 | 
			
		||||
		c.Putln("func (c *Conn) %sChecked(%s) %s {",
 | 
			
		||||
			r.SrcName(), r.ParamNameTypes(), r.CookieName())
 | 
			
		||||
		c.Putln("cookie := c.newCookie(true, false)")
 | 
			
		||||
		c.Putln("c.newRequest(%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s(cookie)", r.CookieName())
 | 
			
		||||
		c.Putln("c.newRequest(c.%s(%s), cookie)", r.ReqName(), r.ParamNames())
 | 
			
		||||
		c.Putln("return %s{cookie}", r.CookieName())
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	c.Putln("func (cook %s) Check() error {", r.CookieName())
 | 
			
		||||
	c.Putln("return cook.check()")
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	r.WriteRequest(c)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -64,10 +71,13 @@ func (r *Request) ReadReply(c *Context) {
 | 
			
		||||
	c.Putln("// Waits and reads reply data from request %s", r.SrcName())
 | 
			
		||||
	c.Putln("func (cook %s) Reply() (*%s, error) {",
 | 
			
		||||
		r.CookieName(), r.ReplyTypeName())
 | 
			
		||||
		c.Putln("buf, err := cookie(cook).reply()")
 | 
			
		||||
		c.Putln("buf, err := cook.reply()")
 | 
			
		||||
		c.Putln("if err != nil {")
 | 
			
		||||
		c.Putln("return nil, err")
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("if buf == nil {")
 | 
			
		||||
		c.Putln("return nil, nil")
 | 
			
		||||
		c.Putln("}")
 | 
			
		||||
		c.Putln("return %s(buf), nil", r.ReplyName())
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
@@ -79,7 +89,9 @@ func (r *Request) ReadReply(c *Context) {
 | 
			
		||||
	c.Putln("b := 1 // skip reply determinant")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	for i, field := range r.Reply.Fields {
 | 
			
		||||
		if i == 1 {
 | 
			
		||||
		field.Read(c, "v.")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
		if i == 0 {
 | 
			
		||||
			c.Putln("v.Sequence = Get16(buf[b:])")
 | 
			
		||||
			c.Putln("b += 2")
 | 
			
		||||
			c.Putln("")
 | 
			
		||||
@@ -87,8 +99,6 @@ func (r *Request) ReadReply(c *Context) {
 | 
			
		||||
			c.Putln("b += 4")
 | 
			
		||||
			c.Putln("")
 | 
			
		||||
		}
 | 
			
		||||
		field.Read(c, "v.")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("return v")
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
@@ -96,30 +106,41 @@ func (r *Request) ReadReply(c *Context) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) WriteRequest(c *Context) {
 | 
			
		||||
	writeSize := func() {
 | 
			
		||||
		c.Putln("Put16(buf[b:], uint16(size / 4)) "+
 | 
			
		||||
			"// write request size in 4-byte units")
 | 
			
		||||
		c.Putln("b += 2")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("// Write request to wire for %s", r.SrcName())
 | 
			
		||||
	c.Putln("func %s(%s) []byte {", r.ReqName(), r.ParamNameTypes())
 | 
			
		||||
	c.Putln("func (c *Conn) %s(%s) []byte {", r.ReqName(), r.ParamNameTypes())
 | 
			
		||||
	c.Putln("size := %s", r.Size(c))
 | 
			
		||||
	c.Putln("b := 0")
 | 
			
		||||
	c.Putln("buf := make([]byte, size)")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	c.Putln("buf[b] = %d // request opcode", r.Opcode)
 | 
			
		||||
	c.Putln("b += 1")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	if strings.ToLower(c.protocol.Name) != "xproto" {
 | 
			
		||||
		c.Putln("buf[b] = c.extensions[\"%s\"]",
 | 
			
		||||
			strings.ToUpper(c.protocol.ExtXName))
 | 
			
		||||
		c.Putln("b += 1")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
	}
 | 
			
		||||
	for i, field := range r.Fields {
 | 
			
		||||
		if i == 1 {
 | 
			
		||||
			c.Putln("Put16(buf[b:], uint16(size / 4)) "+
 | 
			
		||||
				"// write request size in 4-byte units")
 | 
			
		||||
			c.Putln("b += 2")
 | 
			
		||||
			c.Putln("")
 | 
			
		||||
	c.Putln("buf[b] = %d // request opcode", r.Opcode)
 | 
			
		||||
	c.Putln("b += 1")
 | 
			
		||||
	c.Putln("")
 | 
			
		||||
	if len(r.Fields) == 0 {
 | 
			
		||||
		if strings.ToLower(c.protocol.Name) == "xproto" {
 | 
			
		||||
			c.Putln("b += 1 // padding")
 | 
			
		||||
		}
 | 
			
		||||
		writeSize()
 | 
			
		||||
	} else if strings.ToLower(c.protocol.Name) != "xproto" {
 | 
			
		||||
		writeSize()
 | 
			
		||||
	}
 | 
			
		||||
	for i, field := range r.Fields {
 | 
			
		||||
		field.Write(c, "")
 | 
			
		||||
		c.Putln("")
 | 
			
		||||
		if i == 0 && strings.ToLower(c.protocol.Name) == "xproto" {
 | 
			
		||||
			writeSize()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	c.Putln("return buf")
 | 
			
		||||
	c.Putln("}")
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@ package main
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"log"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"unicode"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -41,7 +42,11 @@ type Request struct {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Request) Initialize(p *Protocol) {
 | 
			
		||||
	r.srcName = SrcName(r.xmlName)
 | 
			
		||||
	r.srcName = SrcName(p, r.xmlName)
 | 
			
		||||
	if p.Name != "xproto" {
 | 
			
		||||
		r.srcName = strings.Title(strings.ToLower(p.Name)) + r.srcName
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if r.Reply != nil {
 | 
			
		||||
		r.Reply.Initialize(p)
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -373,7 +373,7 @@ func (x *XMLBitcase) Translate() *Bitcase {
 | 
			
		||||
 | 
			
		||||
// SrcName is used to translate any identifier into a Go name.
 | 
			
		||||
// Mostly used for fields, but used in a couple other places too (enum items).
 | 
			
		||||
func SrcName(name string) string {
 | 
			
		||||
func SrcName(p *Protocol, name string) string {
 | 
			
		||||
	// If it's in the name map, use that translation.
 | 
			
		||||
	if newn, ok := NameMap[name]; ok {
 | 
			
		||||
		return newn
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ func (enum *Enum) Size() Size {
 | 
			
		||||
func (enum *Enum) Initialize(p *Protocol) {
 | 
			
		||||
	enum.srcName = TypeSrcName(p, enum)
 | 
			
		||||
	for _, item := range enum.Items {
 | 
			
		||||
		item.srcName = SrcName(item.xmlName)
 | 
			
		||||
		item.srcName = SrcName(p, item.xmlName)
 | 
			
		||||
		if item.Expr != nil {
 | 
			
		||||
			item.Expr.Initialize(p)
 | 
			
		||||
		}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user