summaryrefslogtreecommitdiff
path: root/05
diff options
context:
space:
mode:
authorpommicket <pommicket@gmail.com>2022-02-16 22:58:16 -0500
committerpommicket <pommicket@gmail.com>2022-02-16 22:58:16 -0500
commit6e1158f49aa014b801b171b358c47389e7f9964e (patch)
tree5702e0b1ce33dd58a42a0cdfa8d90267a82a6fb3 /05
parentb1e837afb44f9053763d6a654a5f7bb2757a39d4 (diff)
the last parts of the C standard library
Diffstat (limited to '05')
-rw-r--r--05/codegen.b10
-rw-r--r--05/errno.h6
-rw-r--r--05/float.h34
-rw-r--r--05/limits.h6
-rw-r--r--05/main.c26
-rw-r--r--05/stdio.h4
-rw-r--r--05/string.h14
-rw-r--r--05/time.h293
8 files changed, 361 insertions, 32 deletions
diff --git a/05/codegen.b b/05/codegen.b
index b89ab51..46354e9 100644
--- a/05/codegen.b
+++ b/05/codegen.b
@@ -2352,20 +2352,26 @@ function generate_push_expression
p = expr + 4
expr = generate_push_expression(statement, expr)
p = types + *4p
- if *2p == TYPE2_FUNCTION_POINTER goto deref_function_pointer
+ p += 1
+ if *1p == TYPE_FUNCTION goto deref_do_nothing ; dereferencing a function pointer does nothing
+ if *1p == TYPE_ARRAY goto deref_do_nothing ; dereferencing a pointer to array does nothing
generate_stack_dereference(statement, type)
- :deref_function_pointer ; dereferencing a function pointer does NOTHING
+ :deref_do_nothing
return expr
:generate_subscript
expr += 8
c = expr + 4 ; type 1
c = *4c
+ p = c + 1
expr = generate_push_expression(statement, expr)
d = expr + 4 ; type 2
d = *4d
expr = generate_push_expression(statement, expr)
generate_stack_add(statement, c, d, c)
+ p = type_is_array(p)
+ if p != 0 goto subscript_is_array
generate_stack_dereference(statement, type)
+ :subscript_is_array
return expr
:generate_dot_or_arrow
; @NONSTANDARD: we require that the 1st operand to . be an lvalue
diff --git a/05/errno.h b/05/errno.h
new file mode 100644
index 0000000..426f351
--- /dev/null
+++ b/05/errno.h
@@ -0,0 +1,6 @@
+#ifndef _ERRNO_H
+#define _ERRNO_H
+
+#include <stdc_common.h> // we define all the relevant things here
+
+#endif // _ERRNO_H
diff --git a/05/float.h b/05/float.h
new file mode 100644
index 0000000..6ae607d
--- /dev/null
+++ b/05/float.h
@@ -0,0 +1,34 @@
+#ifndef _FLOAT_H
+#define _FLOAT_H
+
+#define DBL_DIG 15
+#define DBL_EPSILON 2.2204460492503131e-16
+#define DBL_MANT_DIG 53
+#define DBL_MAX 1.7976931348623157e+308
+#define DBL_MAX_10_EXP 308
+#define DBL_MAX_EXP 1024
+#define DBL_MIN 2.2250738585072027e-308
+#define DBL_MIN_10_EXP (-307)
+#define DBL_MIN_EXP (-1021)
+#define FLT_DIG 6
+#define FLT_EPSILON 1.19209290e-07
+#define FLT_MANT_DIG 24
+#define FLT_MAX 3.40282347e+38
+#define FLT_MAX_10_EXP +38
+#define FLT_MAX_EXP 128
+#define FLT_MIN 1.17549435e-38
+#define FLT_MIN_10_EXP (-37)
+#define FLT_MIN_EXP (-125)
+#define FLT_RADIX 2
+#define FLT_ROUNDS 1
+#define LDBL_DIG DBL_DIG
+#define LDBL_EPSILON DBL_EPSILON
+#define LDBL_MANT_DIG DBL_MANT_DIG
+#define LDBL_MAX DBL_MAX
+#define LDBL_MAX_10_EXP DBL_MAX_10_EXP
+#define LDBL_MAX_EXP DBL_MAX_EXP
+#define LDBL_MIN DBL_MIN
+#define LDBL_MIN_10_EXP DBL_MIN_10_EXP
+#define LDBL_MIN_EXP DBL_MIN_EXP
+
+#endif // _FLOAT_H
diff --git a/05/limits.h b/05/limits.h
new file mode 100644
index 0000000..633e9ff
--- /dev/null
+++ b/05/limits.h
@@ -0,0 +1,6 @@
+#ifndef _LIMITS_H
+#define _LIMITS_H
+
+#include <stdc_common.h> // we define all the relevant constants here
+
+#endif // _LIMITS_H
diff --git a/05/main.c b/05/main.c
index 2dc7b81..0c991b7 100644
--- a/05/main.c
+++ b/05/main.c
@@ -4,30 +4,12 @@
#include <signal.h>
#include <stdlib.h>
#include <string.h>
-
-int compar(const void *a, const void *b) {
- int i = *(int *)a;
- int j = *(int *)b;
- if (i < j) return -1;
- if (i > j) return 1;
- return 0;
-}
+#include <time.h>
+#include <float.h>
int main(int argc, char **argv) {
- char buf[36];
- strcpy(buf, "Hello there there!");
-/* buf[36]='b'; */
- printf("%s\n",strstr(buf," ther"));
-
- static char str[] = "?a???b,,,#c";
- char *t;
-
- printf("%s\n", strtok(str, "?")); /* t points to the token "a" */
- printf("%s\n", strtok(NULL, ","));
- printf("%s\n", strtok(NULL, "#,"));
- printf("%s\n", strtok(NULL, "?"));
-
-
+ srand(time(NULL));
+ printf("%d\n",rand());
return 0;
}
diff --git a/05/stdio.h b/05/stdio.h
index e5a04cc..e474fca 100644
--- a/05/stdio.h
+++ b/05/stdio.h
@@ -1739,7 +1739,9 @@ int rename(const char *old, const char *new) {
char *tmpnam(char *s) {
struct timespec t = {0};
- do {
+ do {
+ // NB: we can't use rand() here because
+ // "The implementation shall behave as if no library function calls the rand function." C89 § 4.10.2.1
clock_gettime(CLOCK_MONOTONIC, &t); // use clock as a source of randomness
sprintf(s, "/tmp/C_%06u", t.tv_nsec % 1000000);
} while (access(s, F_OK) == 0); // if file exists, generate a new name
diff --git a/05/string.h b/05/string.h
index 02216b5..4b73101 100644
--- a/05/string.h
+++ b/05/string.h
@@ -163,21 +163,21 @@ char *strstr(const char *s1, const char *s2) {
return NULL;
}
-char *_strtok_str;
char *strtok(char *s1, const char *s2) {
- if (s1) _strtok_str = s1;
- if (!_strtok_str) return NULL;
- char *p = _strtok_str + strspn(_strtok_str, s2);
+ static char *str;
+ if (s1) str = s1;
+ if (!str) return NULL;
+ char *p = str + strspn(str, s2);
if (!*p) {
- _strtok_str = NULL;
+ str = NULL;
return NULL;
}
char *q = strpbrk(p, s2);
if (q) {
*q = 0;
- _strtok_str = q + 1;
+ str = q + 1;
} else {
- _strtok_str = NULL;
+ str = NULL;
}
return p;
}
diff --git a/05/time.h b/05/time.h
new file mode 100644
index 0000000..8207156
--- /dev/null
+++ b/05/time.h
@@ -0,0 +1,293 @@
+#ifndef _TIME_H
+#define _TIME_H
+
+#include <stdc_common.h>
+#define CLK_TCK 1000000000 // doesnt matter; clock() will always fail.
+
+typedef long clock_t;
+
+clock_t clock(void) {
+ // "If the processor time used is not available or its value cannot be represented, the function returns the value (clock_t)-1." C89 § 4.12.2.1
+ return -1;
+}
+
+double difftime(time_t time1, time_t time0) {
+ return (double)(time1 - time0);
+}
+
+time_t time(time_t *timer) {
+ struct timespec ts = {0};
+ if (clock_gettime(CLOCK_REALTIME, &ts) != 0) return -1;
+ if (timer) *timer = ts.tv_sec;
+ return ts.tv_sec;
+}
+
+
+// @NONSTANDARD(except in UTC+0): we don't support local time in timezones other than UTC+0.
+
+struct tm {
+ int tm_sec; /* seconds after the minute --- [0, 60] */
+ int tm_min; /* minutes after the hour --- [0, 59] */
+ int tm_hour; /* hours since midnight --- [0, 23] */
+ int tm_mday; /* day of the month --- [1, 31] */
+ int tm_mon; /* months since January --- [0, 11] */
+ int tm_year; /* years since 1900 */
+ int tm_wday; /* days since Sunday --- [0, 6] */
+ int tm_yday; /* days since January 1 --- [0, 365] */
+ int tm_isdst; /* Daylight Saving Time flag */
+};
+
+
+void _gmtime_r(const time_t *timer, struct tm *tm) {
+ time_t t = *timer;
+ int year = 1970;
+ int days = t / 86400;
+ int leap_year;
+ int month;
+
+ tm->tm_isdst = 0;
+ tm->tm_wday = (4 + days) % 7; // jan 1 1970 was a thursday
+ while (1) {
+ leap_year = year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
+ int ydays = leap_year ? 366 : 365;
+ if (days < ydays) break;
+ days -= ydays;
+ ++year;
+ }
+ tm->tm_year = year - 1900;
+ tm->tm_yday = days;
+ for (month = 0; month < 12; ++month) {
+ int mdays;
+ switch (month) {
+ case 0: case 2: case 4: case 6: case 7: case 9: case 11:
+ mdays = 31;
+ break;
+ case 3: case 5: case 8: case 10:
+ mdays = 30;
+ break;
+ case 1:
+ mdays = 28 + leap_year;
+ break;
+ }
+ if (days < mdays) break;
+ days -= mdays;
+ }
+ tm->tm_mday = days + 1;
+ tm->tm_mon = month;
+ t %= 86400;
+ tm->tm_hour = t / 3600;
+ t %= 3600;
+ tm->tm_min = t / 60;
+ tm->tm_sec = t % 60;
+}
+
+time_t mktime(struct tm *tm) {
+ // @NONSTANDARD-ish.
+ // not implementing this -- note that the implementation has to support tm_* values
+ // outside of their proper ranges.
+ return (time_t)-1;
+
+}
+
+struct tm *gmtime(const time_t *timer) {
+ static struct tm result;
+ _gmtime_r(timer, &result);
+ return &result;
+}
+
+struct tm *localtime(const time_t *timer) {
+ static struct tm result;
+ _gmtime_r(timer, &result);
+ return &result;
+}
+
+static const char _wday_name[7][4] = {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
+};
+static const char _weekday_name[7][16] = {
+ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
+};
+static const char _mon_name[12][4] = {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+};
+static const char _month_name[12][16] = {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+};
+
+char *asctime(const struct tm *timeptr) {
+ // lifted from the (draft of the) C standard
+ static char result[32];
+ sprintf(result, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
+ _wday_name[timeptr->tm_wday],
+ _mon_name[timeptr->tm_mon],
+ timeptr->tm_mday, timeptr->tm_hour,
+ timeptr->tm_min, timeptr->tm_sec,
+ 1900 + timeptr->tm_year);
+ return result;
+}
+
+char *ctime(const time_t *timer) {
+ return asctime(localtime(timer));
+}
+
+size_t strftime(char *s, size_t maxsize, const char *format, const struct tm *tm) {
+ size_t n = 0, l;
+ char *name;
+
+ while (*format) {
+ if (*format == '%') {
+ ++format;
+ int c = *format++;
+ switch (c) {
+ case 'a':
+ if (n+4 >= maxsize) return 0;
+ strcpy(s, _wday_name[tm->tm_wday]);
+ s += 3;
+ n += 3;
+ break;
+ case 'A':
+ name = _weekday_name[tm->tm_wday];
+ l = strlen(name);
+ if (n+l+1 >= maxsize) return 0;
+ strcpy(s, name);
+ s += l;
+ n += l;
+ break;
+ case 'b':
+ if (n+4 >= maxsize) return 0;
+ strcpy(s, _mon_name[tm->tm_mon]);
+ s += 3;
+ n += 3;
+ break;
+ case 'B':
+ name = _month_name[tm->tm_mon];
+ l = strlen(name);
+ if (n+l+1 >= maxsize) return 0;
+ strcpy(s, name);
+ s += l;
+ n += l;
+ break;
+ case 'c':
+ if (n+32 >= maxsize) return 0;
+ sprintf(s, "%s %02d %s %d %02d:%02d:%02d %s UTC",
+ _wday_name[tm->tm_wday], tm->tm_mday, _mon_name[tm->tm_mon],
+ 1900+tm->tm_year, (tm->tm_hour + 11) % 12 + 1, tm->tm_min, tm->tm_sec,
+ tm->tm_hour >= 12 ? "PM" : "AM");
+ s += 31;
+ n += 31;
+ break;
+ case 'd':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_mday);
+ s += 2;
+ n += 2;
+ break;
+ case 'H':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_hour);
+ s += 2;
+ n += 2;
+ break;
+ case 'I':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", (tm->tm_hour + 11) % 12 + 1);
+ s += 2;
+ n += 2;
+ break;
+ case 'j':
+ if (n+4 >= maxsize) return 0;
+ sprintf(s, "%03d", tm->tm_yday + 1);
+ s += 3;
+ n += 3;
+ break;
+ case 'm':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_mon + 1);
+ s += 2;
+ n += 2;
+ break;
+ case 'M':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_min);
+ s += 2;
+ n += 2;
+ break;
+ case 'p':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%s", tm->tm_hour >= 12 ? "PM" : "AM");
+ s += 2;
+ n += 2;
+ break;
+ case 'S':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_sec);
+ s += 2;
+ n += 2;
+ break;
+ case 'w':
+ if (n+2 >= maxsize) return 0;
+ sprintf(s, "%d", tm->tm_wday);
+ s += 1;
+ n += 1;
+ break;
+ case 'x':
+ if (n+16 >= maxsize) return 0;
+ sprintf(s, "%s %02d %s %d",
+ _wday_name[tm->tm_wday], tm->tm_mday, _mon_name[tm->tm_mon],
+ 1900+tm->tm_year);
+ s += 15;
+ n += 15;
+ break;
+ case 'X':
+ if (n+16 >= maxsize) return 0;
+ sprintf(s, "%02d:%02d:%02d %s UTC",
+ (tm->tm_hour + 11) % 12 + 1, tm->tm_min, tm->tm_sec,
+ tm->tm_hour >= 12 ? "PM" : "AM");
+ s += 15;
+ n += 15;
+ break;
+ case 'y':
+ if (n+3 >= maxsize) return 0;
+ sprintf(s, "%02d", tm->tm_year % 100);
+ s += 2;
+ n += 2;
+ break;
+ case 'Y':
+ if (n+5 >= maxsize) return 0;
+ sprintf(s, "%d", tm->tm_year + 1900);
+ s += 4;
+ n += 4;
+ break;
+ case 'Z':
+ if (n+4 >= maxsize) return 0;
+ strcpy(s, "UTC");
+ s += 3;
+ n += 3;
+ break;
+ case '%':
+ if (n >= maxsize) return 0;
+ *s++ = '%';
+ n += 1;
+ break;
+ case 'U': // WEEK NUMBER OF THE YEAR? WHO GIVES A SHIT?
+ case 'W': // WEEK NUMBER OF THE YEAR MONDAY-BASED EDITION. IF YOU DIDNT ALREADY GET ENOUGH WEEK NUMBERS. FUCK YOU
+ default:
+ fprintf(stderr, "Bad strftime format.\n");
+ abort();
+
+ }
+ } else {
+ if (n >= maxsize) return 0;
+ *s++ = *format++;
+ n += 1;
+ }
+ }
+ if (n >= maxsize) return 0;
+ *s = 0;
+ #undef _Push_str
+ return n;
+}
+
+#endif // _TIME_H