go-vise

Constrained Size Output Virtual Machine
Info | Log | Files | Refs | README | LICENSE

flag.go (3091B)


      1 package asm
      2 
      3 import (
      4 	"encoding/csv"
      5 	"fmt"
      6 	"io"
      7 	"os"
      8 	"strconv"
      9 
     10 	"git.defalsify.org/vise.git/state"
     11 )
     12 
     13 // FlagParser is used to resolve flag strings to corresponding
     14 // flag index integer values.
     15 type FlagParser struct {
     16 	flag map[string]string
     17 	flagDescription map[uint32]string
     18 	hi uint32
     19 	debug bool
     20 }
     21 
     22 // NewFlagParser creates a new FlagParser
     23 func NewFlagParser() *FlagParser {
     24 	return &FlagParser{
     25 		flag: make(map[string]string),
     26 		flagDescription: make(map[uint32]string),
     27 	}
     28 }
     29 
     30 func(pp *FlagParser) WithDebug() *FlagParser {
     31 	pp.debug = true
     32 	return pp
     33 }
     34 
     35 // GetFlag returns the flag index value for a given flag string
     36 // as a numeric string.
     37 //
     38 // If flag string has not been registered, an error is returned.
     39 func(pp *FlagParser) GetAsString(key string) (string, error) {
     40 	v, ok := pp.flag[key]
     41 	if !ok {
     42 		return "", fmt.Errorf("no flag registered under key: %s", key)
     43 	}
     44 	return v, nil
     45 }
     46 
     47 // GetFlag returns the flag index integer value for a given
     48 // flag string
     49 //
     50 // If flag string has not been registered, an error is returned.
     51 func(pp *FlagParser) GetFlag(key string) (uint32, error) {
     52 	v, err := pp.GetAsString(key)
     53 	if err != nil {
     54 		return 0, err
     55 	}
     56 	r, err := strconv.Atoi(v) // cannot fail
     57 	return uint32(r), nil
     58 }
     59 
     60 // GetDescription returns a flag description for a given flag index,
     61 // if available.
     62 //
     63 // If no description has been provided, an error is returned.
     64 func(pp *FlagParser) GetDescription(idx uint32) (string, error) {
     65 	v, ok := pp.flagDescription[idx]
     66 	if !ok {
     67 		return "", fmt.Errorf("no description for flag idx: %v", idx)
     68 	}
     69 	return v, nil
     70 }
     71 
     72 // Last returns the highest registered flag index value
     73 func(pp *FlagParser) Last() uint32 {
     74 	return pp.hi	
     75 }
     76 
     77 // Load parses a Comma Seperated Value file under the given filepath
     78 // to provide mappings between flag strings and flag indices.
     79 //
     80 // The expected format is:
     81 // 
     82 // Field 1: The literal string "flag"
     83 // Field 2: Flag string
     84 // Field 3: Flag index
     85 // Field 4: Flag description (optional)
     86 func(pp *FlagParser) Load(fp string) (int, error) {
     87 	var i int
     88 	f, err := os.Open(fp)
     89 	if err != nil {
     90 		return 0, err
     91 	}
     92 	defer f.Close()
     93 	r := csv.NewReader(f)
     94 	r.FieldsPerRecord = -1
     95 	for i = 0; true; i++ {
     96 		v, err := r.Read()
     97 		if err != nil {
     98 			if err == io.EOF {
     99 				break
    100 			}
    101 			return 0, err
    102 		}
    103 		if v[0] == "flag" {
    104 			if len(v) < 3 {
    105 				return 0, fmt.Errorf("Not enough fields for flag setting in line %d", i)
    106 			}
    107 			vv, err := strconv.Atoi(v[2])
    108 			if err != nil {
    109 				return 0, fmt.Errorf("Flag translation value must be numeric")
    110 			}
    111 			if vv < state.FLAG_USERSTART {
    112 				return 0, fmt.Errorf("Minimum flag value is FLAG_USERSTART (%d)", state.FLAG_USERSTART)
    113 			}
    114 			fl := uint32(vv)
    115 			pp.flag[v[1]] = v[2]
    116 			if fl > pp.hi {
    117 				pp.hi = fl
    118 			}
    119 			
    120 			if (len(v) > 3) {
    121 				pp.flagDescription[uint32(fl)] = v[3]
    122 				logg.Debugf("added flag translation", "from", v[1], "to", v[2], "description", v[3])
    123 			} else {
    124 				logg.Debugf("added flag translation", "from", v[1], "to", v[2])
    125 			}
    126 			if pp.debug {
    127 				state.FlagDebugger.Register(fl, v[2])
    128 			}
    129 		}
    130 	}	
    131 
    132 	return i, nil
    133 }