Bison semantic predicate syntax error, stray '#' - c

So I am trying to use bison's semantic predicate feature, but I've been running into a few issues trying to have it work.
The problem comes when I try to compile the generated .tab.c file with gcc. I am using gcc 7.1.0 and bison 3.0.4. Here's a snippet of the compile error:
test2.tab.c: In function ‘yyuserAction’:
test2.tab.c:811:12: error: stray ‘#’ in program
if (! (#line 19 "test2.y" /* glr.c:816 */
^
test2.tab.c:811:13: error: ‘line’ undeclared (first use in this function); did you mean ‘uint’?
if (! (#line 19 "test2.y" /* glr.c:816 */
^~~~
uint
So I've taken bison's example for semantic predicate, and made it a working example:
%{
int new_syntax = 0;
int yyerror(const char* msg) { /* some error handling */ }
%}
%token id
%glr-parser
%%
prog: %empty
| prog widget
| prog flip
;
widget: %?{ new_syntax } "widget" id old_arg
| %?{ !new_syntax } "widget" id new_arg
;
flip: "flip" { new_syntax = !new_syntax; }
;
old_arg: /* something here */
;
new_arg: /* something else here */
;
%%
After playing around with the tab file, I realized that adding a newline before the #line directives resolves the syntax error, (but it feels kinda hacky directly modifying the generated file. Plus, you would have to align with some spaces in order for gcc to compute the right column position of the code).
I wonder if is this a bug with bison itself, or is it that I'm using semantic predicates wrong, or if this syntax was correct in an earlier version of gcc, or something else.
I've also tried searching the web for this issue, or for a bug already filed with bison, but I found none. (The latest bison version seems to be 3-ish years old. I would be surprised if this issue has not been addressed anywhere at all). Can someone enlighten me about this issue? Thanks.
If necessary, I could try filing a bug with bison (need to figure out how to do that), but I'm not sure if it's my own issue or what not.

As far as I can see, this bug has been present for some time (possibly since the semantic predicate feature was introduced, although it seems like someone should have tested it at some point with some version of bison.)
The simplest workaround is to turn off the generation of #line directives, which you can do by simply adding -l (or --no-lines) to the bison command line. However, that will make it harder to interpret error messages which would otherwise refer to line numbers in your bison grammar file.
As a second workaround, you could find the file c.m4, which is probably in /usr/share/bison/c.m4 (of course, that depends on your distribution). Line 462 of that file (in bison 3.0.4) reads:
if (! ($2)) YYERROR;
If you add a newline just before $2, so that it reads
if (! (
$2)) YYERROR;
then everything should work out fine. (At least, it did when I tested it.)

Related

Linker error while using lex to compile simple print file. have newest version of macOS 13.1 and xcode installed

I'm trying to run a simple progam in flex that reads the string "hello world" and prints "Goodbye"
here is the file:
%%
"hello world" printf("Goodbye\n");
. ;
%%
the commands are
% flex ex1.l
% gcc lex.yy.c -ll
Error message:
ld: warning: object file (/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib/libl.a(libmain.o)) was built for newer macOS version (13.1) than being linked (13.0)
I have redownloaded the newest version of Xcode and have the updated macOS. I'm not sure what I can try to get this error code to go away.
I have also ran
% CMAKE_OSX_DEPLOYMENT_TARGET 13.0
to try and force the link to V13.0 without success.
The lex library, which the linker will use if given the -ll command-line flag, is supposed to be a convenience to make it easier to write quick and dirty (f)lex programs. If your compiler toolchain installation is OK, then it is a small convenience, but it seems like it's pretty easy to get the installation wrong, and since no-one seems to bother documenting the details of toolchain installation, it's hard to debug configuration issues unless you have lots of experience. That makes it a lot less convenient.
You could use this is as a learning experience in configuring your compilation environment, a skill which you will certainly find useful. But if you just want to get on with flex, it's really easy to avoid the need to use of the lex library.
The lex library consists of exactly two things, neither of which are necessary.
First, it contains a definition of yywrap(). The generated lexer calls yywrap() when it encounters the end of an input file. If yywrap returns 0, the lexer assumes that you have done something which will allow the lexer to continue reading input. That's actually not a very common use case, because most parsers just read one input file from beginning to end, and then finish. So a good default is to write a version of yywrap() which always returns 1, in which case the lexer will return an end-of-file token (0), and that should cause the lexer's caller to stop calling the lexer. The lex library includes the definition of precisely that simple default implementation:
int yywrap() { return 1; }
So you could include that code in your flex file, but a better solution is to tell flex to omit the yywrap() call and just assume that end-of-file means that there is no more input. Which you do by inserting the following declaration in your Flex prologue (not in the %{...%} code section):
%option noyywrap
I always recommend using a few more options:
%option noinput nounput noyywrap nodefault
The first two of those suppress the generation of the input() and unput() functions, so that you don't get "Unused function" warnings when you compile. Or better said, so that you wouldn't get warnings if you requested warnings when you compiled. But you should always request warnings. (And you should read them and act on them.) See the sample build instructions at the end of this answer.
The last option, nodefault, causes flex to produce a warning if there is any input which could trigger the automatic default action. The automatic default is to write the unmatched input to stdout and do nothing else, which is practically never what you want to do with unmatched input. Even if you wanted to ignore all unmatched input, which is a good way of ignoring programming errors, you'd very rarely want to print unmatched input to the output.
As it happens, your code will trigger this warning if you add the nodefault option, because you used . as your fallback pattern. . in (f)lex matches anything other than a newline character, and nothing in your program matches a newline, so the newline will go unmatched. Which means it will be echoed to standard output. Instead, you should use .|\n so that your default pattern also matches a newline. (Alternatively, with flex, you can use the s pattern flag, which causes . to really match anything: (?s:.).)
The other thing that the lex library contains is a default definition of main(). It's somewhat interesting that this is even possible. It works because the linker only includes functions from a library if the functions are not defined in the object files being linked. And, in C, main() really acts like an ordinary function. So if you link with a library which defines main(), that main program will be used whenever you don't define main() in your source code. That can be handy for debugging, but it's not really recommended in production code.
The particular main() function which is included in -ll just calls yylex() repeatedly until it returns an end-of-file token (0):
int main() {
while (yylex() != 0) { }
return 0;
}
So instead of relying on the lex library, just add those four lines at the end of your lexer definition, after the second %%.
If you apply both of these suggestions, you will end up with:
%option noinput nounput noyywrap nodefault
%{
/* So that `printf` is declared */
#include <stdio.h>
%}
%%
"hello world" printf("Goodbye\n");
.|\n ;
%%
int main() {
while (yylex() != 0) { }
return 0;
}
You can then build it without the -ll flag. But you should always build with compiler warnings enabled, and personally I think that using the default executable name a.out is bad style:
% flex ex1.l
% gcc -Wall -o ex1 lex.yy.c

Swig: Syntax error in input(3)

./theheader.h:349: Error: Syntax error in input(3).
Offending line:
string read_gdbm(GDBM_FILE dbf, string key_str, bool show_err = gbls.verbose);
Any ideas?
Typically, a syntax error in SWIG means that it can't understand the line in question (which can be annoying, because the line numbers don't follow macros such as %defines). So I suggest you check that string (should it be std::string? has it been defined?), GDBM_FILE (has it been defined? should it be in a namespace?) and maybe gbls.verbose (has it been defined?) make sense to SWIG. It may help to run swig with the -E option (be sure to redirect the stdout), find the corresponding line and search backward for each type involved. You may need to add some #includes.
Also check the previous line, to ensure you're not missing a semicolon, or something like that.
As a side note, I've run into the same issue for different reasons: I was trying to use a vector < vector < double >>. Now the ">>" character sequence mustn't be used with templates according to the C++99 standard, hence the swig error message popped up. The solution was to simply add an extra space to separate them.
I hit a similar error. I'll clarify my process, hope it can be helpful.
lib.i:
...
%begin %{
#include "header1.h"
%}
...
%include "header1.h"
header1.h:
19 typedef struct T {
...
23 } PACKED TlvHdr;
The error message just as below
./header1.h:23: Error: Syntax error in input(3).
I check the SWIG doc(http://www.swig.org/Doc1.3/SWIG.html 5.7.1) and found that the syntax error is so common, it's probably caused by a SWIG bug.
The doc recommended when encountering a syntax error to use #ifndef SWIG to omit statements that will make SWIG parser issue an error. So I changed the header1.h file, then the error disappeared.
header1.h:
#ifndef SWIG
19 typedef struct T {
...
23 } PACKED TlvHdr;
#endif
If you can't modify theheader.h file, you can make a new header file that just contains the declarations you need and replace the file from theheader.h to your new header file at %include directive
I had a similar issue and -E helped me understand that a macro definition was hidden inside an #ifndef SWIG block. I suspect that here it does not see the definition of GDBM_FILE, likely because it does not recurse.

Compiling netcat on AIX

I have been trying to compile netcat.c on AIX for some time (using the command make aix), but the compiler gives me some weird feedback such as :
"netcat.c", line 117.12: 1506-275 (S) Unexpected text 'int' encountered.
when checked the file netcat.c at line 117, I would find the line (second line in code below):
#ifdef HAVE_BIND
extern int h_errno;
/* stolen almost wholesale from bsd herror.c */
even if I changed the int into char for the same of testing, save the file and re-run the command I get the same error
am I missing something in reading the error code?
If you're using xlc (especially older ones), it's normally caused by declarations after statements, something like:
i = i + 1;
int x;
You probably need to give us a little more context, such as 10 or so lines before the error line.
My advice would be to get gcc running on that box if you are using an older xlc. IBM makes some fine compilers now but the earlier ones weren't so crash hot (in my opinion).
When innocent-looking code produces bizarre errors, try running the code through the C preprocessor stage, and looking at it then. Sometimes macros do very funny things.
Also note that a problem on an earlier line (missing semicolon, etc.) might produce an error message on a later line.
The post maybe already a little outdated, but just in case someone else comes along with the same problem ...
Here (AIX 7.1) h_errno is defined as macro in netdb.h.
/usr/include/netdb.h:#define h_errno (*(int *)h_errno_which())
Therefore the declaration in netcat.c line 117 does not work.
I just changed the line into
#ifndef h_errno
extern int h_errno;
#endif
and the compilation worked smoothly.
#A.Rashad, I moved the HAVE_BIND #ifdef block from line 117 to line 30 which is just under the #include "generic.h" declaration. This permitted the xlc to compile it. The (S)yntax error messages are gone and while there are some (W)arning messages, I do get an nc binary at the end!
hth,
Kevin

Statement with no effect warning with GCC and Flex/Bison

When compiling my project with gcc and the -Wall option, I get a warning about a statement with no effect in the non-existant last line of my flex file:
Warning:
gcc -Wall -O0 -ggdb3 -DNOSUDO -DJOBC -DDEBUG -c lex.yy.c
tokenizer.l: In function ‘yylex’:
tokenizer.l:179: warning: statement with no effect
Shell Command:
$ wc -l tokenizer.l
178 tokenizer.l
Last part of lex file:
; {
return SEMI;
}
Anyone know why I might be getting this warning?
If I suppress all #line Directives, the error is:
lex.yy.c: In function ‘yylex’:
lex.yy.c:1021: warning: statement with no effect
Which refers to the ECHO line in:
case 30:
YY_RULE_SETUP
ECHO;
YY_BREAK
case YY_STATE_EOF(INITIAL):
case YY_STATE_EOF(inQuote):
case YY_STATE_EOF(inWord):
yyterminate();
In general, you'll get that error from any lex rule that has an unconditional 'return' in it, because flex ends up generating code that looks like (after macro expansion):
case xxx:
return SEMI;
break;
The problem being that the 'break' is unreachable. It needs to be there in case your rule does not return (so the code won't fall through to the code for the next token, but will instead go on to recognize the next token.) Flex isn't smart enough to actually parse your rule code and do flow analysis to determine when the break is unneeded, so it just always puts it there. In general, using -Wall on the output of flex (or bison) will give you lots of warnings like this...
I guess it feels that ; is a statement with no effect. Try quoting it:
";" {
return SEMI;
}
I ran into the same problem and looked a bit into it. It turned out that one of my "#includes" in the flex source file (the .l file) somehow indirectly included the standard library termios.h file, which defines a macro named "ECHO" (as "0000010").
The source file generated by flex on the other hand also wants to create a macro named "ECHO", there is an "#ifndef ECHO" before that. But of course, with termios.h included, that "ifndef" evaluates to false and ECHO wasn't defined as intended. That led to the error.
Long explanation, short solution: I put
#ifdef ECHO
#undef ECHO
#endif
below all my includes in my .l file, and that did the trick.
I know this discussion thread is already a bit old, but it turned up first when I googled the warning, so my contribution might still be useful for folks.
As the other answers said, the trouble is that a 'break' after a 'return' can't be reached.
It used to be possible to satisfy a compiler that there was a way to get to the 'break' by faking a conditional return:
if (1) return SEMI;
I have a suspicion that some modern compilers are clever enough to see through this - which is actually counter-productive of them. "Yes, you're right, Mr Compiler, but I can't avoid it so STFU".

problems with memset in Metal C

I’m trying to initialize the Metal C environment with the following code, but get the following errors on the memset line.
ERROR CCN3275 IMIJWS0.METAL.SAMPLIB(MEM):6 Unexpected text ')' encountered.
ERROR CCN3045 IMIJWS0.METAL.SAMPLIB(MEM):6 Undeclared identifier ___MEMSET.
ERROR CCN3277 IMIJWS0.METAL.SAMPLIB(MEM):6 Syntax error: possible missing ')' or ','?
CCN0793(I) Compilation failed for file //'IMIJWS0.METAL.SAMPLIB(MEM)'. Object file not created.
Below is my code
#include &lt string.h&gt
#include &lt stdlib.h&gt
#include &lt metal.h&gt
void mymtlfcn(void) {
struct __csysenv_s mysysenv;
memset ( &mysysenv, 0, sizeof ( mysysenv ) );
mysysenv.__cseversion = __CSE_VERSION_1;
mysysenv.__csesubpool = 129;
mysysenv.__cseheap31initsize = 131072;
mysysenv.__cseheap31incrsize = 8192;
mysysenv.__cseheap64initsize = 20;
mysysenv.__cseheap64incrsize = 1;
The issue was with the search order. Although I did search(/usr/metal/include) from with in my JCL I didn't proceed it with a nosearch option, so string.h was getting picked up from the standard system librarys instead of the version included with Metal C. I've pasted my optfile dataset I passed to the CPARM below for refference.
//OPTIONS DD *
SO
LIST
LONG
NOXREF
CSECT
METAL
LP64
NOSEARCH
search(/usr/include/metal/)
So, I have no idea. But some suggestions:
You might try copying/pasting this code here from this example just to make sure it works 'as expected'
Maybe try defining some of the macros here? (when I did C programming on zOS, I had to do include some weird macros in order to get stuff to work. I have no reasonable technical explanation for this.)
You could try searching for memset() using "=3.14" (from ispf.) See if any other modules use that function, and then check the headers that they include (or macros that they define - either in the C files or H files) to make it work.
Another thought: before the memset(), try doing putting a printf() in. If you get a syntax error on the same line (only for printf, rather than memset) then you can see if the problem is before line 6 - like a misplaced parenthesis.
Finally, if i recall correctly, I had to compile my individual modules, and then link them manually (unless I wrote a JCL to do this for me.) So you might have to link once to link with your other modules, and then link again against the C library. Not to be pedantic, but: you're fairly certain that you're doing all of the link passes?
I realize that's a lot of hoops to try and you've probably already read the manuals, but maybe there is something useful to try?
Also, and you probably already know this, but this site (for looking up error codes) is infinitely useful. (along with the above links for full-text-searching the manual)
Edit: this page also talks about "built-in functions" - you could try (as stated at the bottom of the page) "#undef memcpy" to use the non-built-in version?
Can you show us your compiler arguments? You need to make sure that you're not pulling in the standard C header files in addition to the metal C ones. Here's an example:
xlc -c -Wc,metal,longname,nosearch,'list(./)' -I. -I /usr/include/metal -I "//'SYS1.SIEAHDRV'" -S -qlanglvl=extended foo.c
as -mrent -mgoff -a=foo.list -o foo.o foo.s
ld -bac=1 -brent -S "//'SYS1.CSSLIB'" -o foo foo.o
Are you missing the closing brace '}' for the function? How about any missing semi-colon line terminators? When missing braces/semi-colons the z/OS C compiler throws some strange/misleading messages sometimes. I don't have it to try out, but I'm assuming Metal does as well.

Resources