{"record":{"id":"a5fcd3e871638c92","repo":"Tencent/matrix","slug":"unterminated-ifdef-starting-on-line-d","errorCode":null,"errorMessage":"unterminated %%ifdef starting on line %d\n","messagePattern":"unterminated %(.+?)fdef starting on line (.+?)\n","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c","lineNumber":2423,"sourceCode":"        for(n=0; z[j+n] && !isspace(z[j+n]); n++){}\n        exclude = 1;\n        for(k=0; k<nDefine; k++){\n          if( strncmp(azDefine[k],&z[j],n)==0 && strlen(azDefine[k])==n ){\n            exclude = 0;\n            break;\n          }\n        }\n        if( z[i+3]=='n' ) exclude = !exclude;\n        if( exclude ){\n          start = i;\n          start_lineno = lineno;\n        }\n      }\n      for(j=i; z[j] && z[j]!='\\n'; j++) z[j] = ' ';\n    }\n  }\n  if( exclude ){\n    fprintf(stderr,\"unterminated %%ifdef starting on line %d\\n\", start_lineno);\n    exit(1);\n  }\n}\n\n/* In spite of its name, this function is really a scanner.  It read\n** in the entire input file (all at once) then tokenizes it.  Each\n** token is passed to the function \"parseonetoken\" which builds all\n** the appropriate data structures in the global state vector \"gp\".\n*/\nvoid Parse(gp)\nstruct lemon *gp;\n{\n  struct pstate ps;\n  FILE *fp;\n  char *filebuf;\n  int filesize;\n  int lineno;\n  int c;","sourceCodeStart":2405,"sourceCodeEnd":2441,"githubUrl":"https://github.com/Tencent/matrix/blob/3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7/matrix/matrix-android/matrix-sqlite-lint/src/lemon/lemon-gen/lemon.c#L2405-L2441","documentation":"Lemon's input preprocessor tracks %ifdef/%ifndef/%else/%endif conditionals while reading the grammar file. If the end of the file is reached while a conditional block is still open (exclude != 0), it prints 'unterminated %ifdef starting on line %d' naming the line where the block began, and exits 1.","triggerScenarios":"A .y grammar file contains %ifdef or %ifndef without a matching %endif before EOF; a misspelled conditional keyword (e.g. `%endifs` or `%ednif`) that the scanner ignores; a nested conditional where one %endif was removed by an outer block's processing.","commonSituations":"Manual edits to grammar files that delete or comment out a %endif; merge conflicts resolved by dropping lines including %endif; copy-pasted conditional blocks where only part of the pair was copied; refactoring that moved rules across files leaving the opener behind.","solutions":["Add the missing %endif at the end of the conditional block reported by the start line","Search the .y file for all %ifdef/%ifndef and verify each has exactly one matching %endif (nesting order matters)","Check for misspelled conditional keywords near the reported start line","If the block came from a merge, re-diff against the original file to recover the dropped %endif"],"exampleFix":"// before (foo.y)\n%ifdef FOO\nrule ::= A.\n// after\n%ifdef FOO\nrule ::= A.\n%endif","handlingStrategy":"validation","validationCode":"# python pre-check balancing conditional directives in order\nimport re,sys\nstack=[]\nfor n,line in enumerate(open(sys.argv[1]),1):\n    s=line.strip()\n    if s.startswith(('%ifdef','%ifndef')): stack.append(n)\n    elif s.startswith('%endif'): stack and stack.pop()\n    elif s.startswith('%else') and not stack: sys.exit(f'stray %else at line {n}')\nif stack: sys.exit(f'unterminated %ifdef starting on line {stack[0]}')","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Run a conditional-balance linter over .y files in pre-commit/CI","Avoid manual deletion of %endif lines during merges; re-diff conditional blocks","Use consistent, exact keywords (%ifdef/%ifndef/%else/%endif)","Keep conditional blocks small and locally scoped"],"tags":["grammar","lemon","preprocessor","unterminated-block","ifdef"],"backgroundTag":"unterminated-preprocessor-block","analyzedSha":"3b8293bd65d47eeea7caf1f32a3a5d4d5eab60e7","analyzedAt":"2026-09-08T08:01:39.722Z","contentChangedAt":"2026-09-08T08:01:39.722Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}