work on type inference some more
[ccc.git] / util.c
diff --git a/util.c b/util.c
index 91166fd..fa60ddc 100644 (file)
--- a/util.c
+++ b/util.c
@@ -2,54 +2,10 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <ctype.h>
 
 #include "util.h"
 
-struct list *list_cons(void *el, struct list *tail)
-{
-       struct list *res = safe_malloc(sizeof(struct list));
-       res->el = el;
-       res->tail = tail;
-       return res;
-}
-
-void list_free(struct list *head, void (*freefun)(void *))
-{
-       while (head != NULL) {
-               freefun(head->el);
-               head = head->tail;
-       }
-}
-
-void **list_to_array(struct list *list, int *num, bool reverse)
-{
-       int i = list_length(list);
-       *num = i;
-       void **ptr = safe_malloc(i*sizeof(void *));
-
-       struct list *r = list;
-       while(i > 0) {
-               if (reverse)
-                       ptr[--i] = r->el;
-               else
-                       ptr[*num-(--i)] = r->el;
-               struct list *t = r;
-               r = r->tail;
-               free(t);
-       }
-       return ptr;
-}
-
-int list_length(struct list *r)
-{
-       int i = 0;
-       while(r != NULL) {
-               i++;
-               r = r->tail;
-       }
-       return i;
-}
-
 int fromHex(char c)
 {
        if (c >= '0' && c <= '9')
@@ -73,35 +29,76 @@ char *escape_char(char c, char *buf, bool str)
        case '\v': strcpy(buf, "\\v"); break;
        case '\f': strcpy(buf, "\\f"); break;
        case '\r': strcpy(buf, "\\r"); break;
+       case '\\': strcpy(buf, "\\\\"); break;
        case '\'': strcpy(buf, str ? "'" : "\\'"); break;
        case '"': strcpy(buf, str ? "\\\"" : "\""); break;
        default:
-               if (c >= ' ' && c < 127) {
+               if (c >= ' ' && c < 127)
                        sprintf(buf, "%c", c);
-               } else {
+               else
                        sprintf(buf, "\\x%02x", (unsigned char)c);
-               }
                break;
        }
        return buf;
 }
 
+bool isodigit(char c)
+{
+       return c >= '0' && c <= '7';
+}
+
+int fromOctal(char c)
+{
+       if (isodigit(c))
+               return c-'0';
+       return -1;
+}
+
 char *unescape_char(char *c)
 {
-       //escape
        if (c[0] == '\\') {
-               switch (c[1]) {
-               case '0': c[1] = '\0'; break;
-               case '\'': c[1] = '\''; break;
-               case '\\': c[1] = '\\'; break;
-               case '"': c[1] = '"'; break;
-               case 'a': c[1] = '\a'; break;
-               case 'b': c[1] = '\b'; break;
-               case 't': c[1] = '\t'; break;
-               case 'v': c[1] = '\v'; break;
-               case 'f': c[1] = '\f'; break;
-               case 'r': c[1] = '\r'; break;
-               case 'x': c[3] = (fromHex(c[2])<<4)+fromHex(c[3]); c+=2; break;
+               if (c[1] == 'x' && isxdigit(c[2])) {
+                       //two hex
+                       if (isxdigit(c[3])) {
+                               c[3] = (fromHex(c[2])*16)+fromHex(c[3]);
+                               c+=2;
+                       //one hex
+                       } else {
+                               c[2] = fromHex(c[2]);
+                               c++;
+                       }
+               } else if (c[1] == '0' && isodigit(c[2])) {
+                       if (isodigit(c[3])) {
+                               //three octal
+                               if (isodigit(c[4])) {
+                                       c[4] = fromOctal(c[2])*64
+                                               +fromOctal(c[3])*8
+                                               +fromOctal(c[4]);
+                                       c+=2;
+                               //two octal
+                               } else {
+                                       c[3] = fromOctal(c[2])*8
+                                               +fromOctal(c[3]);
+                                       c+=2;
+                               }
+                       // one octal
+                       } else {
+                               c[2] = fromOctal(c[2]);
+                               c++;
+                       }
+               } else {
+                       switch (c[1]) {
+                       case '0': c[1] = '\0'; break;
+                       case '\'': c[1] = '\''; break;
+                       case '\\': c[1] = '\\'; break;
+                       case '"': c[1] = '"'; break;
+                       case 'a': c[1] = '\a'; break;
+                       case 'b': c[1] = '\b'; break;
+                       case 't': c[1] = '\t'; break;
+                       case 'v': c[1] = '\v'; break;
+                       case 'f': c[1] = '\f'; break;
+                       case 'r': c[1] = '\r'; break;
+                       }
                }
                c++;
        }
@@ -157,8 +154,24 @@ void *safe_malloc(size_t size)
 
 void *safe_strdup(const char *c)
 {
-       char *res = strdup(c);
+       size_t nchar = strlen(c);
+       char *res = malloc((nchar+1)*sizeof(char));
        if (res == NULL)
                pdie("strdup");
+       memcpy(res, c, nchar+1);
        return res;
 }
+
+FILE *safe_fopen(const char *path, const char *mode)
+{
+       FILE *res = fopen(path, mode);
+       if (res == NULL)
+               pdie("fopen");
+       return res;
+}
+
+void safe_fclose(FILE *file)
+{
+       if (fclose(file) == -1)
+               pdie("fclose");
+}