diff --git a/readme.md b/readme.md index b288b7df..9320340d 100644 --- a/readme.md +++ b/readme.md @@ -54,7 +54,10 @@ wasmtime run --dir=. src/dialogc.wasm story.dg stdlib.dg ## Release notes -### 1c/04, Lib 1.2.4: +### 1c/04, Lib 1.2.3: + + Compiler: multiple definitions for the same style class or + metadata predicate (outside the library) now produce a warning. Compiler: improved dictionary word matching accuracy. @@ -63,7 +66,7 @@ wasmtime run --dir=. src/dialogc.wasm story.dg stdlib.dg Documentation: Convert the repository readme to markdown. -### 1c/03, Lib 1.2.4: +### 1c/03, Lib 1.2.3: Language: CSS text-decoration: reverse has been replaced with -iftf-reverse-video: reverse for compatibility reasons. diff --git a/src/ast.h b/src/ast.h index 9e5be7b6..66279d5a 100644 --- a/src/ast.h +++ b/src/ast.h @@ -452,6 +452,7 @@ struct program { uint16_t max_temp; uint8_t reported_violations; int topic_warning_level; // WARN_* + int lib_file; // Which file has (library version) }; #define WARN_DEFAULT 0 diff --git a/src/backend.c b/src/backend.c index d1782ba3..372901c2 100644 --- a/src/backend.c +++ b/src/backend.c @@ -300,7 +300,7 @@ int main(int argc, char **argv) { need_meta = prg->totallines > 100; - prg->meta_ifid = decode_metadata_str(BI_STORY_IFID, 0, prg, &prg->arena); + prg->meta_ifid = decode_metadata_str(BI_STORY_IFID, 0, prg, &prg->arena, "story ifid", prg->lib_file); if(!prg->meta_ifid) { if(!strcmp(format, "zblorb")) { // Mandatory for zblorb, make it an error report(LVL_ERR, 0, "An IFID is mandatory for the blorb output format."); @@ -315,25 +315,25 @@ int main(int argc, char **argv) { prg->meta_ifid = 0; } - prg->meta_author = decode_metadata_str(BI_STORY_AUTHOR, 0, prg, &prg->arena); + prg->meta_author = decode_metadata_str(BI_STORY_AUTHOR, 0, prg, &prg->arena, "story author", prg->lib_file); if(!prg->meta_author) { if(need_meta) { report(LVL_WARN, 0, "No author declared."); } prg->meta_author = "Anonymous"; } - prg->meta_title = decode_metadata_str(BI_STORY_TITLE, 0, prg, &prg->arena); + prg->meta_title = decode_metadata_str(BI_STORY_TITLE, 0, prg, &prg->arena, "story title", prg->lib_file); if(!prg->meta_title) { if(need_meta) { report(LVL_WARN, 0, "No title declared."); } prg->meta_title = "An Interactive Fiction"; } - prg->meta_noun = decode_metadata_str(BI_STORY_NOUN, 0, prg, &prg->arena); + prg->meta_noun = decode_metadata_str(BI_STORY_NOUN, 0, prg, &prg->arena, "story noun", prg->lib_file); if(!prg->meta_noun) { prg->meta_noun = "An Interactive Fiction"; } - prg->meta_blurb = decode_metadata_str(BI_STORY_BLURB, 0, prg, &prg->arena); + prg->meta_blurb = decode_metadata_str(BI_STORY_BLURB, 0, prg, &prg->arena, "story blurb", prg->lib_file); predname = find_builtin(prg, BI_STORY_RELEASE); if(predname && (pred = predname->pred)->nclause) { @@ -342,8 +342,14 @@ int main(int argc, char **argv) { exit(1); } prg->meta_release = pred->clauses[0]->params[0]->value; - } else if(need_meta) { - report(LVL_WARN, 0, "No release number declared."); + if(pred->nclause > 1) { + report(LVL_WARN, pred->clauses[0]->line, "%d separate definitions found for (story release $). Only the first (at this line) will be used.", pred->nclause); + } + } else { + if(need_meta) { + report(LVL_WARN, 0, "No release number declared."); + } + prg->meta_release = 1; } if(serial_overridden) { diff --git a/src/frontend.c b/src/frontend.c index 1e2a7e90..c2461685 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -2399,26 +2399,42 @@ static void assign_select_statements(struct program *prg) { selectforms = 0; } -char *decode_metadata_str(int builtin, struct word *param, struct program *prg, struct arena *arena) { +char *decode_metadata_str(int builtin, struct word *param, struct program *prg, struct arena *arena, const char *report_as, int lib_file) { struct predname *predname; struct predicate *pred; - char *buf; + char *buf = 0; int i; + int nfound = 0; + int nlib = 0; + line_t whichline = 0; predname = find_builtin(prg, builtin); pred = predname->pred; for(i = 0; i < pred->nclause; i++) { if(!param || (pred->clauses[i]->params[0]->kind == AN_DICTWORD && pred->clauses[i]->params[0]->word == param)) { - if(decode_output(&buf, pred->clauses[i]->body, 0, 0, arena, "Story metadata")) { - return buf; - } else { - return 0; + if(!nfound) { // First one found + if(!decode_output(&buf, pred->clauses[i]->body, 0, 0, arena, "Story metadata")) { + buf = 0; // Failed to decode into buf + } + whichline = pred->clauses[i]->line; + } + nfound ++; + if(FILENUMPART(pred->clauses[i]->line) == lib_file) { // This one was in a library file + nlib ++; } } } - return 0; + if(nfound - nlib > 1) { + if(param) { + report(LVL_WARN, whichline, "%d separate definitions found for (%s @%s) outside of the library. Only the first (at this line) will be used.", nfound, report_as, param->name); + } else { + report(LVL_WARN, whichline, "%d separate definitions found for (%s) outside of the library. Only the first (at this line) will be used.", nfound, report_as); + } + } + + return buf; } int frontend(struct program *prg, int nfile, char **fname, dictmap_callback_t dictmap_callback) { @@ -2482,6 +2498,7 @@ int frontend(struct program *prg, int nfile, char **fname, dictmap_callback_t di } else if(lexer.lib_file != nfile - 1) { report(LVL_WARN, 0, "The library (in this case %s) should normally appear last on the commandline.", sourcefile[lexer.lib_file]); } + prg->lib_file = lexer.lib_file; // Warn about objects never used as topics, depending on topic_warning_level if(prg->topic_warning_level == WARN_DEFAULT && lexer.lib_file >= 0) { // Default: warn only if library file found @@ -2896,7 +2913,7 @@ int frontend(struct program *prg, int nfile, char **fname, dictmap_callback_t di for(i = 0; i < prg->nboxclass; i++) { struct boxclass *bc = &prg->boxclasses[i]; - char *css = decode_metadata_str(BI_STYLEDEF, bc->class, prg, &lexer.temp_arena); + char *css = decode_metadata_str(BI_STYLEDEF, bc->class, prg, &lexer.temp_arena, "style class", lexer.lib_file); char *param, *str; struct boxclassline *bcl, **bclptr; diff --git a/src/frontend.h b/src/frontend.h index 3843a824..90dd23e4 100644 --- a/src/frontend.h +++ b/src/frontend.h @@ -16,7 +16,7 @@ int body_succeeds(struct astnode *an); int body_might_stop(struct astnode *an); int body_succeeds_at_most_once(struct astnode *an); void frontend_add_builtins(struct program *prg); -char *decode_metadata_str(int builtin, struct word *param, struct program *prg, struct arena *arena); +char *decode_metadata_str(int builtin, struct word *param, struct program *prg, struct arena *arena, const char *report_as, int lib_file); int frontend(struct program *prg, int nfile, char **fname, dictmap_callback_t dictmap_callback); int frontend_inject_query(struct program *prg, struct predname *predname, struct predname *tailpred, struct word *prompt, const uint8_t *str);