#include "gbos.h" /* date: print the wall clock, UTC. * * The kernel hands back unix seconds (SYS_GETTIME); turning that into a date * is all bounded subtraction - no long division or shifts, which SDCC would * pull out of sm83.lib and link into the $A000 RAM window (see usr/uptime.c * and usr/build.sh). ~20k rounds for the day loop is a fraction of a second. * * Says so plainly when the clock has never been set: run ntpdate first. */ /* No initialized arrays: SDCC puts those in _INITIALIZED at $A000, the RAM window, and the image then overflows its bank ("buffer too small" out of makebin - see usr/ansi.c and usr/build.sh). String literals live in _CODE, so the tables are literals indexed by hand. */ #define MDAYS "\x1f\x1c\x1f\x1e\x1f\x1e\x1f\x1f\x1e\x1f\x1e\x1f" #define MNAME "JanFebMarAprMayJunJulAugSepOctNovDec" static void two(unsigned int v) { if (v < 10) putc('0'); putu(v); } static unsigned char leap(unsigned int y) { if (y & 3) return 0; if (y == 2100) return 0; /* good enough until then */ return 1; } void main(void) { unsigned char t[4]; union { unsigned long l; unsigned char b[4]; } u; unsigned long sec; unsigned int days = 0, year = 1970, h, m, i, dim; if (!gettime(t)) { puts("date: clock not set (run ntpdate)"); nl(); sexit(1); } u.b[0] = t[0]; u.b[1] = t[1]; u.b[2] = t[2]; u.b[3] = t[3]; sec = u.l; while (sec >= 86400UL) { sec -= 86400UL; days++; } h = 0; while (sec >= 3600UL) { sec -= 3600UL; h++; } m = 0; while (sec >= 60UL) { sec -= 60UL; m++; } for (;;) { /* years, then months */ unsigned int len = leap(year) ? 366 : 365; if (days < len) break; days -= len; year++; } for (i = 0; i < 12; i++) { dim = (unsigned char)MDAYS[i]; if (i == 1 && leap(year)) dim = 29; if (days < dim) break; days -= dim; } writes(MNAME + i * 3, 3); putc(' '); putu(days + 1); putc(' '); two(h); putc(':'); two(m); putc(':'); two((unsigned int)sec); puts(" UTC "); putu(year); nl(); }