feat: add streq, printErr and printPadded
This commit is contained in:
1 parent
09239a27e8
commit
607eaff366
2 files changed
+202
No files matched your search
@@ -0,0 +1,75 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Only ever spawned by cwdtest.c, with no argv at all -- unlike every other
|
||||||
|
* *test / *target pair in this kernel (which rendezvous over a shared pipe
|
||||||
|
* handle passed as an argv string), this pair's whole point is that the
|
||||||
|
* KERNEL itself hands this process its starting directory at creation time
|
||||||
|
* (sched.c's threadCreate/threadCreateUser, via the new initialCwd helper
|
||||||
|
* that mirrors initialPgid's own "inherit from whoever is currently
|
||||||
|
* running" shape for Thread.pgid), never anything cwdtest.c has to pass
|
||||||
|
* explicitly.
|
||||||
|
*
|
||||||
|
* Proves inheritance first, then proves the inherited value is a real,
|
||||||
|
* independent COPY rather than shared state: this process's own later
|
||||||
|
* chdir() must not reach back into cwdtest.c's Thread.cwd (cwdtest.c's own
|
||||||
|
* post-wait getcwd() check is the other half of that proof).
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int streq(const char* a, const char* b)
|
||||||
|
{
|
||||||
|
while (*a && *a == *b) {
|
||||||
|
a++;
|
||||||
|
b++;
|
||||||
|
}
|
||||||
|
return *a == *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
print("cwdtarget: start, pid=");
|
||||||
|
printDec(userGetpid());
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
char cwdBuf[64];
|
||||||
|
long len = userGetcwd(cwdBuf, sizeof(cwdBuf));
|
||||||
|
if (len < 0 || !streq(cwdBuf, "/tmp/cwda")) {
|
||||||
|
print("cwdtarget: FAIL inherited cwd, got: ");
|
||||||
|
print(len < 0 ? "(error)" : cwdBuf);
|
||||||
|
print("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
print("cwdtarget: inherited-cwd-ok\n");
|
||||||
|
|
||||||
|
if (userChdir("/tmp/cwdb") != 0) {
|
||||||
|
print("cwdtarget: FAIL chdir /tmp/cwdb\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
len = userGetcwd(cwdBuf, sizeof(cwdBuf));
|
||||||
|
if (len < 0 || !streq(cwdBuf, "/tmp/cwdb")) {
|
||||||
|
print("cwdtarget: FAIL getcwd after own chdir, got: ");
|
||||||
|
print(len < 0 ? "(error)" : cwdBuf);
|
||||||
|
print("\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Relative path again -- must land at /tmp/cwdb/note, a COMPLETELY
|
||||||
|
different file than cwdtest.c's own /tmp/cwda/note despite the
|
||||||
|
identical relative name "note", since each process resolves it
|
||||||
|
against its own Thread.cwd. */
|
||||||
|
int fd = (int)userOpen("note", oCreate | oWriteOnly | oTrunc);
|
||||||
|
if (fd < 0) {
|
||||||
|
print("cwdtarget: FAIL create relative note in cwdb\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
const char* payload = "cwdb-payload";
|
||||||
|
unsigned long payloadLen = stringLength(payload);
|
||||||
|
if (userWrite(fd, payload, payloadLen) != (long)payloadLen) {
|
||||||
|
print("cwdtarget: FAIL write relative note in cwdb\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
userClose(fd);
|
||||||
|
print("cwdtarget: relative-write-cwdb-ok\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
+127
@@ -0,0 +1,127 @@
|
|||||||
|
#include "ulib.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Real ring-3 "date": the first live demo of rtc.c/sysTime's wall-clock
|
||||||
|
* time, spawned directly by kmain.c at boot exactly like nicetest.c above
|
||||||
|
* it -- fully synchronous, no injected keystroke or pipe rendezvous, so
|
||||||
|
* unlike most of this kernel's live demos this one has no scheduling-
|
||||||
|
* timing race to flake on at all.
|
||||||
|
*
|
||||||
|
* Deliberately duplicates (not shares) Howard Hinnant's civil-calendar
|
||||||
|
* algorithm rtc.c already uses: this file writes its OWN forward
|
||||||
|
* (civil -> epoch) and inverse (epoch -> civil) implementations from
|
||||||
|
* scratch, independent of the kernel side. Decoding the epoch userTime()
|
||||||
|
* returns and then re-encoding it back with this independent forward
|
||||||
|
* function must reproduce the exact same number, which proves this
|
||||||
|
* program's own encode/decode pair is a true bijection over the date it
|
||||||
|
* actually ran on -- a real, self-verifying round trip, not a print
|
||||||
|
* nobody checks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void printErr(const char* text)
|
||||||
|
{
|
||||||
|
userWrite(2, text, stringLength(text));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Zero-padded unsigned decimal, `width` digits minimum (e.g. printPadded(7, 2)
|
||||||
|
-> "07"). Never negative here -- every field this file ever passes in is
|
||||||
|
already a non-negative calendar component. */
|
||||||
|
static void printPadded(long value, int width)
|
||||||
|
{
|
||||||
|
char digits[16];
|
||||||
|
int len = 0;
|
||||||
|
long remaining = value;
|
||||||
|
|
||||||
|
if (remaining == 0)
|
||||||
|
digits[len++] = '0';
|
||||||
|
while (remaining > 0) {
|
||||||
|
digits[len++] = (char)('0' + (remaining % 10));
|
||||||
|
remaining /= 10;
|
||||||
|
}
|
||||||
|
while (len < width)
|
||||||
|
digits[len++] = '0';
|
||||||
|
|
||||||
|
for (int i = len - 1; i >= 0; i--)
|
||||||
|
userWrite(1, &digits[i], 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Howard Hinnant's days_from_civil -- forward direction, civil date to a
|
||||||
|
day count relative to 1970-01-01. See rtc.c for the same algorithm used
|
||||||
|
kernel-side; this copy is independent, not shared, on purpose (see file
|
||||||
|
header comment). */
|
||||||
|
static long daysFromCivil(long y, long m, long d)
|
||||||
|
{
|
||||||
|
y -= (m <= 2) ? 1 : 0;
|
||||||
|
long era = (y >= 0 ? y : y - 399) / 400;
|
||||||
|
long yoe = y - era * 400;
|
||||||
|
long doy = (153 * (m + (m > 2 ? -3 : 9)) + 2) / 5 + d - 1;
|
||||||
|
long doe = yoe * 365 + yoe / 4 - yoe / 100 + doy;
|
||||||
|
return era * 146097 + doe - 719468;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Howard Hinnant's civil_from_days -- the inverse direction, a day count
|
||||||
|
back to a civil date. */
|
||||||
|
static void civilFromDays(long z, long* outYear, long* outMonth, long* outDay)
|
||||||
|
{
|
||||||
|
z += 719468;
|
||||||
|
long era = (z >= 0 ? z : z - 146096) / 146097;
|
||||||
|
long doe = z - era * 146097;
|
||||||
|
long yoe = (doe - doe / 1460 + doe / 36524 - doe / 146096) / 365;
|
||||||
|
long yy = yoe + era * 400;
|
||||||
|
long doy = doe - (365 * yoe + yoe / 4 - yoe / 100);
|
||||||
|
long mp = (5 * doy + 2) / 153;
|
||||||
|
long dd = doy - (153 * mp + 2) / 5 + 1;
|
||||||
|
long mm = mp + (mp < 10 ? 3 : -9);
|
||||||
|
|
||||||
|
*outYear = yy + (mm <= 2 ? 1 : 0);
|
||||||
|
*outMonth = mm;
|
||||||
|
*outDay = dd;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
long epoch = userTime();
|
||||||
|
if (epoch <= 0) {
|
||||||
|
printErr("date: FAIL sysTime returned a non-positive epoch\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long days = epoch / 86400;
|
||||||
|
long secondsOfDay = epoch % 86400;
|
||||||
|
long hour = secondsOfDay / 3600;
|
||||||
|
long minute = (secondsOfDay % 3600) / 60;
|
||||||
|
long second = secondsOfDay % 60;
|
||||||
|
|
||||||
|
long year;
|
||||||
|
long month;
|
||||||
|
long day;
|
||||||
|
civilFromDays(days, &year, &month, &day);
|
||||||
|
|
||||||
|
if (year < 2020 || year > 2099) {
|
||||||
|
printErr("date: FAIL implausible year decoded\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
printPadded(year, 4);
|
||||||
|
userWrite(1, "-", 1);
|
||||||
|
printPadded(month, 2);
|
||||||
|
userWrite(1, "-", 1);
|
||||||
|
printPadded(day, 2);
|
||||||
|
userWrite(1, " ", 1);
|
||||||
|
printPadded(hour, 2);
|
||||||
|
userWrite(1, ":", 1);
|
||||||
|
printPadded(minute, 2);
|
||||||
|
userWrite(1, ":", 1);
|
||||||
|
printPadded(second, 2);
|
||||||
|
userWrite(1, "\n", 1);
|
||||||
|
printErr("date: printed-ok\n");
|
||||||
|
|
||||||
|
long roundTrip = daysFromCivil(year, month, day) * 86400 + hour * 3600 + minute * 60 + second;
|
||||||
|
if (roundTrip != epoch) {
|
||||||
|
printErr("date: FAIL roundtrip mismatch\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
printErr("date: roundtrip-ok\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user