github.com/primecitizens/pcz/std@v0.2.1/core/sys/os_wasi.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright 2023 The Prime Citizens
     3  
     4  //go:build !noos && wasip1
     5  
     6  package sys
     7  
     8  import (
     9  	"unsafe"
    10  
    11  	"github.com/primecitizens/pcz/std/core/assert"
    12  	"github.com/primecitizens/pcz/std/ffi/wasm/wasi"
    13  )
    14  
    15  var (
    16  	args []string
    17  	envs []string
    18  )
    19  
    20  func ntharg(i int) string {
    21  	return args[i]
    22  }
    23  
    24  func nthenv(i int) string {
    25  	return envs[i]
    26  }
    27  
    28  func init() {
    29  	argc, argSz, errno := wasi.ArgsSizes()
    30  	if errno != 0 {
    31  		assert.Throw("args_sizes_get", "failed")
    32  	}
    33  
    34  	envc, envSz, errno := wasi.EnvironSizes()
    35  	if errno != 0 {
    36  		assert.Throw("environ_sizes_get", "failed")
    37  	}
    38  
    39  	// defensive: ensure size is zero when count is zero.
    40  	if argc == 0 {
    41  		argSz = 0
    42  	}
    43  	if envc == 0 {
    44  		envSz = 0
    45  	}
    46  
    47  	if argSz == 0 && envSz == 0 {
    48  		return
    49  	}
    50  
    51  	type uintptr32 = uint32
    52  
    53  	totalSize := uintptr(envSz) + uintptr(argSz) +
    54  		unsafe.Sizeof(string(""))*(uintptr(envc)+uintptr(argc))
    55  
    56  	buf := make([]byte, totalSize)
    57  	args = unsafe.Slice(
    58  		(*string)(unsafe.Pointer(unsafe.SliceData(buf))),
    59  		argc,
    60  	)
    61  
    62  	buf = buf[uintptr(argc)*unsafe.Sizeof(string("")):]
    63  	envs = unsafe.Slice(
    64  		(*string)(unsafe.Pointer(unsafe.SliceData(buf))),
    65  		envc,
    66  	)
    67  	buf = buf[uintptr(envc)*unsafe.Sizeof(string("")):]
    68  
    69  	if argSz != 0 {
    70  		argv := unsafe.Slice((*uintptr32)(unsafe.Pointer(unsafe.SliceData(args))), argc)
    71  		if wasi.ArgsGet(
    72  			unsafe.Pointer(unsafe.SliceData(argv)),
    73  			unsafe.Pointer(unsafe.SliceData(buf)),
    74  		) != 0 {
    75  			assert.Throw("args_get", "failed")
    76  		}
    77  
    78  		for argc > 0 {
    79  			argc--
    80  			start := argv[argc] - uintptr32(uintptr(unsafe.Pointer(unsafe.SliceData(buf))))
    81  			end := start
    82  			for buf[end] != 0 {
    83  				end++
    84  			}
    85  			args[argc] = unsafe.String(&buf[start], end-start)
    86  		}
    87  
    88  		buf = buf[argSz:]
    89  	}
    90  
    91  	if envSz != 0 {
    92  		envv := unsafe.Slice((*uintptr32)(unsafe.Pointer(unsafe.SliceData(envs))), envc)
    93  		if wasi.Environ(
    94  			unsafe.Pointer(unsafe.SliceData(envv)),
    95  			unsafe.Pointer(unsafe.SliceData(buf)),
    96  		) != 0 {
    97  			assert.Throw("environ_get", "failed")
    98  		}
    99  
   100  		for envc > 0 {
   101  			envc--
   102  			start := envv[envc] - uintptr32(uintptr(unsafe.Pointer(unsafe.SliceData(buf))))
   103  			end := start
   104  			for buf[end] != 0 {
   105  				end++
   106  			}
   107  			envs[envc] = unsafe.String(&buf[start], end-start)
   108  		}
   109  	}
   110  }