Overview
Comment: | check in missing files |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
269baab90a0d97cbfb1984d1590ea42b |
User & Date: | lexi on 2019-08-22 08:45:23 |
Other Links: | manifest | tags |
Context
2019-08-22
| ||
08:52 | add tests for linear allocators, fix dumb bug in kmheapf() that caused it to return an error on success check-in: f37ee769c9 user: lexi tags: trunk | |
08:45 | check in missing files check-in: 269baab90a user: lexi tags: trunk | |
08:44 | add kmlini() and kmlina() functions; restructure allocation functions to work more reasonably (returning a tuple struct instead of making a user pass in a void**); update docs accordingly check-in: acb4a9944e user: lexi tags: trunk | |
Changes
Added mod/kcli/kcli.md version [09b7990027].
1 +# kcli 2 +**kcli** is a module that implements common routines used by command-line utilities, such as option parsing, usage display, and more. 3 + 4 +## functions 5 + 6 +### kcli_usage(kcli_set, kiochan) 7 +kcli_usage() takes a `kcli_set` and prints a succinct usage summary to a [kiochan](../kio/kio.md). 8 + 9 +## types 10 + 11 +### struct kcli_set 12 +`kcli_set` is a struct containing information about your program, such as its name, a synopsis of its function, a pointer to `argv`, and a list of `kcli_opt`s. 13 + 14 + * `const char* name` - program name (if null, will be determined from argv instead) 15 + * `size_t argc` - the number of arguments in the `argv` array. 16 + * `const char** argv` - the `argv` pointer passed to the `entry` function, representing the command-line arguments passed to the program. 17 + * `const char* desc` - program description 18 + * `const kcli_param* params` - a list of options expected by the program. 19 + * `size_t paramc` - the number of params in the list to process. 20 + * `const kcli_opt* opts` - a list of options expected by the program. 21 + * `size_t optc` - the number of options in the list to process. 22 + 23 +a kcli_set might be used like so: 24 + 25 + #include <k/core.h> 26 + #include <k/io.h> 27 + #include <k/cli.h> 28 + stat entry(kenv e) { 29 + kcli_flag aardvark; 30 + kcli_flag zebra; 31 + char* user; 32 + char* password; 33 + long age; 34 + kcli_param params[] = { 35 + { "user", kcli_param_string, kcli_class_required, 36 + &user, "the user to log in as" } 37 + // or Kcli_param(user,string,required,"the user to log in as"), 38 + 39 + { "age", kcli_param_dec, kcli_class_optional, 40 + &age, "the age of the user" } 41 + // or Kcli_param(age,dec,optional,"the age of the user"), 42 + }; 43 + kcli_opt options[] = { 44 + { 'a', "aardvark", kcli_opt_flag, &aardvark, 45 + "a nocturnal burrowing mammal" }, 46 + // or Kcli_opt(aardvark, 'a', flag, "a nocturnal burrowing mammal") 47 + { 'z', "zebra", kcli_opt_flag, &zebra, 48 + "a striped equine" }, 49 + { 'p', "password", kcli_opt_string, &password, 50 + "the password to log in with" } 51 + }; 52 + kcli_set argset = { 53 + "demo", e.argc, e.argv, 54 + "a demonstration of the kcli_set type", 55 + params, Kmsz(params), 56 + options, Kmsz(options) 57 + }, 58 + size_t args_parsed = kcli_parse(&argset); 59 + if (args_parsed == 0) { kcli_usage(&me, e.err); return 1; } 60 + 61 + return 0; 62 + } 63 + 64 +### struct kcli_opt 65 +a `kcli_opt` is a representation of a command-line flag and its function. each option must have a unique `id` and/or a unique `name`. 66 + 67 + * `char id` - the short single-character form of the flag (or NUL for no short form) 68 + * `const char* name` - the long string form of the flag (or NULL for no long form) 69 + * `kcli_opt_kind kind` - enum that describes how the flag will function 70 + * `void* val` - a pointer to an appropriate type to store the return value in. 71 + * `const char* desc` - a description of the flag's purpose and function (or NULL for no description) 72 + 73 +#### enum kcli_opt_kind 74 + 75 + * `kcli_opt_none` - flag is disabled and will not be shown in usage 76 + * `kcli_opt_string` - flag tells kcli to add a string to the list of expected parameters; appropriate string will be returned 77 + * `kcli_opt_oct` - flag tells kcli to add an octal number to the list of expected parameters 78 + * `kcli_opt_dec` - flag tells kcli to add a decimal number to the list of expected parameters 79 + * `kcli_opt_hex` - flag tells kcli to add a hexdecimal number to the list of expected parameters 80 + * `kcli_opt_flag` - flag is an option: will return `kcli_flag_on` if entered at least once, `kcli_flag_off` otherwise. 81 + * `kcli_opt_toggle` - flag toggles value on and off: will return `kcli_flag_on` if entered an odd number of times, `kcli_flag_off` otherwise. 82 + * `kcli_opt_accumulate` - flag increments a value every time it is entered; often used to implement `-v (--verbose)`-style options (e.g. `-vvvv` would return a value of `4`). 83 + * `kcli_opt_enum` - flag is one of a series of enumerated values, which will be matched against a table to yield the associated integer. 84 + 85 +### struct kcli_param 86 +`kcli_param` describes a parameter that may be passed to the program whether or not any flags are passed. 87 + 88 + * `const char* name` - a short name for the parameter 89 + * `kcli_param_kind kind` - the kind of parameter passed 90 + * `kcli_class class` - whether or not the parameter is optional 91 + * `void* val` - a pointer to an appropriate type of variable to fill 92 + * `const char* desc` - a description of the parameter's function 93 + 94 +#### enum kcli_param_kind 95 + * `kcli_param_none` - parameter is disabled and will not be expected or accepted 96 + * `kcli_param_string` - parameter will not be parsed; a raw string will be returned 97 + * `kcli_param_oct` - parameter will be parsed as an octal number 98 + * `kcli_param_dec` - parameter will be parsed as a decimal number 99 + * `kcli_param_hex` - parameter will be parsed as a hexadecimal number 100 + 101 +### enum kcli_class 102 + * `kcli_class_forbidden` - parameter may not be passed 103 + * `kcli_class_optional` - parameter may or may not be passed 104 + * `kcli_class_required` - parameter must be passed 105 + 106 +### enum kcli_flag 107 +results that an option of kind `kcli_opt_flag` can return. 108 + 109 + * `kcli_flag_off = 0` - flag is off 110 + * `kcli_flag_on = 1` - flag is on 111 + 112 +## macros 113 + 114 +### Kcli_param(field, kind, class, description) 115 +a convenience macro for filling out parameter lists. 116 + 117 +`Kcli_param(field,a,b,"description")` is transformed into: 118 + 119 + { "field", kcli_param_a, kcli_class_b, &field, "description" } 120 + 121 +### Kcli_opt(field, kind, class, description) 122 +a convenience macro for filling out option lists. 123 + 124 +`Kcli_opt(name,'n',string,"description")` is transformed into: 125 + 126 + { 'n', "name", kcli_opt_string, &name, "description" }
Added mod/kcore/okay.fn.c version [4f27230207].
1 +#include <k/core.h> 2 +#include <k/type.h> 3 +#include <k/internal.egroup.h> 4 + 5 +bool kokay(kcond val) { 6 + return (val % kglobal_module_offset) == 0; 7 +}
Added mod/kcore/syscall.fn.x86.lin.32.s version [78de383598].
1 +; kcore/syscall.fn.x86.lin.32.s 2 +; ~ lexi hale <lexi@hale.su> 3 +; 4 +; this function performs a syscall and stores its 5 +; results in the variables provided. this makes it 6 +; possible to bypass the hideous errno mechanism 7 +; altogether and access the error value of a 8 +; syscall directly. invoke as: 9 +; 10 +; void k_platform_syscall_raw(s32* result, u32* errno, 11 +; syscall, u8 valency, s32[] args) 12 + 13 +bits 32 14 +%include "../arch/posix/x86.lin.32.s" 15 +%include "../arch/x86.cdecl.32.s" 16 +; vim: ft=nasm 17 + 18 + 19 +%define result_ptr edi 20 +%define errno_ptr ebx 21 +%define valency ecx 22 +%define args esi 23 +%define opcode eax 24 + 25 +%macro handle_arg 1 26 + push dword [args] 27 + sub args, 4 28 + dec valency 29 + jz .perform_call 30 +%endmacro 31 + 32 +global k_platform_syscall_raw:function 33 +k_platform_syscall_raw: 34 + ; locals: rbx = s32* result 35 + ; r12 = u32* errno 36 + ; arg 0 = s32* result 37 + ; arg 1 = errno ptr 38 + ; arg 2 = syscall num 39 + ; arg 3 = valency 40 + ; arg 4 = args ptr 41 + 42 + ; store the locals in registers that 43 + ; are guaranteed not to be clobbered, 44 + ; saving us some cycles pushing to 45 + ; and popping back from the stack 46 + pop result_ptr 47 + pop errno_ptr 48 + pop edx ; opcode 49 + 50 + ; set up registers for the loop 51 + pop valency 52 + pop args ; ptr to args array 53 + mov eax, 4 54 + mul valency 55 + add args, eax ; adjust args pointer to point 56 + ; at end of array, so it can be 57 + ; trivially pushed in backwards 58 + 59 + ; this needs to go before the loop 60 + ; or it'll get clobbered 61 + mov opcode, edx ; syscall number 62 + 63 + ; automatically generate the code 64 + ; needed to move the arguments into 65 + ; their correct registers. see above 66 + %assign i 0 67 + %rep 6 68 + handle_arg i 69 + %assign i i+1 70 + %endrep 71 + 72 + ; valency >= 7. this is not valid, so 73 + ; we set our return value to 0 and the 74 + ; error number to its maximum value in 75 + ; order to indicate that the syscall 76 + ; was invalid 77 + mov dword [result_ptr], -1 78 + mov dword [errno_ptr], -1 79 + ret 80 + 81 + ; we have a valency match - perform the 82 + ; requested syscall already stored in eax 83 + .perform_call: sys.call 84 + 85 + ; check if an error has occurred, and 86 + ; jump to the error handling routine 87 + ; if necessary 88 + test sys.reg.ret, sys.reg.ret 89 + js .error 90 + 91 + ; move our return values into place and 92 + ; return to the caller (which should 93 + ; always be k_platform_syscall, btw) 94 + mov [result_ptr], sys.reg.ret 95 + mov dword [errno_ptr], 0 96 + ret 97 + 98 + .error: neg sys.reg.ret 99 + mov dword [result_ptr], -1 100 + mov [errno_ptr], sys.reg.ret 101 + ret
Added mod/kmem/lina.fn.c version [0011a847e1].
1 +/* lina.fn.c - kmlina() - linear allocate 2 + * ~ lexi hale <lexi@hale.su> 3 + * kmlina() allocates the requested amount of space on 4 + * the heap and returns a pointer to it. it allocates 5 + * this memory simply by growing the heap the proper 6 + * length. */ 7 + 8 +#include <k/mem.h> 9 +#include <k/def.h> 10 + 11 +#ifdef KFenv_posix 12 +# include <posix/posix.h> 13 +#endif 14 + 15 +kmres kmlina(sz size) { 16 + k_platform_syscall_arg 17 + top = (sz)kmlini(), 18 + newbrk = top + size; 19 + 20 + struct k_platform_syscall_answer a = k_platform_syscall 21 + (k_platform_syscall_brk, 1, &newbrk); 22 + 23 + kmres reply; 24 + 25 + if (a.error != 0) reply.cond = kmcond_no_room, 26 + reply.raw = 0; 27 + else reply.cond = kmcond_ok, 28 + reply.raw = (void*)a.ret; 29 + 30 + return reply; 31 +}
Added mod/kmem/lini.fn.c version [99be01eb40].
1 +/* lini.fn.c - kmlini() - initiate a linear segment 2 + * ~ lexi hale <lexi@hale.su> 3 + * this function is the initiator function for the 4 + * linear memory store. it simply returns the current 5 + * heap position by invoking the brk syscall with the 6 + * value `0`. (note that the brk syscall and the libc 7 + * wrapper have different behavior.) */ 8 + 9 +#include <k/mem.h> 10 +#include <k/def.h> 11 + 12 +#ifdef KFenv_posix 13 +# include <posix/posix.h> 14 +#endif 15 + 16 +/* returns void* instead of kmres because kmlini has 17 + * no failure state */ 18 +void* kmlini(void) { 19 + k_platform_syscall_arg zero = 0; 20 + /* brk adjusts the heap break then returns the new 21 + * break. by passing zero, we can get retrieve the 22 + * current heap break. */ 23 + struct k_platform_syscall_answer a = k_platform_syscall 24 + (k_platform_syscall_brk, 1, &zero); 25 + 26 + /* no point in checking for errors, since none can 27 + * actually occur; just return the kernel's answer. */ 28 + return (void*)a.ret; 29 +}