mojoshader_common.c
changeset 939 64cc93ee5a56
parent 870 f9e20269c20b
child 944 9f9fa9650772
--- a/mojoshader_common.c	Tue Nov 02 14:58:31 2010 -0400
+++ b/mojoshader_common.c	Wed Nov 03 22:54:17 2010 -0400
@@ -365,6 +365,9 @@
 
 void stringcache_destroy(StringCache *cache)
 {
+    if (cache == NULL)
+        return;
+
     MOJOSHADER_free f = cache->f;
     void *d = cache->d;
     size_t i;
@@ -386,5 +389,149 @@
     f(cache, d);
 } // stringcache_destroy
 
+
+
+ErrorList *errorlist_create(MOJOSHADER_malloc m, MOJOSHADER_free f, void *d)
+{
+    ErrorList *retval = (ErrorList *) m(sizeof (ErrorList), d);
+    if (retval != NULL)
+    {
+        memset(retval, '\0', sizeof (ErrorList));
+        retval->tail = &retval->head;
+        retval->m = m;
+        retval->f = f;
+        retval->d = d;
+    } // if
+
+    return retval;
+} // errorlist_create
+
+
+int errorlist_add(ErrorList *list, const char *fname,
+                  const int errpos, const char *str)
+{
+    return errorlist_add_fmt(list, fname, errpos, "%s", str);
+} // errorlist_add
+
+
+int errorlist_add_fmt(ErrorList *list, const char *fname,
+                      const int errpos, const char *fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    const int retval = errorlist_add_va(list, fname, errpos, fmt, ap);
+    va_end(ap);
+    return retval;
+} // errorlist_add_fmt
+
+
+int errorlist_add_va(ErrorList *list, const char *_fname,
+                     const int errpos, const char *fmt, va_list va)
+{
+    ErrorItem *error = (ErrorItem *) list->m(sizeof (ErrorItem), list->d);
+    if (error == NULL)
+        return 0;
+
+    char *fname = NULL;
+    if (_fname != NULL)
+    {
+        fname = (char *) list->m(strlen(_fname) + 1, list->d);
+        if (fname == NULL)
+        {
+            list->f(error, list->d);
+            return 0;
+        } // if
+        strcpy(fname, _fname);
+    } // if
+
+    char scratch[128];
+    va_list ap;
+    va_copy(ap, va);
+    const int len = vsnprintf(scratch, sizeof (scratch), fmt, ap);
+    va_end(ap);
+
+    char *failstr = (char *) list->m(len + 1, list->d);
+    if (failstr == NULL)
+    {
+        list->f(error, list->d);
+        list->f(fname, list->d);
+        return 0;
+    } // if
+
+    // If we overflowed our scratch buffer, that's okay. We were going to
+    //  allocate anyhow...the scratch buffer just lets us avoid a second
+    //  run of vsnprintf().
+    if (len < sizeof (scratch))
+        strcpy(failstr, scratch);  // copy it over.
+    else
+    {
+        va_copy(ap, va);
+        vsnprintf(failstr, len + 1, fmt, ap);  // rebuild it.
+        va_end(ap);
+    } // else
+
+    error->error.error = failstr;
+    error->error.filename = fname;
+    error->error.error_position = errpos;
+    error->next = NULL;
+
+    list->tail->next = error;
+    list->tail = error;
+
+    list->count++;
+    return 1;
+} // errorlist_add_va
+
+
+MOJOSHADER_error *errorlist_flatten(ErrorList *list)
+{
+    if (list->count == 0)
+        return NULL;
+
+    int total = 0;
+    MOJOSHADER_error *retval = (MOJOSHADER_error *)
+            list->m(sizeof (MOJOSHADER_error) * list->count, list->d);
+    if (retval == NULL)
+        return NULL;
+
+    ErrorItem *item = list->head.next;
+    while (item != NULL)
+    {
+        ErrorItem *next = item->next;
+        // reuse the string allocations
+        memcpy(&retval[total], &item->error, sizeof (MOJOSHADER_error));
+        list->f(item, list->d);
+        item = next;
+        total++;
+    } // while
+
+    assert(total == list->count);
+    list->count = 0;
+    list->head.next = NULL;
+    list->tail = &list->head;
+    return retval;
+} // errorlist_flatten
+
+
+void errorlist_destroy(ErrorList *list)
+{
+    if (list == NULL)
+        return;
+
+    MOJOSHADER_free f = list->f;
+    void *d = list->d;
+    ErrorItem *item = list->head.next;
+    while (item != NULL)
+    {
+        ErrorItem *next = item->next;
+        f((void *) item->error.error, d);
+        f((void *) item->error.filename, d);
+        f(item, d);
+        item = next;
+    } // while
+    f(list, d);
+} // errorlist_destroy
+
+
 // end of mojoshader_common.c ...