github.com/goplus/llgo@v0.8.3/internal/projs/proj.go (about)

     1  /*
     2   * Copyright (c) 2024 The GoPlus Authors (goplus.org). All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  package projs
    18  
    19  import (
    20  	"errors"
    21  	"path/filepath"
    22  	"syscall"
    23  )
    24  
    25  // -----------------------------------------------------------------------------
    26  
    27  type Proj = interface {
    28  	projObj()
    29  }
    30  
    31  type FilesProj struct {
    32  	Files []string
    33  }
    34  
    35  type PkgPathProj struct {
    36  	Path string
    37  }
    38  
    39  type DirProj struct {
    40  	Dir string
    41  }
    42  
    43  func (p *FilesProj) projObj()   {}
    44  func (p *PkgPathProj) projObj() {}
    45  func (p *DirProj) projObj()     {}
    46  
    47  // -----------------------------------------------------------------------------
    48  
    49  func ParseOne(args ...string) (proj Proj, next []string, err error) {
    50  	if len(args) == 0 {
    51  		return nil, nil, syscall.ENOENT
    52  	}
    53  	arg := args[0]
    54  	if isFile(arg) {
    55  		n := 1
    56  		for n < len(args) && isFile(args[n]) {
    57  			n++
    58  		}
    59  		return &FilesProj{Files: args[:n]}, args[n:], nil
    60  	}
    61  	if isLocal(arg) {
    62  		return &DirProj{Dir: arg}, args[1:], nil
    63  	}
    64  	return &PkgPathProj{Path: arg}, args[1:], nil
    65  }
    66  
    67  func isFile(fname string) bool {
    68  	n := len(filepath.Ext(fname))
    69  	return n > 1
    70  }
    71  
    72  func isLocal(ns string) bool {
    73  	if len(ns) > 0 {
    74  		switch c := ns[0]; c {
    75  		case '/', '\\', '.':
    76  			return true
    77  		default:
    78  			return len(ns) >= 2 && ns[1] == ':' && ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')
    79  		}
    80  	}
    81  	return false
    82  }
    83  
    84  // -----------------------------------------------------------------------------
    85  
    86  func ParseAll(args ...string) (projs []Proj, err error) {
    87  	var hasFiles, hasNotFiles bool
    88  	for {
    89  		proj, next, e := ParseOne(args...)
    90  		if e != nil {
    91  			if hasFiles && hasNotFiles {
    92  				return nil, ErrMixedFilesProj
    93  			}
    94  			return
    95  		}
    96  		if _, ok := proj.(*FilesProj); ok {
    97  			hasFiles = true
    98  		} else {
    99  			hasNotFiles = true
   100  		}
   101  		projs = append(projs, proj)
   102  		args = next
   103  	}
   104  }
   105  
   106  var (
   107  	ErrMixedFilesProj = errors.New("mixed files project")
   108  )
   109  
   110  // -----------------------------------------------------------------------------