github.com/platinasystems/nvram@v1.0.1-0.20190709235807-51a23abd5aec/layout_text.go (about) 1 package nvram 2 3 import ( 4 "bufio" 5 "fmt" 6 "os" 7 "strings" 8 ) 9 10 func ReadLayoutFromTextFile(filename string) (layout *Layout, err error) { 11 var file *os.File 12 13 // Create new empty layout 14 layout = NewLayout() 15 16 // Open layout text file 17 file, err = os.Open(filename) 18 if err != nil { 19 return 20 } 21 defer file.Close() 22 23 // Start parsing comment region 24 var mode int = 0 25 26 var linenum uint = 0 27 28 scanner := bufio.NewScanner(file) 29 for scanner.Scan() { 30 // Get line and ignore blanks and comments 31 line := strings.TrimSpace(scanner.Text()) 32 linenum++ 33 if len(line) == 0 { 34 continue 35 } 36 if line[0] == '#' { 37 continue 38 } 39 40 // Break line into files 41 fields := strings.Fields(line) 42 if len(fields) == 0 { 43 continue 44 } 45 46 // A single filed indicates a new region 47 // Change mode to parsing entries, enumerations or checksums 48 if len(fields) == 1 { 49 switch fields[0] { 50 case "entries": 51 mode = 1 52 case "enumerations": 53 mode = 2 54 case "checksums": 55 mode = 3 56 default: 57 err = fmt.Errorf("Unexpected section header on line %d", linenum) 58 return 59 } 60 continue 61 } 62 63 switch mode { 64 case 1: 65 // Entries have 5 fields 66 if len(fields) != 5 { 67 err = fmt.Errorf("Unexpected data in entries on line %d", linenum) 68 return 69 } 70 71 // Scan line and parse CMOS entry data 72 var entry CMOSEntry 73 var n int 74 n, err = fmt.Sscanf(line, "%d %d %c %d %s", 75 &entry.bit, &entry.length, &entry.config, &entry.config_id, &entry.name) 76 if err != nil || n != 5 { 77 err = fmt.Errorf("Unexpected data in entries on line %d", linenum) 78 return 79 } 80 81 // Add entry to layout 82 err = layout.AddCMOSEntry(&entry) 83 if err != nil { 84 return 85 } 86 87 case 2: 88 // Enumerations have 3 fields 89 if len(fields) != 3 { 90 err = fmt.Errorf("Unexpected data in enumerations on line %d", linenum) 91 return 92 } 93 94 // Scan line and parse CMOS enumeration data 95 var item CMOSEnumItem 96 var n int 97 n, err = fmt.Sscanf(line, "%d %d %s", 98 &item.id, &item.value, &item.text) 99 if err != nil || n != 3 { 100 err = fmt.Errorf("Unexpected data in enumerations on line %d", linenum) 101 return 102 } 103 104 // Check if enumeration value already exists for an id. 105 _, ok := layout.FindCMOSEnumText(item.id, item.value) 106 if ok { 107 fmt.Errorf("Enum %d already exists for id %d on line %d", 108 item.id, item.value, linenum) 109 return 110 } 111 112 // Add enumeration to layout 113 layout.AddCMOSEnum(&item) 114 115 case 3: 116 // Checksums have 4 fields 117 if len(fields) != 4 { 118 err = fmt.Errorf("Unexpected data in checksums on line %d", linenum) 119 return 120 } 121 122 // Scan line and parase checksum info. 123 var start, end, index uint 124 var label string 125 var n int 126 n, err = fmt.Sscanf(line, "%s %d %d %d", &label, 127 &start, &end, &index) 128 if err != nil || n != 4 { 129 err = fmt.Errorf("Unexpected data in checksums on line %d", linenum) 130 return 131 } 132 133 // Check label 134 if label != "checksum" { 135 err = fmt.Errorf("Missing checksum on line %d", linenum) 136 return 137 } 138 139 // Create and test new CMOS checksum for layout 140 layout.cmosChecksum, err = NewCMOSChecksum(start, end, index) 141 if err != nil { 142 return 143 } 144 145 default: 146 err = fmt.Errorf("Unexpected data on line %d", linenum) 147 return 148 } 149 } 150 151 // Return any errors 152 err = scanner.Err() 153 return 154 }