My Yacc source is in pos.yacc and my Lex source is in pos1.lex, as shown.
pos1.lex
%{
#include "y.tab.h"
int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%
pos.yacc
%token DIGIT
%%
s:e {printf("%d\n",$1);}
e:DIGIT {$$=$1;}
|e e "+" {$$=$1+$2;}
|e e "*" {$$=$1*$2;}
|e e "-" {$$=$1-$2;}
|e e "/" {$$=$1/$2;}
;
%%
main() {
yyparse();
}
yyerror() {
printf("Error");
}
Compilation errors
While compiling I am getting errors like:
malathy#malathy:~$ cc lex.yy.c y.tab.c -ly -ll
pos.y: In function ‘yyerror’:
pos.y:16: warning: incompatible implicit declaration of built-in function ‘printf’
pos.y: In function ‘yyparse’:
pos.y:4: warning: incompatible implicit declaration of built-in function ‘printf’
What causes those errors?
How am I supposed to compile Lex and Yacc source code?
printf() is defined in stdio.h so just include it above y.tab.h in pos1.lex:
%{
#include <stdio.h>
/* Add ^^^^^^^^^^^ this line */
#include "y.tab.h"
int yylval;
%}
DIGIT [0-9]+
%%
{DIGIT} {yylval=atoi(yytext);return DIGIT;}
[\n ] {}
. {return *yytext;}
%%
You have the direct answer to your question from trojanfoe - you need to include <stdio.h> to declare the function printf(). This is true in any source code presented to the C compiler.
However, you should also note that the conventional suffix for Yacc source is .y (rather than .yacc), and for Lex source is .l (rather than .lex). In particular, using those sufffixes means that make will know what to do with your source, rather than having to code the compilation rules by hand.
Given files lex.l and yacc.y, make compiles them to object code using:
$ make lex.o yacc.o
rm -f lex.c
lex -t lex.l > lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
yacc yacc.y
mv -f y.tab.c yacc.c
cc -O -std=c99 -Wall -Wextra -c -o yacc.o yacc.c
rm lex.c yacc.c
$
This is in a directory with a makefile that sets CFLAGS = -O -std=c99 -Wall -Wextra. (This was on MacOS X 10.6.6.) You will sometimes see other similar rules used; in particular, lex generates a file lex.yy.c by default (at least on MacOS X), and you'll often see a rule such as:
lex lex.l
mv lex.yy.c lex.c
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.c
Or even:
lex lex.l
cc -O -std=c99 -Wall -Wextra -c -o lex.o lex.yy.c
The alternatives are legion; use make and it gets it right.
Include header file stdio.h
for compilation
open terminal locate both files and type
lex pos1.l
yacc pos.y
cc lex.yy.c y.tab.h -ll
./a.out
You can follow these steps.
you just need to save in file
pos1.l and pos.y
I hope it will work
Related
I have a test file (just for the link test) where I overload the new/delete operators with my own malloc/free library called libxmalloc.a. But I keep getting "undefined reference to" error as following when linking the static library, even I change the order of test.o and -lxmalloc. But everything works well with other C programs linking this library. I'm so confused with this issue and appreciate any clue.
Error Msg:
g++ -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64 -c -o test.o test.cpp
g++ -m64 -O3 -L. -o demo test.o -lxmalloc
test.o: In function `operator new(unsigned long)':
test.cpp:(.text+0x1): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete(void*)':
test.cpp:(.text+0x11): undefined reference to `free(void*)'
test.o: In function `operator new[](unsigned long)':
test.cpp:(.text+0x21): undefined reference to `malloc(unsigned long)'
test.o: In function `operator delete[](void*)':
test.cpp:(.text+0x31): undefined reference to `free(void*)'
test.o: In function `main':
test.cpp:(.text.startup+0xc): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x19): undefined reference to `malloc(unsigned long)'
test.cpp:(.text.startup+0x24): undefined reference to `free(void*)'
test.cpp:(.text.startup+0x31): undefined reference to `free(void*)'
collect2: ld returned 1 exit status
make: *** [demo] Error 1
My test.cpp file:
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
void*
operator new (size_t sz)
{
return malloc(sz);
}
void
operator delete (void *ptr)
{
free(ptr);
}
void*
operator new[] (size_t sz)
{
return malloc(sz);
}
void
operator delete[] (void *ptr)
{
free(ptr);
}
int
main(void)
{
int *iP = new int;
int *aP = new int[3];
delete iP;
delete[] aP;
return 0;
}
My Makefile:
CFLAGS += -m64 -O3 -I/usr/include/ethos -I/usr/include/nacl/x86_64
CXXFLAGS += -m64 -O3
LIBDIR += -L.
LIBS += -lxmalloc
all: demo
demo: test.o
$(CXX) $(CXXFLAGS) $(LIBDIR) -o demo test.o $(LIBS)
test.o: test.cpp
$(CXX) $(CFLAGS) -c -o $# $<
clean:
- rm -f *.o demo
But everything works well with other C programs linking this library.
Did you notice that C and C++ compilation create different symbol names on object file level? It's called 'name mangling'.
The (C++) linker would show undefined references as demangled symbols in the error message, which might confuse you. If you inspect your test.o file with nm -u you'll see that the referenced symbol names don't match with those provided in your library.
If you want to use functions linked in as externals that were compiled using the plain C compiler, you'll need their function declarations enclosed in an extern "C" {} block which suppresses C++ name mangling for everything declared or defined inside, e.g.:
extern "C"
{
#include <dual/xalloc.h>
#include <dual/xmalloc.h>
}
Even better, you might wrap your function declarations in your header files like this:
#if defined (__cplusplus)
extern "C" {
#endif
/*
* Put plain C function declarations here ...
*/
#if defined (__cplusplus)
}
#endif
I know this a trivial question but I am having difficulties in running the m5ops in gem5,
lets take for example the m5-exit.c file that has been provided by gem5, in the test programs, how would I compile it and link it to the file m5op_x86.S
Currently this is the way I am compiling and linking it:
gcc m5-exit.c -I ~/Desktop/gem5_86/gem5/include -o test ~/Desktop/gem5_86/gem5/util/m5/m5op_x86.S
the error i get:
/tmp/ccXsGX3d.o: relocation R_X86_64_16 against undefined symbol `M5OP_ARM' can not be used when making a PIE object; recompile with -fPIC
the directory i am in is:
gem5/tests/test-progs/m5-exit/src
the code for m5-exit.c is from the gem5 directory found here
This is a copy of: How to use m5 in gem5-20 which was deleted on my other answer, since my previous DRY link-only answer was removed followed by an unsuccessful (although correct, but not enough users who care) dupe close attempt.
On gem5 046645a4db646ec30cc36b0f5433114e8777dc44 I can do:
scons -C util/m5 build/x86/out/m5
gcc -static -I include -o main.out main.c util/m5/build/x86/out/libm5.a
with:
main.c
#include <gem5/m5ops.h>
int main(void) {
m5_exit(0);
}
Or for ARM:
sudo apt install gcc-aarch64-linux-gnu g++-aarch64-linux-gnu
scons -C util/m5 build/aarch64/out/m5
aarch64-linux-gnu-gcc -static -I include -o main.out main.c \
util/m5/build/aarch64/out/libm5.a
But in practice, I often just don't have the patience for this business, so I just misbehave and add raw assembly directly as shown here muahahaha e.g.:
#if defined(__x86_64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ (".word 0x040F; .word 0x0043;" : : "D" (0), "S" (0) :)
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ (".word 0x040F; .word 0x0041;" : : "D" (0), "S" (0) :)
#elif defined(__aarch64__)
#define LKMC_M5OPS_CHECKPOINT __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x43 << 16);" : : : "x0", "x1")
#define LKMC_M5OPS_DUMPSTATS __asm__ __volatile__ ("mov x0, 0; mov x1, 0; .inst 0xFF000110 | (0x41 << 16);" : : : "x0", "x1")
More general m5op information can also be found at: What are pseudo-instructions for in gem5?
Tested on Ubuntu 20.04.
There are two codes in Fortran and C++ with simple array manipulations with different declarations of arrays for C++. Let me know how to improve C++ code to get similar efficiency as in the Fortran code. The duration of runs in seconds is summarized below.
The Fortran program:
! fort.f90
PARAMETER ( N=1000000, M=10000 )
REAL*8, ALLOCATABLE :: D(:)
ALLOCATE(D(N))
A=1.0
DO J=1,M
DO I=1,N
D(I)=A+I+J
ENDDO
ENDDO
END
The Cpp program:
// main.cpp
using namespace std;
using namespace blitz;
int main(int argc, char* argv[]){
int N=1000000, M=10000;
double* D=new double[N];
//Array<double,1> D(N); // for Blitz C++
//vector<double>D(N);
//valarray<double>D(N);
const double a=1.0;
size_t i,j;
for (j=0; j<M; j++)
for (i=0; i<N; i++)
D[i]=a+i+j;
return 0;
}
g++ main.cpp -o main && time main
g++ main.cpp -o main -Ofast && time main
f95 fort.f90 -o fort && time fort
f95 fort.f90 -o fort -Ofast && time fort
Here is statistics:
1) double* D=new double[N]; g++: 58,1s, g++ -Ofast : 16,413s
2) valarrayD(N); ~ the same
3) vector; ~ the same
4) BlitzC++ ; g++ : 3m19,017s, g++ -Ofast : 15,142s
5) ALLOCATE(d(N)); f95 : 42,092s, f95 -Ofast : 0,002s
I'm trying to compile the following code
#include <iostream>
#include <windows.h>
#include <objbase.h>
int main (int argc, char** argv) {
HRESULT hr;
hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (SUCCEEDED(hr)) {
std::cout << "Initialized" << std::endl;
} else {
std::cout << "Failed" << std::endl;
}
CoUninitialize();
return 0;
}
but
g++ -o test -L"<dir>" -lOle32 <file>.cpp
# <dir> contains Ole32.Lib
always tells me that __imp_CoInitializeEx and __imp_CoUninitialize are undefined and -print-file-name=Ole32.Lib just return Ole32.Lib. If g++ doesn't find Ole32.Lib, maybe
g++ -c -o test.o <file>.cpp
ld -L"<dir>" -lOle32 -o test test.o
works. Now g++/ld actually finds CoInitializeEx and CoUninitialize, but the standard library seems to be missing and adding -static-libstdc++ or -lstdc++ or -llibstdc++ doesn't help either. So what am I missing? Why is g++ unable to find CoInitializeEx and CoUninitialize?
EDIT: I can definitely say that there is nothing wrong with my code, my header files and my library files, because I can compile the code using Visual Studios compiler:
cl /c /EHsc ^
/I"<...>\Microsoft Visual Studio 14.0\VC\include" ^
/I"<...>\Windows Kits\10\Include\<version>\ucrt" ^
/I"<...>\Windows Kits\10\Include\<version>\shared" ^
/I"<...>\Windows Kits\10\Include\<version>\um" ^
/Fotest.obj ^
main.cpp
link /nologo /machine:x64 /subsystem:console ^
/libpath:"<...>\Microsoft Visual Studio 14.0\VC\lib\amd64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\ucrt\x64" ^
/libpath:"<...>\Windows Kits\10\Lib\<version>\um\x64" ^
/out:test.exe ^
test.obj Ole32.Lib
#include <iostream>
using namespace std;
int main()
{
constexpr double GetPi() {return 22.0/7;}
cout << GetPi() << endl;
}
No idea what is going on here. Please help me.
I've tried to compile this and even tried to re-format the code but it doesn't really help much. I thought this was the correct way you did things? What's going on here? It's a constant expression.
Here is the compilation error:
C:\Windows\system32\cmd.exe /C "C:/TDM-GCC-64/bin/mingw32-make.exe -j4` SHELL=cmd.exe -e -f Makefile"
"----------Building project:[ Constant_Expression - Debug ]----------"
mingw32-make.exe[1]: Entering directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
codelite-cc C:/TDM-GCC-64/bin/g++.exe -c "C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp" -g -O0 -std=c++11 -Wall -o ./Debug/main.cpp.o -I. -I.
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp: In function 'int main()':
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:7:30: error: a function-definition is not allowed here before '{' token
constexpr double GetPi() {return 22.0/7;}
^
C:/Program Files/CodeLite/CPP/Constants/Constant_Expression/main.cpp:8:19: error: 'GetPi' was not declared in this scope
cout << GetPi() << endl;
^
mingw32-make.exe[1]: *** [Debug/main.cpp.o] Error 1
Constant_Expression.mk:93: recipe for target 'Debug/main.cpp.o' failed
mingw32-make.exe[1]: Leaving directory 'C:/Program Files/CodeLite/CPP/Constants/Constant_Expression'
mingw32-make.exe: *** [All] Error 2
Makefile:4: recipe for target 'All' failed
3 errors, 0 warnings
In C++ you are not allowed to define a function inside another function. (unlike closures in javascript).
You have to define GetPI() outside the main() function
#include <iostream>
using namespace std;
constexpr double GetPi() {return 22.0/7;}
int main()
{
cout << GetPi() << endl;
}