Source file src/cmd/compile/internal/types/goversion.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package types
     6  
     7  import (
     8  	"fmt"
     9  	"internal/goversion"
    10  	"internal/lazyregexp"
    11  	"log"
    12  	"strconv"
    13  
    14  	"cmd/compile/internal/base"
    15  )
    16  
    17  // A lang is a language version broken into major and minor numbers.
    18  type lang struct {
    19  	major, minor int
    20  }
    21  
    22  // langWant is the desired language version set by the -lang flag.
    23  // If the -lang flag is not set, this is the zero value, meaning that
    24  // any language version is supported.
    25  var langWant lang
    26  
    27  // AllowsGoVersion reports whether local package is allowed
    28  // to use Go version major.minor.
    29  func AllowsGoVersion(major, minor int) bool {
    30  	if langWant.major == 0 && langWant.minor == 0 {
    31  		return true
    32  	}
    33  	return langWant.major > major || (langWant.major == major && langWant.minor >= minor)
    34  }
    35  
    36  // ParseLangFlag verifies that the -lang flag holds a valid value, and
    37  // exits if not. It initializes data used by AllowsGoVersion.
    38  func ParseLangFlag() {
    39  	if base.Flag.Lang == "" {
    40  		return
    41  	}
    42  
    43  	var err error
    44  	langWant, err = parseLang(base.Flag.Lang)
    45  	if err != nil {
    46  		log.Fatalf("invalid value %q for -lang: %v", base.Flag.Lang, err)
    47  	}
    48  
    49  	if def := currentLang(); base.Flag.Lang != def {
    50  		defVers, err := parseLang(def)
    51  		if err != nil {
    52  			log.Fatalf("internal error parsing default lang %q: %v", def, err)
    53  		}
    54  		if langWant.major > defVers.major || (langWant.major == defVers.major && langWant.minor > defVers.minor) {
    55  			log.Fatalf("invalid value %q for -lang: max known version is %q", base.Flag.Lang, def)
    56  		}
    57  	}
    58  }
    59  
    60  // parseLang parses a -lang option into a langVer.
    61  func parseLang(s string) (lang, error) {
    62  	if s == "go1" { // cmd/go's new spelling of "go1.0" (#65528)
    63  		s = "go1.0"
    64  	}
    65  
    66  	matches := goVersionRE.FindStringSubmatch(s)
    67  	if matches == nil {
    68  		return lang{}, fmt.Errorf(`should be something like "go1.12"`)
    69  	}
    70  	major, err := strconv.Atoi(matches[1])
    71  	if err != nil {
    72  		return lang{}, err
    73  	}
    74  	minor, err := strconv.Atoi(matches[2])
    75  	if err != nil {
    76  		return lang{}, err
    77  	}
    78  	return lang{major: major, minor: minor}, nil
    79  }
    80  
    81  // currentLang returns the current language version.
    82  func currentLang() string {
    83  	return fmt.Sprintf("go1.%d", goversion.Version)
    84  }
    85  
    86  // goVersionRE is a regular expression that matches the valid
    87  // arguments to the -lang flag.
    88  var goVersionRE = lazyregexp.New(`^go([1-9]\d*)\.(0|[1-9]\d*)$`)
    89  

View as plain text