diff --git a/attributes/schema_type_parse.c b/attributes/schema_type_parse.c
index 07b4f119becd8f52a821ec1ed3cc82e9fff440ab..9de255da6fc5986bb28a4565adb4a9709f05f74a 100644
--- a/attributes/schema_type_parse.c
+++ b/attributes/schema_type_parse.c
@@ -81,7 +81,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind)
         break;
       case MSTRO_STP_STR:
         res->str_minlen = 0;
-        res->str_maxlen = SIZE_MAX;
+        res->str_maxlen = MSTRO_STP_VAL_SIZE_MAX;
         res->str_excludedchars = NULL;
         break;
       case MSTRO_STP_EXCLSTR:
@@ -101,7 +101,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind)
         break;
       case MSTRO_STP_BLOB:
         res->blob_minlen = 0;
-        res->blob_maxlen = SIZE_MAX;
+        res->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX;
         break;
       case MSTRO_STP_ERROR:
         res->errmsg = NULL;
@@ -1238,10 +1238,19 @@ static void pcc_action_type_arguments_0(mstro_stp_context_t *__pcc_ctx, pcc_thun
 #define _0s ((const)__pcc_in->data.leaf.capt0.range.start)
 #define _0e ((const)__pcc_in->data.leaf.capt0.range.end)
     DEBUG("unnamed and keyword type arguments\n");
+    size_t l_a,l_l, l_tot;
+    struct mstro_stp_val *tmp;
+    LL_COUNT2(a,tmp,l_a,list_tail);
+    LL_COUNT2(l,tmp,l_l,list_tail);
+
     assert(a->kind == MSTRO_STP_LIST);
     assert(l->kind == MSTRO_STP_LIST);
     __=a;
-    LL_APPEND2(__,l,list_tail);
+    LL_CONCAT2(__,l,list_tail);
+
+    LL_COUNT2(__,tmp,l_tot,list_tail);
+    DEBUG("unnamed count %zu, named count %zu, total %zu\n", l_a, l_l, l_tot);
+
 #undef _0e
 #undef _0s
 #undef _0
@@ -3567,7 +3576,9 @@ void mstro_stp_destroy(mstro_stp_context_t *ctx) {
 
 #include "maestro/logging.h"
 
-#line 452 "schema_type_parse.peg"
+#define MIN(x,y) ((x)<(y) ? (x) : (y))
+
+#line 561 "schema_type_parse.peg"
 mstro_status
 mstro_schema_type_parse(const char *string, struct mstro_stp_val **res)
 {
@@ -3726,7 +3737,7 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXUINT: 
            result->uint_max = tmp->list_entry->maxuintval; break;
          default:
-           ERR("Illegal type restriction for unsigned integer: %d\n", tmp->kind);
+           ERR("Illegal type restriction for unsigned integer: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -3744,10 +3755,22 @@ mstro_stp_val__build_restricted_type(
        switch(tmp->list_entry->kind) {
          case MSTRO_STP_MININT: 
            result->int_min = tmp->list_entry->minintval; break;
+         case MSTRO_STP_MINUINT: 
+           if(tmp->list_entry->minuintval>(uint64_t)INT64_MAX) {
+             ERR("signed int min %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->minuintval);
+           }
+           result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->minuintval);
+           break;
          case MSTRO_STP_MAXINT: 
            result->int_max = tmp->list_entry->maxintval; break;
+         case MSTRO_STP_MAXUINT: 
+           if(tmp->list_entry->maxuintval>(uint64_t)INT64_MAX) {
+             ERR("signed int max %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->maxuintval);
+           }
+           result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->maxuintval);
+           break;
          default:
-           ERR("Illegal type restriction for signed integer: %d\n", tmp->kind);
+           ERR("Illegal type restriction for signed integer: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -3768,7 +3791,7 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXFLOAT: 
            result->float_max = tmp->list_entry->maxfloatval; break;
          default:
-           ERR("Illegal type restriction for float: %d\n", tmp->kind);
+           ERR("Illegal type restriction for float: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -3789,17 +3812,172 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXDOUBLE: 
            result->double_max = tmp->list_entry->maxdoubleval; break;
          default:
-           ERR("Illegal type restriction for double: %d\n", tmp->kind);
+           ERR("Illegal type restriction for double: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
       };
       break;
       }
-    case MSTRO_STP_STR:
-    case MSTRO_STP_REGEX:
-    case MSTRO_STP_BLOB:
+    case MSTRO_STP_STR: {
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_EXCLSTR: 
+           result->str_excludedchars = tmp->list_entry->exclstrval;
+           tmp->list_entry->exclstrval = NULL; // passed on to result
+           break;
+         case MSTRO_STP_MAXINT:
+           result->str_maxlen = tmp->list_entry->maxintval;
+           break;
+         case MSTRO_STP_MAXUINT:
+           result->str_maxlen = tmp->list_entry->maxuintval; 
+           break;
+         case MSTRO_STP_MININT:
+           result->str_minlen = tmp->list_entry->minintval; 
+           break;
+         case MSTRO_STP_MINUINT:
+           result->str_minlen = tmp->list_entry->minuintval; 
+           break;
+         default:
+           ERR("Illegal type restriction for string: %d\n", tmp->list_entry->kind);
+       }
+       /* clamp to protobuf permitted max */
+       if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) {
+         if(result->str_minlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("string min %zu larger than supported maximum, clamping\n", 
+               result->str_minlen);
+           result->str_minlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) {
+         if(result->str_maxlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("string max %zu larger than supported maximum, clamping\n", 
+               result->str_maxlen);
+           result->str_maxlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       
+       mstro_stp_val_dispose(tmp);
+      };
+      break;
+      }
+    case MSTRO_STP_BLOB: {
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_MAXINT:
+           result->blob_maxlen = tmp->list_entry->maxintval;
+           break;
+         case MSTRO_STP_MAXUINT:
+           result->blob_maxlen = tmp->list_entry->maxuintval; 
+           break;
+         case MSTRO_STP_MININT:
+           result->blob_minlen = tmp->list_entry->minintval; 
+           break;
+         case MSTRO_STP_MINUINT:
+           result->blob_minlen = tmp->list_entry->minuintval; 
+           break;
+         default:
+           ERR("Illegal type restriction for blob: %d\n", tmp->list_entry->kind);
+       }
+       /* clamp to protobuf permitted max */
+       if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) {
+         if(result->blob_minlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("blob min %zu larger than supported maximum, clamping\n", 
+               result->blob_minlen);
+           result->blob_minlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) {
+         if(result->blob_maxlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("blob max %zu larger than supported maximum, clamping\n", 
+               result->blob_maxlen);
+           result->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       mstro_stp_val_dispose(tmp);
+      };
+      break;
+      }
+
+    case MSTRO_STP_REGEX: {
+      struct mstro_stp_val *patterns = NULL;
+      result->regex_numpatterns=0;
+
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       DEBUG("looking at %d\n", tmp->list_entry->kind);
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_ICASE:
+           result->regex_ignorecase = tmp->list_entry->icase;
+           break;
+         case MSTRO_STP_NAME:
+           result->regex_name = tmp->list_entry->nameval;
+           tmp->list_entry->nameval = NULL; // moved to result
+           DEBUG("regex name '%s'\n", result->regex_name);
+           break;
+         case MSTRO_STP_STRVAL: 
+           /* patterns; push to pattern stack and count */
+           LL_PREPEND2(patterns,tmp,list_tail);
+           result->regex_numpatterns++;
+           tmp=NULL; /* moved to patterns stack */
+           DEBUG("Found pattern |%s|, have %zu\n", 
+                 patterns->list_entry->strval, 
+                 result->regex_numpatterns);
+           break;
+         default:
+           ERR("Illegal type arg or restriction for regex: %d\n", tmp->list_entry->kind);
+       }
+       if(tmp!=NULL)
+         mstro_stp_val_dispose(tmp);
+      };
+      if(result->regex_numpatterns==0) {
+        ERR("Regex without any pattern, defaulting to \"\"\n");
+        result->regex_numpatterns=1;
+        result->regex_patterns = malloc(sizeof(char*));
+        if(result->regex_patterns == NULL) {
+          ERR("Failed to allocate for regex patterns\n");
+          abort();
+        }
+        result->regex_patterns[0] = strdup("");
+        if(result->regex_patterns[0] == NULL) {
+          ERR("Failed to allocate for regex\n");
+          abort();
+        }
+      } else {
+        result->regex_patterns = malloc(sizeof(char*)*result->regex_numpatterns);
+        if(result->regex_patterns == NULL) {
+          ERR("Failed to allocate for regex patterns\n");
+          abort();
+        }
+        /* insert, reversing */
+       struct mstro_stp_val *tmp = patterns;
+       size_t i;
+        for(i=result->regex_numpatterns, tmp = patterns;
+            i-->0;
+            tmp = tmp->list_tail) {
+          result->regex_patterns[i] = tmp->list_entry->strval;
+	  tmp->list_entry->strval = NULL; /* moved to result */
+        }
+        mstro_stp_val_dispose(patterns);
+      }
+
+
       break;
+      }
     default:
       ERR("type parse intermediate kind %d should not be returned\n",
           typename->kind);
diff --git a/attributes/schema_type_parse.h b/attributes/schema_type_parse.h
index 5ab782e67c8a17ee6f80e8d8ac924e926b64154d..ce7f22e3449416de2c03b84eddd9dcec359b454c 100644
--- a/attributes/schema_type_parse.h
+++ b/attributes/schema_type_parse.h
@@ -13,7 +13,7 @@ struct mstro_stp_parser_ctx;
 
 enum mstro_stp_val_kind {
   /** error node */
-  MSTRO_STP_ERROR,
+  MSTRO_STP_ERROR = 0,
   /** plain values, should not be visible in final parse result nodes, but appear during parse */
   MSTRO_STP_INTVAL,
   MSTRO_STP_UINTVAL,
@@ -21,7 +21,7 @@ enum mstro_stp_val_kind {
   MSTRO_STP_DOUBLEVAL,
   MSTRO_STP_STRVAL,
   MSTRO_STP_BOOLVAL,
-  MSTRO_STP_MININT,
+  MSTRO_STP_MININT = 10,
   MSTRO_STP_MINUINT,
   MSTRO_STP_MINFLOAT,
   MSTRO_STP_MINDOUBLE,
@@ -29,13 +29,13 @@ enum mstro_stp_val_kind {
   MSTRO_STP_MAXUINT,
   MSTRO_STP_MAXFLOAT,
   MSTRO_STP_MAXDOUBLE,
-  MSTRO_STP_EXCLSTR,
+  MSTRO_STP_EXCLSTR = 20,
   MSTRO_STP_ICASE,
   MSTRO_STP_NAME,
   MSTRO_STP_LIST,
 
   /** user-facing node types */
-  MSTRO_STP_BOOL,
+  MSTRO_STP_BOOL = 64,
   MSTRO_STP_UINT,
   MSTRO_STP_INT,
   MSTRO_STP_FLOAT,
@@ -45,7 +45,14 @@ enum mstro_stp_val_kind {
   MSTRO_STP_BLOB
 };
 
-/** User-facing: the parsed type. This is also serving as documentation for the permitted restrictions for types. */
+/** User-facing: Protobuf imposes a size limit on strings and blobs
+ ** (because they need to fit a single message) */
+
+#define MSTRO_STP_VAL_SIZE_MAX ((uint64_t) 1U<<31)
+
+/** User-facing: the parsed type. This is also serving as
+ ** documentation for the permitted restrictions for types. */
+
 struct mstro_stp_val {
   enum mstro_stp_val_kind kind;
   union {
@@ -96,8 +103,8 @@ struct mstro_stp_val {
      };
 
    struct {
-     size_t  str_minlen;
-     size_t  str_maxlen;
+     uint64_t str_minlen;
+     uint64_t str_maxlen;
      char    *str_excludedchars;
      };
 
@@ -109,8 +116,8 @@ struct mstro_stp_val {
      };
 
    struct {
-     size_t blob_minlen;
-     size_t blob_maxlen;
+     uint64_t blob_minlen;
+     uint64_t blob_maxlen;
      };
    };
 
diff --git a/attributes/schema_type_parse.peg b/attributes/schema_type_parse.peg
index 3c6e2fd98f5e90a7e0d558377358eb426f0b039e..620a0a594bdade6ebe6f60293281e3ea4da241cc 100644
--- a/attributes/schema_type_parse.peg
+++ b/attributes/schema_type_parse.peg
@@ -67,7 +67,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind)
         break;
       case MSTRO_STP_STR:
         res->str_minlen = 0;
-	res->str_maxlen = SIZE_MAX;
+	res->str_maxlen = MSTRO_STP_VAL_SIZE_MAX;
 	res->str_excludedchars = NULL;
 	break;
       case MSTRO_STP_EXCLSTR:
@@ -87,7 +87,7 @@ mstro_stp_val_alloc(enum mstro_stp_val_kind kind)
 	break;
       case MSTRO_STP_BLOB:
         res->blob_minlen = 0;
-	res->blob_maxlen = SIZE_MAX;
+	res->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX;
 	break;
       case MSTRO_STP_ERROR:
         res->errmsg = NULL;
@@ -174,7 +174,7 @@ struct mstro_stp_parser_ctx;
 
 enum mstro_stp_val_kind {
   /** error node */
-  MSTRO_STP_ERROR,
+  MSTRO_STP_ERROR = 0,
   /** plain values, should not be visible in final parse result nodes, but appear during parse */
   MSTRO_STP_INTVAL,
   MSTRO_STP_UINTVAL,
@@ -182,7 +182,7 @@ enum mstro_stp_val_kind {
   MSTRO_STP_DOUBLEVAL,
   MSTRO_STP_STRVAL,
   MSTRO_STP_BOOLVAL,
-  MSTRO_STP_MININT,
+  MSTRO_STP_MININT = 10,
   MSTRO_STP_MINUINT,
   MSTRO_STP_MINFLOAT,
   MSTRO_STP_MINDOUBLE,
@@ -190,13 +190,13 @@ enum mstro_stp_val_kind {
   MSTRO_STP_MAXUINT,
   MSTRO_STP_MAXFLOAT,
   MSTRO_STP_MAXDOUBLE,
-  MSTRO_STP_EXCLSTR,
+  MSTRO_STP_EXCLSTR = 20,
   MSTRO_STP_ICASE,
   MSTRO_STP_NAME,
   MSTRO_STP_LIST,
   
   /** user-facing node types */
-  MSTRO_STP_BOOL,
+  MSTRO_STP_BOOL = 64,
   MSTRO_STP_UINT,
   MSTRO_STP_INT,
   MSTRO_STP_FLOAT,
@@ -205,8 +205,15 @@ enum mstro_stp_val_kind {
   MSTRO_STP_REGEX,
   MSTRO_STP_BLOB
 };
-   
-/** User-facing: the parsed type. This is also serving as documentation for the permitted restrictions for types. */
+
+/** User-facing: Protobuf imposes a size limit on strings and blobs
+ ** (because they need to fit a single message) */
+
+#define MSTRO_STP_VAL_SIZE_MAX ((uint64_t) 1U<<31)
+
+/** User-facing: the parsed type. This is also serving as
+ ** documentation for the permitted restrictions for types. */
+
 struct mstro_stp_val {
   enum mstro_stp_val_kind kind;
   union {
@@ -257,8 +264,8 @@ struct mstro_stp_val {
      };
      
    struct {
-     size_t  str_minlen;
-     size_t  str_maxlen;
+     uint64_t str_minlen;
+     uint64_t str_maxlen;
      char    *str_excludedchars;
      };
      
@@ -270,8 +277,8 @@ struct mstro_stp_val {
      };
      
    struct {
-     size_t blob_minlen;
-     size_t blob_maxlen;
+     uint64_t blob_minlen;
+     uint64_t blob_maxlen;
      };
    };
 
@@ -325,10 +332,19 @@ user_type_name <- ide:identifier { $$ = ide; DEBUG("User-defined type name %s\n"
 ## Type argumets: empty restrictions, keyword=value arguments, unnamed arguments, or both
 type_arguments <- '(' a:unnamed_args ','  l:type_restriction_list ')' {
                          DEBUG("unnamed and keyword type arguments\n");
+                         size_t l_a,l_l, l_tot;
+			 struct mstro_stp_val *tmp;
+			 LL_COUNT2(a,tmp,l_a,list_tail);
+			 LL_COUNT2(l,tmp,l_l,list_tail);
+			 
 			 assert(a->kind == MSTRO_STP_LIST);
 			 assert(l->kind == MSTRO_STP_LIST);
 			 $$=a;
-			 LL_APPEND2($$,l,list_tail);
+			 LL_CONCAT2($$,l,list_tail);
+			 
+			 LL_COUNT2($$,tmp,l_tot,list_tail);
+ 			 DEBUG("unnamed count %zu, named count %zu, total %zu\n", l_a, l_l, l_tot);
+
 		      }
 	        / '(' a:unnamed_args ')' {
 		         $$=a;
@@ -548,7 +564,9 @@ EOF  <- !.
 %%
 #include "maestro/logging.h"
 
-#line 452 "schema_type_parse.peg"
+#define MIN(x,y) ((x)<(y) ? (x) : (y))
+
+#line 561 "schema_type_parse.peg"
 mstro_status
 mstro_schema_type_parse(const char *string, struct mstro_stp_val **res)
 {
@@ -707,7 +725,7 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXUINT: 
            result->uint_max = tmp->list_entry->maxuintval; break;
          default:
-           ERR("Illegal type restriction for unsigned integer: %d\n", tmp->kind);
+           ERR("Illegal type restriction for unsigned integer: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -725,10 +743,22 @@ mstro_stp_val__build_restricted_type(
        switch(tmp->list_entry->kind) {
          case MSTRO_STP_MININT: 
            result->int_min = tmp->list_entry->minintval; break;
+         case MSTRO_STP_MINUINT: 
+           if(tmp->list_entry->minuintval>(uint64_t)INT64_MAX) {
+             ERR("signed int min %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->minuintval);
+           }
+           result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->minuintval);
+           break;
          case MSTRO_STP_MAXINT: 
            result->int_max = tmp->list_entry->maxintval; break;
+         case MSTRO_STP_MAXUINT: 
+           if(tmp->list_entry->maxuintval>(uint64_t)INT64_MAX) {
+             ERR("signed int max %" PRIu64 "exceeds INT64_MAX\n", tmp->list_entry->maxuintval);
+           }
+           result->int_min = MIN((uint64_t)INT64_MAX,tmp->list_entry->maxuintval);
+           break;
          default:
-           ERR("Illegal type restriction for signed integer: %d\n", tmp->kind);
+           ERR("Illegal type restriction for signed integer: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -749,7 +779,7 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXFLOAT: 
            result->float_max = tmp->list_entry->maxfloatval; break;
          default:
-           ERR("Illegal type restriction for float: %d\n", tmp->kind);
+           ERR("Illegal type restriction for float: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
@@ -770,17 +800,172 @@ mstro_stp_val__build_restricted_type(
          case MSTRO_STP_MAXDOUBLE: 
            result->double_max = tmp->list_entry->maxdoubleval; break;
          default:
-           ERR("Illegal type restriction for double: %d\n", tmp->kind);
+           ERR("Illegal type restriction for double: %d\n", tmp->list_entry->kind);
        }
        
        mstro_stp_val_dispose(tmp);
       };
       break;
       }
-    case MSTRO_STP_STR:
-    case MSTRO_STP_REGEX:
-    case MSTRO_STP_BLOB:
+    case MSTRO_STP_STR: {
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_EXCLSTR: 
+           result->str_excludedchars = tmp->list_entry->exclstrval;
+           tmp->list_entry->exclstrval = NULL; // passed on to result
+           break;
+         case MSTRO_STP_MAXINT:
+           result->str_maxlen = tmp->list_entry->maxintval;
+           break;
+         case MSTRO_STP_MAXUINT:
+           result->str_maxlen = tmp->list_entry->maxuintval; 
+           break;
+         case MSTRO_STP_MININT:
+           result->str_minlen = tmp->list_entry->minintval; 
+           break;
+         case MSTRO_STP_MINUINT:
+           result->str_minlen = tmp->list_entry->minuintval; 
+           break;
+         default:
+           ERR("Illegal type restriction for string: %d\n", tmp->list_entry->kind);
+       }
+       /* clamp to protobuf permitted max */
+       if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) {
+         if(result->str_minlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("string min %zu larger than supported maximum, clamping\n", 
+               result->str_minlen);
+           result->str_minlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) {
+         if(result->str_maxlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("string max %zu larger than supported maximum, clamping\n", 
+               result->str_maxlen);
+           result->str_maxlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       
+       mstro_stp_val_dispose(tmp);
+      };
+      break;
+      }
+    case MSTRO_STP_BLOB: {
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_MAXINT:
+           result->blob_maxlen = tmp->list_entry->maxintval;
+           break;
+         case MSTRO_STP_MAXUINT:
+           result->blob_maxlen = tmp->list_entry->maxuintval; 
+           break;
+         case MSTRO_STP_MININT:
+           result->blob_minlen = tmp->list_entry->minintval; 
+           break;
+         case MSTRO_STP_MINUINT:
+           result->blob_minlen = tmp->list_entry->minuintval; 
+           break;
+         default:
+           ERR("Illegal type restriction for blob: %d\n", tmp->list_entry->kind);
+       }
+       /* clamp to protobuf permitted max */
+       if(tmp->list_entry->kind==MSTRO_STP_MININT||tmp->list_entry->kind==MSTRO_STP_MINUINT) {
+         if(result->blob_minlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("blob min %zu larger than supported maximum, clamping\n", 
+               result->blob_minlen);
+           result->blob_minlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       if(tmp->list_entry->kind==MSTRO_STP_MAXINT||tmp->list_entry->kind==MSTRO_STP_MAXUINT) {
+         if(result->blob_maxlen > MSTRO_STP_VAL_SIZE_MAX) {
+           ERR("blob max %zu larger than supported maximum, clamping\n", 
+               result->blob_maxlen);
+           result->blob_maxlen = MSTRO_STP_VAL_SIZE_MAX;
+         }
+       }
+       mstro_stp_val_dispose(tmp);
+      };
       break;
+      }
+
+    case MSTRO_STP_REGEX: {
+      struct mstro_stp_val *patterns = NULL;
+      result->regex_numpatterns=0;
+
+      while(args!=NULL) {
+       assert(args->kind==MSTRO_STP_LIST);
+       struct mstro_stp_val *tmp = args;
+       args = args->list_tail;
+       tmp->list_tail = NULL;
+       
+       DEBUG("looking at %d\n", tmp->list_entry->kind);
+       switch(tmp->list_entry->kind) {
+         case MSTRO_STP_ICASE:
+           result->regex_ignorecase = tmp->list_entry->icase;
+           break;
+         case MSTRO_STP_NAME:
+           result->regex_name = tmp->list_entry->nameval;
+           tmp->list_entry->nameval = NULL; // moved to result
+           DEBUG("regex name '%s'\n", result->regex_name);
+           break;
+         case MSTRO_STP_STRVAL: 
+           /* patterns; push to pattern stack and count */
+           LL_PREPEND2(patterns,tmp,list_tail);
+           result->regex_numpatterns++;
+           tmp=NULL; /* moved to patterns stack */
+           DEBUG("Found pattern |%s|, have %zu\n", 
+                 patterns->list_entry->strval, 
+                 result->regex_numpatterns);
+           break;
+         default:
+           ERR("Illegal type arg or restriction for regex: %d\n", tmp->list_entry->kind);
+       }
+       if(tmp!=NULL)
+         mstro_stp_val_dispose(tmp);
+      };
+      if(result->regex_numpatterns==0) {
+        ERR("Regex without any pattern, defaulting to \"\"\n");
+        result->regex_numpatterns=1;
+        result->regex_patterns = malloc(sizeof(char*));
+        if(result->regex_patterns == NULL) {
+          ERR("Failed to allocate for regex patterns\n");
+          abort();
+        }
+        result->regex_patterns[0] = strdup("");
+        if(result->regex_patterns[0] == NULL) {
+          ERR("Failed to allocate for regex\n");
+          abort();
+        }
+      } else {
+        result->regex_patterns = malloc(sizeof(char*)*result->regex_numpatterns);
+        if(result->regex_patterns == NULL) {
+          ERR("Failed to allocate for regex patterns\n");
+          abort();
+        }
+        /* insert, reversing */
+       struct mstro_stp_val *tmp = patterns;
+       size_t i;
+        for(i=result->regex_numpatterns, tmp = patterns;
+            i-->0;
+            tmp = tmp->list_tail) {
+          result->regex_patterns[i] = tmp->list_entry->strval;
+	  tmp->list_entry->strval = NULL; /* moved to result */
+        }
+        mstro_stp_val_dispose(patterns);
+      }
+
+
+      break;
+      }
     default:
       ERR("type parse intermediate kind %d should not be returned\n",
           typename->kind);
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 8d63ed47589fd2d7b48dadf988045fcd7f95011a..76af787fd946abc1935468028ca0c06ce1f3d737 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -51,6 +51,9 @@ LDADD = $(top_builddir)/libmaestro.la
 check_HEADERS = cheat.h
 
 TESTS = check_version check_init\
+	check_schema_parse \
+	check_type_parser \
+	check_symtab \
 	check_protobuf_c \
 	check_transport_gfs \
         check_declare \
@@ -64,14 +67,11 @@ TESTS = check_version check_init\
 	run_demo.sh \
         check_pool_manager \
 	check_pm_declare.sh \
-	check_pm_interlock.sh
+	check_pm_interlock.sh 
 
-#	will come when 46-* branch is completely merged
-#	check_schema_parse \
-#	check_type_parser \
-#	check_symtab 
-
-# too expensive:	check_pool_local_multi 
+# too expensive, actually more of a benchmark:
+#	check_pool_local_multi 
+# broken for now:
 # 	check_mempool 
 
 check_PROGRAMS = check_version check_init \
diff --git a/tests/check_schema_parse.c b/tests/check_schema_parse.c
index bf72e7d23cf1beeec415996e32b8be32d9950523..cc8b6f5ae477dbba9558326365e43b4a9cbc66ef 100644
--- a/tests/check_schema_parse.c
+++ b/tests/check_schema_parse.c
@@ -53,8 +53,9 @@
 #define XSTRINGIFY(s) #s
 #define STRINGIFY(s) XSTRINGIFY(s) 
 
-#define CORE_YAML STRINGIFY(TOPSRCDIR) "/attributes/maestro-core.yaml"
-#define USER_YAML STRINGIFY(TOPSRCDIR) "/attributes/user.yaml"
+#define CORE_YAML STRINGIFY(TOPSRCDIR)  "/attributes/maestro-core.yaml"
+#define USER_YAML STRINGIFY(TOPSRCDIR)  "/attributes/user.yaml"
+#define ECMWF_YAML STRINGIFY(TOPSRCDIR) "/attributes/ecmwf.yaml"
 
 #define SAMPLE_YAML_STRING                      \
   ".maestro.core.cdo:\n"                        \
@@ -67,7 +68,7 @@
 
 
 CHEAT_TEST(core_schema_parse,
-           mstro_schema s1, s2;
+           mstro_schema s1, s2, s3;
            mstro_attribute_dict dict;
            mstro_status s=MSTRO_OK;
 
@@ -77,6 +78,8 @@ CHEAT_TEST(core_schema_parse,
 
            s=mstro_schema_parse_from_file(CORE_YAML, &s1);
            if(MSTRO_OK!=s) {
+             /* clean up successful one so that valgrind is happy
+              * even on failure */
              cheat_assert(MSTRO_OK==mstro_schema_free(s2));
            }
            cheat_assert(MSTRO_OK==s);
@@ -85,9 +88,28 @@ CHEAT_TEST(core_schema_parse,
            /* cheat_assert(MSTRO_OK==mstro_schema_merge(s1, s2)); */
            /* cheat_yield(); */
 
-           cheat_assert(MSTRO_OK==mstro_attributes_parse(s1,SAMPLE_YAML_STRING, &dict));
+           s=mstro_schema_parse_from_file(ECMWF_YAML, &s3);
+           if(MSTRO_OK!=s) {
+             /* clean up successful ones so that valgrind is happy
+              * even on failure */
+             cheat_assert(MSTRO_OK==mstro_schema_free(s1));
+             cheat_assert(MSTRO_OK==mstro_schema_free(s2));
+           }
+           cheat_assert(MSTRO_OK==s);
+           cheat_yield();
+           
+
+           /* now use the merged schema to parse some sample defs */
+           cheat_assert(MSTRO_OK==mstro_attributes_parse(s1,
+                                                         SAMPLE_YAML_STRING,
+                                                         &dict));
            cheat_yield();
+
+
+           
            /* cheat_assert(MSTRO_OK==mstro_schema_add_from_file(CORE_YAML)); */
            /* cheat_assert(MSTRO_OK==mstro_schema_add_from_file(USER_YAML)); */
+
+           
            )
            
diff --git a/tests/check_type_parser.c b/tests/check_type_parser.c
index ddf6ffad0e8e5a46f2cbc0ac21e5afe022b6696e..ffe91b09601d68269355ab95a5f9462d86b5eeeb 100644
--- a/tests/check_type_parser.c
+++ b/tests/check_type_parser.c
@@ -53,20 +53,26 @@
 CHEAT_DECLARE(
     const char *strings[] = {
       /* built-in types, no restrictions */
-      "bool()", "uint()", "int()", "float()", "double()", "regex()", "str()", "blob()",
-          /* /\* typical restricted types *\/ */
-          "uint(max=10, min=7)",
-          "int(min=-17, max=42)",
-          "str(exclude='XYZ')", /* string that can not include the specified characters */
-          "str(min=42)",
-          "str(max=8)",
-          "str(max=8, min=8)",
-          "\tblob ( max = 4711) ",
-          "regex(';.*$',ignore_case=False, name='lisp comment')",
-           /* multiple patterns */
-          "regex('^$','^[ \\t\\n\\r\\v]*#.*$',ignore_case=true, name='empty line or shell block comment')",
-          /* FIXME: add nested types */
-          NULL,
+      "bool()", "uint()", "int()", "float()", "double()",
+      "str()", "blob()",
+      /* regex is also built-in but can't be used without args;
+       * see below */
+          
+      /* typical restricted types */
+      "uint(max=10, min=7)",
+      "int(min=-17, max=42)",
+      "str(exclude='XYZ')", /* string that can not include the
+                             * specified characters */
+      "str(min=42)",
+      "str(max=8)",
+      "str(max=8, min=8)",
+      "\tblob ( max = 4711) ",
+      "regex(';.*$',ignore_case=False, name='lisp comment')",
+      "regex(';.*$',ignore_case=True, name='lisp comment')",
+      /* multiple patterns */
+      "regex('^$','^[ \\t\\n\\r\\v]*#.*$',ignore_case=true, name='empty line or shell block comment')",
+      /* /\* FIXME: add nested types *\/ */
+      NULL,
           };
               )
 
@@ -75,7 +81,8 @@ CHEAT_TEST(core_schema_parse,
            struct mstro_stp_val *result;
            const char **s;
            for(s=strings; (*s)!=NULL; s++) {
-             /* FIXME: could be improved to also have expected parse results listed above and compare them */
+             /* FIXME: could be improved to also have expected parse
+              * results listed above and compare them */
              INFO("parsing type |%s|\n", *s);
              cheat_assert(MSTRO_OK==mstro_schema_type_parse(*s, &result));
              cheat_yield();