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  }