|  |  |  | @@ -71,10 +71,14 @@ type Generator struct { | 
		
	
		
			
				|  |  |  |  | 	Consts []ConstItem | 
		
	
		
			
				|  |  |  |  | 	// Structs holds a list of all the structs found by the parser | 
		
	
		
			
				|  |  |  |  | 	Structs []Structure | 
		
	
		
			
				|  |  |  |  | 	// Typedefs hold all the type definitions from 'typedef ...' lines. | 
		
	
		
			
				|  |  |  |  | 	// StructMap is a map of the structs we find for quick searching. | 
		
	
		
			
				|  |  |  |  | 	StructMap map[string]int | 
		
	
		
			
				|  |  |  |  | 	// Typedefs holds all the type definitions from 'typedef ...' lines. | 
		
	
		
			
				|  |  |  |  | 	Typedefs []Typedef | 
		
	
		
			
				|  |  |  |  | 	// Unions hold all the discriminated unions | 
		
	
		
			
				|  |  |  |  | 	// Unions holds all the discriminated unions. | 
		
	
		
			
				|  |  |  |  | 	Unions []Union | 
		
	
		
			
				|  |  |  |  | 	// Procs holds all the discovered libvirt procedures. | 
		
	
		
			
				|  |  |  |  | 	Procs []Proc | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Gen accumulates items as the parser runs, and is then used to produce the | 
		
	
	
		
			
				
					
					|  |  |  | @@ -85,15 +89,48 @@ var Gen Generator | 
		
	
		
			
				|  |  |  |  | // explicitly given a value. | 
		
	
		
			
				|  |  |  |  | var CurrentEnumVal int64 | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // oneRuneTokens lists the runes the lexer will consider to be tokens when it | 
		
	
		
			
				|  |  |  |  | // finds them. These are returned to the parser using the integer value of their | 
		
	
		
			
				|  |  |  |  | // runes. | 
		
	
		
			
				|  |  |  |  | var oneRuneTokens = `{}[]<>(),=;:*` | 
		
	
		
			
				|  |  |  |  | // goEquivTypes maps the basic types defined in the rpc spec to their golang | 
		
	
		
			
				|  |  |  |  | // equivalents. | 
		
	
		
			
				|  |  |  |  | var goEquivTypes = map[string]string{ | 
		
	
		
			
				|  |  |  |  | 	// Some of the identifiers in the rpc specification are reserved words or | 
		
	
		
			
				|  |  |  |  | 	// pre-existing types in go. This renames them to something safe. | 
		
	
		
			
				|  |  |  |  | 	"type":  "lvtype", | 
		
	
		
			
				|  |  |  |  | 	"error": "lverror", | 
		
	
		
			
				|  |  |  |  | 	"nil":   "lvnil", | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | var reservedIdentifiers = map[string]string{ | 
		
	
		
			
				|  |  |  |  | 	"type":   "lvtype", | 
		
	
		
			
				|  |  |  |  | 	"string": "lvstring", | 
		
	
		
			
				|  |  |  |  | 	"error":  "lverror", | 
		
	
		
			
				|  |  |  |  | 	// The libvirt spec uses this NonnullString type, which is a string with a | 
		
	
		
			
				|  |  |  |  | 	// specified maximum length. This makes the go code more confusing, and | 
		
	
		
			
				|  |  |  |  | 	// we're not enforcing the limit anyway, so collapse it here. This also | 
		
	
		
			
				|  |  |  |  | 	// requires us to ditch the typedef that would otherwise be generated. | 
		
	
		
			
				|  |  |  |  | 	"NonnullString": "string", | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	"String":  "string", | 
		
	
		
			
				|  |  |  |  | 	"Int":     "int", | 
		
	
		
			
				|  |  |  |  | 	"Uint":    "uint", | 
		
	
		
			
				|  |  |  |  | 	"Int8":    "int8", | 
		
	
		
			
				|  |  |  |  | 	"Uint8":   "uint8", | 
		
	
		
			
				|  |  |  |  | 	"Int16":   "int16", | 
		
	
		
			
				|  |  |  |  | 	"Uint16":  "uint16", | 
		
	
		
			
				|  |  |  |  | 	"Int32":   "int32", | 
		
	
		
			
				|  |  |  |  | 	"Uint32":  "uint32", | 
		
	
		
			
				|  |  |  |  | 	"Int64":   "int64", | 
		
	
		
			
				|  |  |  |  | 	"Uint64":  "uint64", | 
		
	
		
			
				|  |  |  |  | 	"Float32": "float32", | 
		
	
		
			
				|  |  |  |  | 	"Float64": "float64", | 
		
	
		
			
				|  |  |  |  | 	"Bool":    "bool", | 
		
	
		
			
				|  |  |  |  | 	"Byte":    "byte", | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // These defines are from libvirt-common.h. They should be fetched from there, | 
		
	
		
			
				|  |  |  |  | // but for now they're hardcoded here. | 
		
	
		
			
				|  |  |  |  | var lvTypedParams = map[string]uint32{ | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_INT":     1, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_UINT":    2, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_LLONG":   3, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_ULLONG":  4, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_DOUBLE":  5, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_BOOLEAN": 6, | 
		
	
		
			
				|  |  |  |  | 	"VIR_TYPED_PARAM_STRING":  7, | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Decl records a declaration, like 'int x' or 'remote_nonnull_string str' | 
		
	
	
		
			
				
					
					|  |  |  | @@ -123,14 +160,50 @@ type Union struct { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Case holds a single case of a discriminated union. | 
		
	
		
			
				|  |  |  |  | type Case struct { | 
		
	
		
			
				|  |  |  |  | 	CaseName        string | 
		
	
		
			
				|  |  |  |  | 	DiscriminantVal string | 
		
	
		
			
				|  |  |  |  | 	Type            Decl | 
		
	
		
			
				|  |  |  |  | 	Decl | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Proc holds information about a libvirt procedure the parser has found. | 
		
	
		
			
				|  |  |  |  | type Proc struct { | 
		
	
		
			
				|  |  |  |  | 	Num        int64 | 
		
	
		
			
				|  |  |  |  | 	Name       string | 
		
	
		
			
				|  |  |  |  | 	Args       []Decl | 
		
	
		
			
				|  |  |  |  | 	Ret        []Decl | 
		
	
		
			
				|  |  |  |  | 	ArgsStruct string | 
		
	
		
			
				|  |  |  |  | 	RetStruct  string | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | type structStack []*Structure | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // CurrentStruct will point to a struct record if we're in a struct declaration. | 
		
	
		
			
				|  |  |  |  | // When the parser adds a declaration, it will be added to the open struct if | 
		
	
		
			
				|  |  |  |  | // there is one. | 
		
	
		
			
				|  |  |  |  | var CurrentStruct *Structure | 
		
	
		
			
				|  |  |  |  | var CurrentStruct structStack | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // Since it's possible to have an embedded struct definition, this implements | 
		
	
		
			
				|  |  |  |  | // a stack to keep track of the current structure. | 
		
	
		
			
				|  |  |  |  | func (s *structStack) empty() bool { | 
		
	
		
			
				|  |  |  |  | 	return len(*s) == 0 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | func (s *structStack) push(st *Structure) { | 
		
	
		
			
				|  |  |  |  | 	*s = append(*s, st) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | func (s *structStack) pop() *Structure { | 
		
	
		
			
				|  |  |  |  | 	if s.empty() { | 
		
	
		
			
				|  |  |  |  | 		return nil | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	st := (*s)[len(*s)-1] | 
		
	
		
			
				|  |  |  |  | 	*s = (*s)[:len(*s)-1] | 
		
	
		
			
				|  |  |  |  | 	return st | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  | func (s *structStack) peek() *Structure { | 
		
	
		
			
				|  |  |  |  | 	if s.empty() { | 
		
	
		
			
				|  |  |  |  | 		return nil | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	return (*s)[len(*s)-1] | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // CurrentTypedef will point to a typedef record if we're parsing one. Typedefs | 
		
	
		
			
				|  |  |  |  | // can define a struct or union type, but the preferred for is struct xxx{...}, | 
		
	
	
		
			
				
					
					|  |  |  | @@ -148,6 +221,7 @@ var CurrentCase *Case | 
		
	
		
			
				|  |  |  |  | // the path to the root of the libvirt source directory to use for the | 
		
	
		
			
				|  |  |  |  | // generation. | 
		
	
		
			
				|  |  |  |  | func Generate(proto io.Reader) error { | 
		
	
		
			
				|  |  |  |  | 	Gen.StructMap = make(map[string]int) | 
		
	
		
			
				|  |  |  |  | 	lexer, err := NewLexer(proto) | 
		
	
		
			
				|  |  |  |  | 	if err != nil { | 
		
	
		
			
				|  |  |  |  | 		return err | 
		
	
	
		
			
				
					
					|  |  |  | @@ -162,6 +236,10 @@ func Generate(proto io.Reader) error { | 
		
	
		
			
				|  |  |  |  | 		return fmt.Errorf("failed to parse libvirt protocol: %v", rv) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// When parsing is done, we can link the procedures we've found to their | 
		
	
		
			
				|  |  |  |  | 	// argument types. | 
		
	
		
			
				|  |  |  |  | 	procLink() | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | 	// Generate and write the output. | 
		
	
		
			
				|  |  |  |  | 	constFile, err := os.Create("../constants/constants.gen.go") | 
		
	
		
			
				|  |  |  |  | 	if err != nil { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -216,26 +294,44 @@ func genGo(constFile, procFile io.Writer) error { | 
		
	
		
			
				|  |  |  |  | // also tries to upcase abbreviations so a name like DOMAIN_GET_XML becomes | 
		
	
		
			
				|  |  |  |  | // DomainGetXML, not DomainGetXml. | 
		
	
		
			
				|  |  |  |  | func constNameTransform(name string) string { | 
		
	
		
			
				|  |  |  |  | 	nn := fromSnakeToCamel(strings.TrimPrefix(name, "REMOTE_"), true) | 
		
	
		
			
				|  |  |  |  | 	decamelize := strings.ContainsRune(name, '_') | 
		
	
		
			
				|  |  |  |  | 	nn := strings.TrimPrefix(name, "REMOTE_") | 
		
	
		
			
				|  |  |  |  | 	if decamelize { | 
		
	
		
			
				|  |  |  |  | 		nn = fromSnakeToCamel(nn, true) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	nn = fixAbbrevs(nn) | 
		
	
		
			
				|  |  |  |  | 	return nn | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | func identifierTransform(name string) string { | 
		
	
		
			
				|  |  |  |  | 	decamelize := strings.ContainsRune(name, '_') | 
		
	
		
			
				|  |  |  |  | 	nn := strings.TrimPrefix(name, "remote_") | 
		
	
		
			
				|  |  |  |  | 	nn = fromSnakeToCamel(nn, false) | 
		
	
		
			
				|  |  |  |  | 	if decamelize { | 
		
	
		
			
				|  |  |  |  | 		nn = fromSnakeToCamel(nn, true) | 
		
	
		
			
				|  |  |  |  | 	} else { | 
		
	
		
			
				|  |  |  |  | 		nn = publicize(nn) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	nn = fixAbbrevs(nn) | 
		
	
		
			
				|  |  |  |  | 	nn = checkIdentifier(nn) | 
		
	
		
			
				|  |  |  |  | 	return nn | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | func typeTransform(name string) string { | 
		
	
		
			
				|  |  |  |  | 	nn := strings.TrimLeft(name, "*") | 
		
	
		
			
				|  |  |  |  | 	nn := strings.TrimLeft(name, "*[]") | 
		
	
		
			
				|  |  |  |  | 	diff := len(name) - len(nn) | 
		
	
		
			
				|  |  |  |  | 	nn = identifierTransform(nn) | 
		
	
		
			
				|  |  |  |  | 	return name[0:diff] + nn | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | func publicize(name string) string { | 
		
	
		
			
				|  |  |  |  | 	if len(name) <= 0 { | 
		
	
		
			
				|  |  |  |  | 		return name | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	r, n := utf8.DecodeRuneInString(name) | 
		
	
		
			
				|  |  |  |  | 	name = string(unicode.ToUpper(r)) + name[n:] | 
		
	
		
			
				|  |  |  |  | 	return name | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // fromSnakeToCamel transmutes a snake-cased string to a camel-cased one. All | 
		
	
		
			
				|  |  |  |  | // runes that follow an underscore are up-cased, and the underscores themselves | 
		
	
		
			
				|  |  |  |  | // are omitted. | 
		
	
	
		
			
				
					
					|  |  |  | @@ -292,6 +388,30 @@ func fixAbbrevs(s string) string { | 
		
	
		
			
				|  |  |  |  | 	return s | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // procLink associates a libvirt procedure with the types that are its arguments | 
		
	
		
			
				|  |  |  |  | // and return values, filling out those fields in the procedure struct. These | 
		
	
		
			
				|  |  |  |  | // types are extracted by iterating through the argument and return structures | 
		
	
		
			
				|  |  |  |  | // defined in the protocol file. If one or both of these structs is not defined | 
		
	
		
			
				|  |  |  |  | // then either the args or return values are empty. | 
		
	
		
			
				|  |  |  |  | func procLink() { | 
		
	
		
			
				|  |  |  |  | 	for ix, proc := range Gen.Procs { | 
		
	
		
			
				|  |  |  |  | 		argsName := proc.Name + "Args" | 
		
	
		
			
				|  |  |  |  | 		retName := proc.Name + "Ret" | 
		
	
		
			
				|  |  |  |  | 		argsIx, hasArgs := Gen.StructMap[argsName] | 
		
	
		
			
				|  |  |  |  | 		retIx, hasRet := Gen.StructMap[retName] | 
		
	
		
			
				|  |  |  |  | 		if hasArgs { | 
		
	
		
			
				|  |  |  |  | 			argsStruct := Gen.Structs[argsIx] | 
		
	
		
			
				|  |  |  |  | 			Gen.Procs[ix].ArgsStruct = argsStruct.Name | 
		
	
		
			
				|  |  |  |  | 			Gen.Procs[ix].Args = argsStruct.Members | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		if hasRet { | 
		
	
		
			
				|  |  |  |  | 			retStruct := Gen.Structs[retIx] | 
		
	
		
			
				|  |  |  |  | 			Gen.Procs[ix].RetStruct = retStruct.Name | 
		
	
		
			
				|  |  |  |  | 			Gen.Procs[ix].Ret = retStruct.Members | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | //--------------------------------------------------------------------------- | 
		
	
		
			
				|  |  |  |  | // Routines called by the parser's actions. | 
		
	
		
			
				|  |  |  |  | //--------------------------------------------------------------------------- | 
		
	
	
		
			
				
					
					|  |  |  | @@ -327,6 +447,7 @@ func addEnumVal(name string, val int64) error { | 
		
	
		
			
				|  |  |  |  | 	name = constNameTransform(name) | 
		
	
		
			
				|  |  |  |  | 	Gen.EnumVals = append(Gen.EnumVals, ConstItem{name, fmt.Sprintf("%d", val)}) | 
		
	
		
			
				|  |  |  |  | 	CurrentEnumVal = val | 
		
	
		
			
				|  |  |  |  | 	addProc(name, val) | 
		
	
		
			
				|  |  |  |  | 	return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -341,6 +462,17 @@ func AddConst(name, val string) error { | 
		
	
		
			
				|  |  |  |  | 	return nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // addProc checks an enum value to see if it's a procedure number. If so, we | 
		
	
		
			
				|  |  |  |  | // add the procedure to our list for later generation. | 
		
	
		
			
				|  |  |  |  | func addProc(name string, val int64) { | 
		
	
		
			
				|  |  |  |  | 	if !strings.HasPrefix(name, "Proc") { | 
		
	
		
			
				|  |  |  |  | 		return | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	name = name[4:] | 
		
	
		
			
				|  |  |  |  | 	proc := &Proc{Num: val, Name: name} | 
		
	
		
			
				|  |  |  |  | 	Gen.Procs = append(Gen.Procs, *proc) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // parseNumber makes sure that a parsed numerical value can be parsed to a 64- | 
		
	
		
			
				|  |  |  |  | // bit integer. | 
		
	
		
			
				|  |  |  |  | func parseNumber(val string) (int64, error) { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -357,25 +489,22 @@ func parseNumber(val string) (int64, error) { | 
		
	
		
			
				|  |  |  |  | // before the member declarations are processed. | 
		
	
		
			
				|  |  |  |  | func StartStruct(name string) { | 
		
	
		
			
				|  |  |  |  | 	name = identifierTransform(name) | 
		
	
		
			
				|  |  |  |  | 	CurrentStruct = &Structure{Name: name} | 
		
	
		
			
				|  |  |  |  | 	CurrentStruct.push(&Structure{Name: name}) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // AddStruct is called when the parser has finished parsing a struct. It adds | 
		
	
		
			
				|  |  |  |  | // the now-complete struct definition to the generator's list. | 
		
	
		
			
				|  |  |  |  | func AddStruct() { | 
		
	
		
			
				|  |  |  |  | 	Gen.Structs = append(Gen.Structs, *CurrentStruct) | 
		
	
		
			
				|  |  |  |  | 	CurrentStruct = nil | 
		
	
		
			
				|  |  |  |  | 	st := *CurrentStruct.pop() | 
		
	
		
			
				|  |  |  |  | 	Gen.Structs = append(Gen.Structs, st) | 
		
	
		
			
				|  |  |  |  | 	Gen.StructMap[st.Name] = len(Gen.Structs) - 1 | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // StartTypedef is called when the parser finds a typedef. | 
		
	
		
			
				|  |  |  |  | func StartTypedef() { | 
		
	
		
			
				|  |  |  |  | 	CurrentTypedef = &Typedef{} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // TODO: remove before flight | 
		
	
		
			
				|  |  |  |  | func Beacon(name string) { | 
		
	
		
			
				|  |  |  |  | 	fmt.Println(name) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // StartUnion is called by the parser when it finds a union declaraion. | 
		
	
		
			
				|  |  |  |  | func StartUnion(name string) { | 
		
	
		
			
				|  |  |  |  | 	name = identifierTransform(name) | 
		
	
	
		
			
				
					
					|  |  |  | @@ -384,16 +513,34 @@ func StartUnion(name string) { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // AddUnion is called by the parser when it has finished processing a union | 
		
	
		
			
				|  |  |  |  | // type. It adds the union to the generator's list and clears the CurrentUnion | 
		
	
		
			
				|  |  |  |  | // pointer. | 
		
	
		
			
				|  |  |  |  | // pointer. We handle unions by declaring an interface for the union type, and | 
		
	
		
			
				|  |  |  |  | // adding methods to each of the cases so that they satisfy the interface. | 
		
	
		
			
				|  |  |  |  | func AddUnion() { | 
		
	
		
			
				|  |  |  |  | 	Gen.Unions = append(Gen.Unions, *CurrentUnion) | 
		
	
		
			
				|  |  |  |  | 	CurrentUnion = nil | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // StartCase is called when the parser finds a case statement within a union. | 
		
	
		
			
				|  |  |  |  | func StartCase(dvalue string) { | 
		
	
		
			
				|  |  |  |  | 	CurrentCase = &Case{DiscriminantVal: dvalue} | 
		
	
		
			
				|  |  |  |  | 	// In libvirt, the discriminant values are all C pre- processor definitions. | 
		
	
		
			
				|  |  |  |  | 	// Since we don't run the C pre-processor on the protocol file, they're | 
		
	
		
			
				|  |  |  |  | 	// still just names when we get them - we don't actually have their integer | 
		
	
		
			
				|  |  |  |  | 	// values. We'll use the strings to build the type names, although this is | 
		
	
		
			
				|  |  |  |  | 	// brittle, because we're defining a type for each of the case values, and | 
		
	
		
			
				|  |  |  |  | 	// that type needs a name. | 
		
	
		
			
				|  |  |  |  | 	caseName := dvalue | 
		
	
		
			
				|  |  |  |  | 	if ix := strings.LastIndexByte(caseName, '_'); ix != -1 { | 
		
	
		
			
				|  |  |  |  | 		caseName = caseName[ix+1:] | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	caseName = fromSnakeToCamel(caseName, true) | 
		
	
		
			
				|  |  |  |  | 	dv, ok := lvTypedParams[dvalue] | 
		
	
		
			
				|  |  |  |  | 	if ok { | 
		
	
		
			
				|  |  |  |  | 		dvalue = strconv.FormatUint(uint64(dv), 10) | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	CurrentCase = &Case{CaseName: caseName, DiscriminantVal: dvalue} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // AddCase is called when the parser finishes parsing a case. | 
		
	
		
			
				|  |  |  |  | func AddCase() { | 
		
	
		
			
				|  |  |  |  | 	CurrentUnion.Cases = append(CurrentUnion.Cases, *CurrentCase) | 
		
	
		
			
				|  |  |  |  | 	CurrentCase = nil | 
		
	
	
		
			
				
					
					|  |  |  | @@ -403,27 +550,59 @@ func AddCase() { | 
		
	
		
			
				|  |  |  |  | // The declaration will be added to any open container (such as a struct, if the | 
		
	
		
			
				|  |  |  |  | // parser is working through a struct definition.) | 
		
	
		
			
				|  |  |  |  | func AddDeclaration(identifier, itype string) { | 
		
	
		
			
				|  |  |  |  | 	// TODO: panic if not in a struct/union/typedef? | 
		
	
		
			
				|  |  |  |  | 	// fmt.Println("adding", identifier, itype) | 
		
	
		
			
				|  |  |  |  | 	// If the name is a reserved word, transform it so it isn't. | 
		
	
		
			
				|  |  |  |  | 	identifier = identifierTransform(identifier) | 
		
	
		
			
				|  |  |  |  | 	itype = typeTransform(itype) | 
		
	
		
			
				|  |  |  |  | 	decl := &Decl{Name: identifier, Type: itype} | 
		
	
		
			
				|  |  |  |  | 	if CurrentStruct != nil { | 
		
	
		
			
				|  |  |  |  | 		CurrentStruct.Members = append(CurrentStruct.Members, *decl) | 
		
	
		
			
				|  |  |  |  | 	decl := Decl{Name: identifier, Type: itype} | 
		
	
		
			
				|  |  |  |  | 	if !CurrentStruct.empty() { | 
		
	
		
			
				|  |  |  |  | 		st := CurrentStruct.peek() | 
		
	
		
			
				|  |  |  |  | 		st.Members = append(st.Members, decl) | 
		
	
		
			
				|  |  |  |  | 	} else if CurrentTypedef != nil { | 
		
	
		
			
				|  |  |  |  | 		CurrentTypedef.Name = identifier | 
		
	
		
			
				|  |  |  |  | 		CurrentTypedef.Type = itype | 
		
	
		
			
				|  |  |  |  | 		Gen.Typedefs = append(Gen.Typedefs, *CurrentTypedef) | 
		
	
		
			
				|  |  |  |  | 		if identifier != "string" { | 
		
	
		
			
				|  |  |  |  | 			// Omit recursive typedefs. These happen because we're massaging | 
		
	
		
			
				|  |  |  |  | 			// some of the type names. | 
		
	
		
			
				|  |  |  |  | 			Gen.Typedefs = append(Gen.Typedefs, *CurrentTypedef) | 
		
	
		
			
				|  |  |  |  | 		} | 
		
	
		
			
				|  |  |  |  | 		CurrentTypedef = nil | 
		
	
		
			
				|  |  |  |  | 	} else if CurrentCase != nil { | 
		
	
		
			
				|  |  |  |  | 		CurrentCase.Type = *decl | 
		
	
		
			
				|  |  |  |  | 		CurrentCase.Name = identifier | 
		
	
		
			
				|  |  |  |  | 		CurrentCase.Type = itype | 
		
	
		
			
				|  |  |  |  | 	} else if CurrentUnion != nil { | 
		
	
		
			
				|  |  |  |  | 		CurrentUnion.DiscriminantType = itype | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // AddFixedArray is called by the parser to add a fixed-length array to the | 
		
	
		
			
				|  |  |  |  | // current container (struct, union, etc). Fixed-length arrays are not length- | 
		
	
		
			
				|  |  |  |  | // prefixed. | 
		
	
		
			
				|  |  |  |  | func AddFixedArray(identifier, itype, len string) { | 
		
	
		
			
				|  |  |  |  | 	atype := fmt.Sprintf("[%v]%v", len, itype) | 
		
	
		
			
				|  |  |  |  | 	AddDeclaration(identifier, atype) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | // AddVariableArray is called by the parser to add a variable-length array. | 
		
	
		
			
				|  |  |  |  | // Variable-length arrays are prefixed with a 32-bit unsigned length, and may | 
		
	
		
			
				|  |  |  |  | // also have a maximum length specified. | 
		
	
		
			
				|  |  |  |  | func AddVariableArray(identifier, itype, len string) { | 
		
	
		
			
				|  |  |  |  | 	// FIXME: This ignores the length restriction, so as of now we can't check | 
		
	
		
			
				|  |  |  |  | 	// to make sure that we're not exceeding that restriction when we fill in | 
		
	
		
			
				|  |  |  |  | 	// message buffers. That may not matter, if libvirt's checking is careful | 
		
	
		
			
				|  |  |  |  | 	// enough. This could be handled with a map, however. | 
		
	
		
			
				|  |  |  |  | 	atype := fmt.Sprintf("[]%v", itype) | 
		
	
		
			
				|  |  |  |  | 	// Handle strings specially. In the rpcgen definition a string is specified | 
		
	
		
			
				|  |  |  |  | 	// as a variable-length array, either with or without a max length. We want | 
		
	
		
			
				|  |  |  |  | 	// these to be go strings, so we'll just remove the array specifier. | 
		
	
		
			
				|  |  |  |  | 	if itype == "string" { | 
		
	
		
			
				|  |  |  |  | 		atype = itype | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
		
			
				|  |  |  |  | 	AddDeclaration(identifier, atype) | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | func checkIdentifier(i string) string { | 
		
	
		
			
				|  |  |  |  | 	nn, reserved := reservedIdentifiers[i] | 
		
	
		
			
				|  |  |  |  | 	nn, reserved := goEquivTypes[i] | 
		
	
		
			
				|  |  |  |  | 	if reserved { | 
		
	
		
			
				|  |  |  |  | 		return nn | 
		
	
		
			
				|  |  |  |  | 	} | 
		
	
	
		
			
				
					
					|  |  |  |   |