diff --git a/attributes/maestro-core-yaml.h b/attributes/maestro-core-yaml.h index 487865da8680aee3e82c7a58b59585563fc2914d..42dc7e7c2644744d6d526924d26b87b8898ea7df 100644 --- a/attributes/maestro-core-yaml.h +++ b/attributes/maestro-core-yaml.h @@ -318,10 +318,38 @@ unsigned char maestro_core_yaml[] = { 0x6e, 0x64, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x20, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x2f, 0x55, 0x6e, 0x61, 0x6c, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x65, 0x64, 0x2e, 0x0a, 0x0a, 0x20, 0x20, 0x23, 0x20, 0x4c, - 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x23, 0x20, 0x44, - 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x0a, 0x0a, 0x0a, 0x23, 0x20, 0x28, 0x65, 0x6e, 0x64, 0x20, 0x6f, 0x66, - 0x20, 0x6d, 0x61, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x2d, 0x63, 0x6f, 0x72, - 0x65, 0x2e, 0x79, 0x61, 0x6d, 0x6c, 0x29, 0x0a, 0x0a + 0x61, 0x79, 0x6f, 0x75, 0x74, 0x73, 0x0a, 0x20, 0x20, 0x2d, 0x20, 0x6b, + 0x65, 0x79, 0x3a, 0x20, 0x22, 0x63, 0x64, 0x6f, 0x2e, 0x73, 0x63, 0x6f, + 0x70, 0x65, 0x2e, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x2e, 0x72, 0x65, + 0x67, 0x75, 0x6c, 0x61, 0x72, 0x2d, 0x31, 0x64, 0x2e, 0x65, 0x6c, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x22, 0x0a, 0x20, + 0x20, 0x20, 0x20, 0x74, 0x79, 0x70, 0x65, 0x3a, 0x20, 0x75, 0x69, 0x6e, + 0x74, 0x28, 0x29, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x72, 0x65, 0x71, 0x75, + 0x69, 0x72, 0x65, 0x64, 0x3a, 0x20, 0x46, 0x61, 0x6c, 0x73, 0x65, 0x0a, + 0x20, 0x20, 0x20, 0x20, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c, 0x74, 0x3a, + 0x20, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, + 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x3a, 0x20, 0x45, 0x6c, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2d, 0x73, 0x69, 0x7a, 0x65, 0x20, 0x69, + 0x6e, 0x20, 0x61, 0x20, 0x31, 0x2d, 0x64, 0x20, 0x72, 0x65, 0x67, 0x75, + 0x6c, 0x61, 0x72, 0x20, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x0a, 0x0a, + 0x20, 0x20, 0x23, 0x20, 0x6d, 0x75, 0x6c, 0x74, 0x69, 0x64, 0x69, 0x6d, + 0x65, 0x6e, 0x73, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x20, 0x6c, 0x61, 0x79, + 0x6f, 0x75, 0x74, 0x73, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x77, 0x69, + 0x6c, 0x6c, 0x20, 0x62, 0x65, 0x20, 0x61, 0x64, 0x64, 0x65, 0x64, 0x20, + 0x77, 0x69, 0x74, 0x68, 0x20, 0x6d, 0x61, 0x6d, 0x62, 0x61, 0x0a, 0x20, + 0x20, 0x23, 0x20, 0x63, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, + 0x6c, 0x69, 0x74, 0x79, 0x3b, 0x20, 0x77, 0x69, 0x6c, 0x6c, 0x20, 0x6e, + 0x65, 0x65, 0x64, 0x20, 0x65, 0x6e, 0x75, 0x6d, 0x73, 0x20, 0x61, 0x6e, + 0x64, 0x20, 0x75, 0x73, 0x65, 0x72, 0x2d, 0x64, 0x65, 0x66, 0x69, 0x6e, + 0x65, 0x64, 0x20, 0x74, 0x79, 0x70, 0x65, 0x73, 0x20, 0x66, 0x6f, 0x72, + 0x20, 0x74, 0x68, 0x65, 0x0a, 0x20, 0x20, 0x23, 0x20, 0x6e, 0x61, 0x6d, + 0x65, 0x64, 0x20, 0x6c, 0x61, 0x79, 0x6f, 0x75, 0x74, 0x20, 0x73, 0x74, + 0x79, 0x6c, 0x65, 0x73, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x72, 0x6f, + 0x77, 0x2d, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x2f, 0x63, 0x6f, 0x6c, 0x75, + 0x6d, 0x6e, 0x2d, 0x6d, 0x61, 0x6a, 0x6f, 0x72, 0x0a, 0x0a, 0x20, 0x20, + 0x23, 0x20, 0x64, 0x69, 0x73, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x0a, 0x0a, 0x0a, 0x23, 0x20, 0x28, 0x65, 0x6e, 0x64, + 0x20, 0x6f, 0x66, 0x20, 0x6d, 0x61, 0x65, 0x73, 0x74, 0x72, 0x6f, 0x2d, + 0x63, 0x6f, 0x72, 0x65, 0x2e, 0x79, 0x61, 0x6d, 0x6c, 0x29, 0x0a, 0x0a }; -const unsigned int maestro_core_yaml_len = 3885; +const unsigned int maestro_core_yaml_len = 4224; diff --git a/attributes/maestro-core.yaml b/attributes/maestro-core.yaml index 7a23acc38df552bf6e13733b50cb187288fee325..7097c7685acbc87e7491da9e943ed13960fc157b 100644 --- a/attributes/maestro-core.yaml +++ b/attributes/maestro-core.yaml @@ -120,7 +120,17 @@ maestro-attributes: documentation: The local size of the CDO. -1 indicates Unknown/Unallocated. # Layouts - # Distributions + - key: "cdo.scope.layout.regular-1d.element-size" + type: uint() + required: False + default: 1 + documentation: Element-size in a 1-d regular layout + + # multidimensional layouts will will be added with mamba + # compatibility; will need enums and user-defined types for the + # named layout styles like row-major/column-major + + # distributions # (end of maestro-core.yaml) diff --git a/attributes/maestro-schema.c b/attributes/maestro-schema.c index f73fba7dd35abb91c5f6354169f508b37b9aa1fd..adc1a7ad61b7ab0f288cbe75e6d1d9b383407f3d 100644 --- a/attributes/maestro-schema.c +++ b/attributes/maestro-schema.c @@ -628,7 +628,7 @@ mstro_attribute_val_parse(const struct mstro_stp_val *parsed_type, const char *s switch(parsed_type->kind) { case MSTRO_STP_BOOL: { - err = regcomp(&(regex[0]), "1|0|On|Off|True|False",REG_ICASE|REG_NOSUB|REG_EXTENDED); + err = regcomp(&(regex[0]), "1|on|yes|true|0|off|no|false",REG_ICASE|REG_NOSUB|REG_EXTENDED); break; } case MSTRO_STP_UINT: { @@ -735,6 +735,7 @@ mstro_attribute_val_parse(const struct mstro_stp_val *parsed_type, const char *s } /* numeric bound checking should happen in this switch. All the info is in the stp_val */ + void *dst=*val_p; /* to make the assignments and casts below less messy wrt. '**' */ if(s==MSTRO_OK) { switch(parsed_type->kind) { case MSTRO_STP_BOOL: { @@ -744,49 +745,48 @@ mstro_attribute_val_parse(const struct mstro_stp_val *parsed_type, const char *s case '1': // 1 case 'o': // ON case 'y': // YES - **((bool**)(val_p)) = true; + *(bool*)dst = true; break; default: - *((bool**)(val_p)) = false; + *((bool*)dst) = false; break; } break; } case MSTRO_STP_UINT: - **((uint64_t**)(val_p)) = strtoumax((const char*)string, NULL, 10); + *((uint64_t*)dst) = strtoumax((const char*)string, NULL, 10); break; case MSTRO_STP_INT: - **((int64_t**)(val_p)) = strtoimax(string, NULL, 10); + *((int64_t*)dst) = strtoimax(string, NULL, 10); break; case MSTRO_STP_FLOAT: - *((float*)(val_p)) = strtof(string, NULL); + *((float*)dst) = strtof(string, NULL); break; case MSTRO_STP_DOUBLE: - **((double**)(val_p)) = strtod(string, NULL); + *((double*)dst) = strtod(string, NULL); break; case MSTRO_STP_STR: - case MSTRO_STP_REGEX: - strcpy(*(char**)val_p, string); - (*(char**)(val_p))[(*val_size)-1] = '\0'; + case MSTRO_STP_REGEX: + strcpy((char*)dst, string); + ((char*)dst)[(*val_size)-1] = '\0'; break; case MSTRO_STP_BLOB: - memcpy(*(char**)val_p, string, *val_size); + memcpy((char*)dst, string, *val_size); break; - case MSTRO_STP_TIMESTAMP: { - s=mstro_timestamp_parse(string, *val_size, *((mstro_timestamp**)val_p)); + case MSTRO_STP_TIMESTAMP: + s=mstro_timestamp_parse(string, *val_size, (mstro_timestamp*)dst); if(s!=MSTRO_OK) { ERR("Failed to parse timestamp value |%s| as rfc3339-timestamp\n"); } break; - } - default: + default: ERR("Unexpected parsed type %d\n", parsed_type->kind); s=MSTRO_UNIMPL; } @@ -803,10 +803,11 @@ mstro_status mstro_schema_attribute__parse_defaultval(struct mstro_schema_attribute_ *attr) { assert(attr->type_parse_closure.info!=NULL); - if(attr->defaultval_string) + if(attr->defaultval_string) return mstro_attribute_val_parse(attr->type_parse_closure.info, attr->defaultval_string, &attr->defaultval, &attr->defaultval_size); else { + DEBUG("Attribute |%s| has no default value in schema\n", attr->key); attr->defaultval = NULL; attr->defaultval_size = 0; return MSTRO_OK; @@ -966,12 +967,13 @@ mstro_schema_validate_and_instantiate(mstro_schema schema) } /* check that attribute has value type */ - DEBUG("Attribute |%s| type |%s|, required %s, default %s, doc: %s\n", + DEBUG("Attribute |%s| type |%s|, required %s, default %s [parsed %s], doc: %s\n", mstro_symbol_name(current->key_symbol), current->typespec, current->required ? "YES" : "NO", //"?"// current->defaultval_string ? current->defaultval_string : "(none)", + current->defaultval == NULL ? "NOT OK" : "ok", current->documentation ? current->documentation : "(none)" ); } @@ -1470,7 +1472,8 @@ static inline mstro_status mstro_attributes__parse_helper(yaml_parser_t parser, struct mstro_schema_ *schema, - mstro_attribute_dict *result) + mstro_attribute_dict *result, + const char *default_namespace_prefix) { mstro_status status = MSTRO_UNIMPL; bool result_allocated_here=false; @@ -1483,6 +1486,10 @@ mstro_attributes__parse_helper(yaml_parser_t parser, ERR("NULL attribute dict\n"); return MSTRO_INVOUT; } + size_t default_namespace_prefix_len = 0; + if(default_namespace_prefix!=NULL) + default_namespace_prefix_len = strlen(default_namespace_prefix); + if(*result==NULL) { *result = malloc(sizeof(struct mstro_attribute_dict_)); if(*result==NULL) { @@ -1576,7 +1583,17 @@ mstro_attributes__parse_helper(yaml_parser_t parser, if(keystack->fqkey==NULL) { DEBUG("No key on top of stack, this must be the mapping key\n"); - size_t next_len = (keystack->next==NULL ? 0 : keystack->next->keylen + 1 /* '.' */); + size_t next_len; + if(keystack->next!=NULL) { + next_len = keystack->next->keylen + 1 /* need a '.' */; + } else if (default_namespace_prefix!=NULL) { + next_len = default_namespace_prefix_len; + /* maybe will need to append a '.' */ + if(default_namespace_prefix[next_len-1]!='.') + next_len++; + } else { + next_len=0; + } keystack->keylen = (val_len + next_len); keystack->fqkey = malloc(keystack->keylen+1); @@ -1585,20 +1602,35 @@ mstro_attributes__parse_helper(yaml_parser_t parser, status=MSTRO_NOMEM; goto BAILOUT; } + size_t offset; if(keystack->next!=NULL) { + DEBUG("keystack provides prefix %s\n", keystack->next->fqkey); strcpy(keystack->fqkey, keystack->next->fqkey); keystack->fqkey[next_len-1] = '.'; keystack->fqkey[next_len] = '\0'; offset = next_len; } else { - if(val[0]!='.') { - ERR("Toplevel key needs to start with '.'\n"); + DEBUG("no next elt on keystack\n"); + if(val[0]=='.') { + /* fully qualified key */ + DEBUG("Key is fully qualified\n"); + offset=0; + } else if (default_namespace_prefix!=NULL) { + /* prepend default namespace */ + strcpy(keystack->fqkey, default_namespace_prefix); + keystack->fqkey[next_len-1] = '.'; + keystack->fqkey[next_len] = '\0'; + offset = next_len; + DEBUG("qualifying |%s| using default namespace |%s|\n", + val, default_namespace_prefix); + } else { + ERR("Toplevel key needs to start with '.', or a default namespace needs to be set\n"); status=MSTRO_FAIL; goto BAILOUT; } - offset = 0; } + strcpy(keystack->fqkey+offset, (const char*)val); DEBUG("Stored fqkey %s\n", keystack->fqkey); } else { @@ -1800,7 +1832,8 @@ BAILOUT: mstro_status mstro_attributes_parse(mstro_schema schema, const char *yaml_fragment, - mstro_attribute_dict *result) + mstro_attribute_dict *result, + const char *default_namespace_prefix) { mstro_status s; if(schema==NULL) { @@ -1827,7 +1860,7 @@ mstro_attributes_parse(mstro_schema schema, /* Set input file */ yaml_parser_set_input_string(&parser, (const unsigned char*)yaml_fragment, strlen(yaml_fragment)); - s=mstro_attributes__parse_helper(parser, schema, result); + s=mstro_attributes__parse_helper(parser, schema, result, default_namespace_prefix); yaml_parser_delete(&parser); if(s!=MSTRO_OK) { @@ -1994,6 +2027,9 @@ BAILOUT: if(status!=MSTRO_OK) if(must_insert) mstro_attribute_entry_dispose(entry); + + DEBUG("Insert default returns %d (%s)\n", + status, mstro_status_description(status)); return status; } diff --git a/attributes/maestro-schema.h b/attributes/maestro-schema.h index fc74f5dad86bf39489e5dd24433c75b238c0274e..f6ae7170bb7b0b08f74902afe6d2dadd062b6d25 100644 --- a/attributes/maestro-schema.h +++ b/attributes/maestro-schema.h @@ -140,12 +140,15 @@ typedef struct mstro_attribute_dict_ * mstro_attribute_dict; ** maestro.core.cdo.scope.size: 1024 ** ** @arg yaml_fragment may not be NULL. + ** + ** @arg default_namespace_prefix may be NULL **/ mstro_status mstro_attributes_parse(mstro_schema schema, const char *yaml_fragment, - mstro_attribute_dict *result); + mstro_attribute_dict *result, + const char *default_namespace_prefix); /** Inject default values from schema into attribute dictionary. diff --git a/attributes/symtab.c b/attributes/symtab.c index d2686731ee4156b9060086333bac6fc70a500ffd..83ea50e5304df4fe0b0fbf14a8589aafb8a60617 100644 --- a/attributes/symtab.c +++ b/attributes/symtab.c @@ -123,6 +123,16 @@ mstro_symtab_key_equal(struct mstro_symtab_entry_key *k1, /** A structure whose allocation address serves as atribute key in */ +/* FIXME: key has a VLA at the end, hence strictly speaking we cannot embed it into another structure: + symtab.c:130:33: warning: 'key' may not be nested in a struct due to flexible array member [-Wflexible-array-extensions] + (C11 (ISO/IEC 9899:2011), §6.7.2.1.3 / §6.7.2.1.18) + We should fix that, but both gcc and clang are handling it fine for now (they only warn at -pedantic and above) + + Note that simply using key[1] does not work either. Likely the best + option is to have the same declaration #defined and use it here + inline and in mstro_symtab_entry_key to make the two regions + assignment-compatible. +*/ struct mstro_symtab_entry { UT_hash_handle hh; /**< hashable using specialized functions * mstro_symtab_key_hash and diff --git a/include/maestro/i_cdo.h b/include/maestro/i_cdo.h index 55c7b5793253d9c2fda6347802d4dd6a14e5bcc8..d4095bed7f71bf331e63b492369052cebec951d4 100644 --- a/include/maestro/i_cdo.h +++ b/include/maestro/i_cdo.h @@ -288,6 +288,9 @@ struct mstro_cdo_ { /* all other attributes and name and id are stored in the following table */ mstro_cdo_attributes attributes; /**< attribute and schema information */ + /* FIXME: we could store the current_namespace in a global namespace + * symtab ... millions of CDOs that all have the same string copied + * seems overkill */ char* current_namespace; /**< namespace string; default: ".maestro.core.cdo" */ }; diff --git a/maestro/attributes.c b/maestro/attributes.c index 1a7a6c7ca8e2b666dc6b236b3c3cbd9a0b55c6ad..01272fe7bf5a9826b0e697cb3a2efe228e4b836c 100644 --- a/maestro/attributes.c +++ b/maestro/attributes.c @@ -109,16 +109,22 @@ mstro_cdo_attribute_set(mstro_cdo cdo, const char* key, void* val) const char *fqkey=NULL; if(key[0]!='.') { /* qualify it */ - tmpfqkey = malloc(strlen(key)+strlen(cdo->current_namespace)); + tmpfqkey = malloc(strlen(cdo->current_namespace)+1+strlen(key)+1); if(tmpfqkey==NULL) { ERR("Cannot allocate for fully-qualified key\n"); return MSTRO_NOMEM; } + strcpy(tmpfqkey,cdo->current_namespace); + size_t l = strlen(tmpfqkey); + if(tmpfqkey[l-1]!='.') /* add '.' if needed ; we could require current_namespace to always have one ...*/ + tmpfqkey[l++]='.'; + strcpy(tmpfqkey+l,key); fqkey = tmpfqkey; } else { fqkey=key; } + mstro_status status = mstro_attribute_dict_set(cdo->attributes, fqkey, MSTRO_CDO_ATTR_VALUE_INVALID, /* we dont help in checking */ @@ -194,7 +200,8 @@ mstro_cdo_attribute_set_yaml(mstro_cdo cdo, const char* keyval_in_yaml) return mstro_attributes_parse(schema, keyval_in_yaml, - &cdo->attributes); + &cdo->attributes, + cdo->current_namespace); } mstro_status diff --git a/tests/check_declaration_seal.c b/tests/check_declaration_seal.c index a894559becb61b19434727d1deddc224b8810c5f..fead59246d0e714ae1033dddf4ba7eb76bedb8d9 100644 --- a/tests/check_declaration_seal.c +++ b/tests/check_declaration_seal.c @@ -58,11 +58,11 @@ CHEAT_TEST(cdo_declaration_seal_works, == mstro_cdo_attribute_get( cdo, "allocate-now", &type, &val)); fprintf(stdout, "check: default allocate_now: %d (%p)\n", - *(const int*)val, val); + *(const bool*)val, val); cheat_assert(MSTRO_OK == mstro_cdo_attribute_set_yaml( - cdo, "allocate_now: \"yes\"")); + cdo, "allocate-now: \"yes\"")); cheat_assert(MSTRO_OK == mstro_cdo_attribute_set_yaml( cdo, "persist: \"yes\"")); @@ -72,15 +72,15 @@ CHEAT_TEST(cdo_declaration_seal_works, cdo, u8"name: \"Robert Données \xF0\x9F\x90\x81\"")); cheat_assert(MSTRO_OK == mstro_cdo_attribute_set_yaml( - cdo, "scope: \n local_size: 4096")); + cdo, "scope: \n local-size: 4096")); cheat_assert(MSTRO_OK == mstro_cdo_attribute_set_yaml( cdo, "scope: \n" - " local_size: 8192 \n" + " local-size: 8192 \n" " layout: \n" - " regular_1d: \n" - " element_size: 8")); + " regular-1d: \n" + " element-size: 8")); cheat_assert(!(MSTRO_OK == mstro_cdo_attribute_set( cdo, "maestro.core.cdo.scope.local-size", @@ -96,17 +96,17 @@ CHEAT_TEST(cdo_declaration_seal_works, cheat_assert(MSTRO_FAIL == mstro_cdo_attribute_set_yaml( - cdo, "allocate_now: \"no\"")); + cdo, "allocate-now: \"no\"")); cheat_assert(MSTRO_OK == mstro_cdo_attribute_get( - cdo, "allocate_now", &type, &val)); - fprintf(stdout, "check: allocate_now: %d (%p)\n", *(const int*)val, val); + cdo, "allocate-now", &type, &val)); + fprintf(stdout, "check: allocate-now: %d (%p)\n", *(const bool*)val, val); cheat_assert(MSTRO_OK == mstro_cdo_attribute_get( cdo, "persist", &type, &val)); - fprintf(stdout, "check: persist: %d (%p)\n", *(const int*)val, val); + fprintf(stdout, "check: persist: %d (%p)\n", *(const bool*)val, val); cheat_assert(MSTRO_OK == mstro_cdo_attribute_get( @@ -115,11 +115,11 @@ CHEAT_TEST(cdo_declaration_seal_works, cheat_assert(MSTRO_OK == mstro_cdo_attribute_get( - cdo, "local_size", &type, &val)); + cdo, "scope.local-size", &type, &val)); fprintf(stderr, "check: scope.local-size == %d (%p)\n", *(const int*)val, val); - cheat_assert(MSTRO_INVARG + cheat_assert(MSTRO_NOENT == mstro_cdo_attribute_get( cdo, "totally_an_attribute", &type, &val)); diff --git a/tests/check_schema_parse.c b/tests/check_schema_parse.c index 90cb51c368b66fb48176d61b815c439919fe5139..0a2acdb48c7036f2fbc2687bc534f848404feb99 100644 --- a/tests/check_schema_parse.c +++ b/tests/check_schema_parse.c @@ -100,7 +100,7 @@ CHEAT_TEST(core_schema_parse, /* now use the merged schema to parse some sample defs */ cheat_assert(MSTRO_OK==mstro_attributes_parse(s1, SAMPLE_YAML_STRING, - &dict)); + &dict, NULL)); cheat_yield(); /* s1 is the merged one, and freeing it will recurse */ @@ -135,7 +135,7 @@ CHEAT_TEST(core_schema_parse_builtin, /* now use the merged schema to parse some sample defs */ cheat_assert(MSTRO_OK==mstro_attributes_parse(s1, SAMPLE_YAML_STRING, - &dict)); + &dict, NULL)); cheat_yield(); /* try a direct lookup */