| git.druid.rocks | index | druid520 | kaboom | src/ | user/ | lib.nsc |
src/user/lib.nsc
/*
* tiny shared helpers every userspace program under src/user/ needs.
* unlike the kernel side (where ptr_byte_at gets duplicated separately
* into kfs.nsc/elf.nsc/fd.nsc, because each file's other needs
* genuinely differ) every userspace program needs exactly this same
* small set, so it's compiled once and linked into each program's
* binary instead of copy-pasted -- nsc has no #include, but nothing
* stops sharing one compiled object across multiple final links.
*/
global u8
ptr_byte_at(ptr base, u64 index)
{
ptr p;
u64 word;
p = base + index;
word = (u64)*p;
return (u8)(word & (u64)0xff);
}
/* stdio.nsc's fputs is the one remaining real caller -- every program
* under src/user/ that needs a string length now includes string.nsh
* and calls strlen instead (see string.nsc's own note on why stdio.nsc
* itself didn't make that same move). */
global u64
my_strlen(ptr s)
{
u64 n;
n = 0;
while(ptr_byte_at(s, n) != (u8)0)
{
n = n + (u64)1;
}
return n;
}
/* argv is a raw ptr to an array of ptr, 8 bytes per slot -- reading
* the i-th one is a plain 8-byte-aligned *ptr load, no packed-word
* trickery needed (unlike byte-at-a-time access) since each slot is
* exactly the granularity *ptr already works at. */
global ptr
argv_get(ptr argv, i32 i)
{
ptr slot;
slot = argv + (u64)i * (u64)8;
return (ptr)*slot;
}
/* writes val as decimal digits into buf (caller-owned, room for at
* least 20 bytes -- u64's max is 20 digits, no sign, no
* nul-terminator written since the caller already has the length).
* returns the number of digits written. same digit-extraction
* algorithm as the kernel's own print_udec (idt.nsc), adapted to
* fill a buffer left-to-right instead of printing directly. */
global u64
u64_to_dec(u64 val, ptr buf)
{
i8 tmp[20];
i32 i;
u64 v;
u64 n;
u64 j;
u64 word;
u64 wordoff;
u64 byteoff;
ptr dst;
i = 20;
v = val;
if(v == (u64)0)
{
i = i - 1;
tmp[i] = (i8)48;
}
while(v > (u64)0)
{
i = i - 1;
tmp[i] = (i8)(48 + (i32)(v % (u64)10));
v = v / (u64)10;
}
/* buf is a bare ptr, not a real array, so filling it is the same
* packed-word read-modify-write technique as every other
* byte-at-a-time write through a raw ptr in this kernel (see
* kfs_pwd for the kernel-side counterpart). */
n = (u64)20 - (u64)i;
j = 0;
while(j < n)
{
wordoff = j & ~(u64)7;
byteoff = j & (u64)7;
dst = buf + wordoff;
word = (u64)*dst;
word = word & ~((u64)0xff << (byteoff * (u64)8));
word = word | ((u64)(u8)tmp[(u64)i + j] << (byteoff * (u64)8));
*dst = (i64)word;
j = j + (u64)1;
}
return n;
}