I'm doing a translation of acronyms. That is, if it finds 'OMS' print 'Organización Mundial del trabajo', but once I compile and run the program it runs infinitely.
I'm using Windows as a development environment. I have seen examples but I can't see where the error is. Here is the code:
%option noyywrap
%{
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
%}
%%
OMS {fprintf(yyout,"Organización Mundial del trabajo");}
%%
int main(int argc, char *argv[]) {
FILE*yyin=fopen(argv[1],"r");
FILE*yyout=fopen(argv[2],"w");
yylex();
fclose(yyin);
fclose(yyout);
return 0;
}
FILE*yyin=fopen(argv[1],"r");
FILE*yyout=fopen(argv[2],"w");
These lines declare and initialize two local variables named yyin and yyout. They are closed in the end of the function, but otherwise remain unused (that is, no one does any input/output with them). They are not available to the rest of the program. Meanwhile, global variables yyin and yyout, which are entirely separate from these local variables, remain untouched.
What you need to do is simply remove FILE* from both lines:
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
Now the names yyin and yyout refer to the global variables that are known to the rest of the program.
Related
I am learning C for an operating systems course and have just finished writing this program as per the textbook instructions:
#include <dirent.h>
#include <stdio.h>
#include "quit.h"
int main(int argc, char **argv) {
DIR *dir;
struct dirent *direntry;
arg_check(2, argc, "Specify a directory\n", 1);
if ( (dir = opendir(argv[1])) == NULL)
quit("opendir", 1);
while ((direntry = readdir(dir)) != NULL)
printf("%10d %s\n", direntry->d_ino, direntry->d_name);
closedir(dir);
exit(0);
}
This code is exactly copied from the textbook, but quit.h appears to be causing the compile to file. I have tried switching "quit.h" to , and "quit", but none of these have worked, and I cannot find other questions about this specific issue.
include "quit.h"
The word #include (with its hash # prefix) means that a file has to be read in; the content of that file (quit.h in this case) is processed exactly as if it was typed inside the program. Suppose you have a file name "test.h" which contains the single line
// this is a test
if you a have a program like this:
#include "test.h"
int main(int argc, char **argv)
...
the compiler processes (sees) exactly these lines:
// this is a test
int main(int argc, char **argv)
...
The file name specified after #include can be enclosed with angles or quotes. Conventionally, if angles are used, like
#include <stdio.h>
this means that the file (stdio.h in this case) is some system or standard file or so - in other simple words, someone else has written that file for you. If quotes are used, instead, the file specified is considered somehow part of the program you are compiling. Your quit.h seems like this. So you must have a file named quit.h. If you change that "quit.h" to "quit", a file named quit must be present in the same directory of the file you are compiling. (Actually things are more complicated, but don't mind it for now). Read your book, somewhere it should explain what is that file "quit.h".
I know it might sound strange but I'm trying to find when to get this type of error when passing a wrong argument to a main program.
Let's say I have a program that accepts 1 or 2 arguments. If it's 2 arguments it can only be:
argv[0] =./programName
and
argv[1] = "-A".
Any other argv[1] other than "-A" needs to printf a "2 No such file or directory" message.
As far as I know, this is a system message, so printing it will not work for me.
DO I need to save all possible main arguments in a file and then compare the typed arguments with the ones in the file?
Right now the way I have it is:
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/times.h>
#include <sys/wait.h>
int main (int argc, char *argv[]){
.....
...
if (argc == 2 && strcmp(argv[1], ARGV_2)!=0){
return(EXIT_FAILURE);
}
...
.....
}
I think ls does this with the error() function:
GNU Error_messages
Function: void error (int status, int errnum, const char *format, …)
Preliminary: | MT-Safe locale | AS-Unsafe corrupt heap i18n | AC-Safe
| See POSIX Safety Concepts.
The error function can be used to report general problems during
program execution. The format argument is a format string just like
those given to the printf family of functions. The arguments required
for the format can follow the format parameter. Just like perror,
error also can report an error code in textual form. But unlike perror
the error value is explicitly passed to the function in the errnum
parameter. This eliminates the problem mentioned above that the error
reporting function must be called immediately after the function
causing the error since otherwise errno might have a different value.
error prints first the program name. If the application defined a
global variable error_print_progname and points it to a function this
function will be called to print the program name. Otherwise the
string from the global variable program_name is used. The program name
is followed by a colon and a space which in turn is followed by the
output produced by the format string. If the errnum parameter is
non-zero the format string output is followed by a colon and a space,
followed by the error message for the error code errnum. In any case
is the output terminated with a newline.
The output is directed to the stderr stream. If the stderr wasn’t
oriented before the call it will be narrow-oriented afterwards.
The function will return unless the status parameter has a non-zero
value. In this case the function will call exit with the status value
for its parameter and therefore never return. If error returns, the
global variable error_message_count is incremented by one to keep
track of the number of errors reported.
So maybe something like this would achieve OP's goal as well as the other answers suggested before:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <error.h>
int main(int argc, char* argv[])
{
if (argc == 2 && strcmp(argv[1], "-A") != 0) {
error(ENOENT, ENOENT, "cannot access %s", argv[1]);
}
printf("program didn't get to here\n");
}
Outputs of ls and this example:
~/workspace/tests/ $ ./ctest bogus_dir
./ctest: cannot access bogus_dir: No such file or directory
~/workspace/tests/ $ ls bogus_dir
ls: cannot access bogus_dir: No such file or directory
I have a new problem from the question: Call a function in a Yacc file from another c file So this time, I confront with the problem of yyin function in Lex and Yacc. My codes are following:
calc.l
%{
#include "y.tab.h"
extern int yylval;
%}
%%
[0-9]+ { yylval=atoi(yytext); return NUMBER;}
[ \t];
\n return 0;
. return yytext[0];
%%
calc.y
%{
#include <stdio.h>
#include <string.h>
extern FILE* yyin;
%}
%token NAME NUMBER
%%
statement: NAME '=' expression
| expression {printf("= %d\n",$1);}
;
expression: NUMBER '+' NUMBER {$$=$1+$3;}
| NUMBER '-' NUMBER {$$=$1-$3;}
| NUMBER 'x' NUMBER {$$=$1*$3;}
| NUMBER '/' NUMBER
{ if($3 == 0)
yyerror("Error, cannot divided by zero");
else
$$=$1/$3;
}
| NUMBER {$$=$1;}
;
%%
void parse(FILE* fileInput)
{
yyin= fileInput;
while(feof(yyin)==0)
{
yyparse();
}
}
main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc,char* argv[])
{
FILE* fileInput;
char inputBuffer[36];
char lineData[36];
if((fileInput=fopen(argv[1],"r"))==NULL)
{
printf("Error reading files, the program terminates immediately\n");
exit(0);
}
parse(fileInput);
}
test.txt
2+1
5+1
1+3
This is how my codes work:
I created main.c to open a file and read it then call a function, parse(), with parameter fileInput.
In calc.y, I set the pointer yyin to be the same as fileInput so the parser can loop and read all lines in a text file (test.txt)
The problem is that yyin didn't read all lines in the text. The result I got is
= 3
The result I should get is
= 3
= 6
= 4
How could I solve this problem. Note that, I want main.c to remain.
This has nothing to do with yyin. Your problem is that your grammar does not recognize a series of statements; it only recognizes one. Having parsed the first line of the file and, ultimately, reduced it to a statement, the parser has nothing more it can do. It has no way to reduce a series of symbols starting with a statement to anything else. Since there is still input left when the parser jams up, it will return an error code to its caller, but the caller ignores that.
To enable the parser to handle multiple statements, you need a rule for that. Presumably you'll want that resulting symbol to be the start symbol, instead of statement. This would be a reasonable rule:
statements: statement
| statements statement
;
Your lexical analyzer returns 0 when it reads a newline.
All grammars from Yacc or Bison recognize 0 as meaning EOF (end of file). You told your grammar that you'd reached the end of file; it believed you.
Don't return 0 for newline. You'll probably need to have your first grammar rule iterate (accept a sequence of statements) — as suggested by John Bollinger in another answer.
So my program is effectively a DPLL SAT solver, therefore inside the program it needs to choose random variables to assign TRUE or FALSE to. If I run my once program it works fine!If if run it again it will choose different variables and still work (this is what I want).
However to produce reliable experiments I need to do repeat runs of my program. This could be done by running the program multiple times separately, but this is tedious and will take too long. I have learnt how to use bash as follows:
#!/bin/bash
for ((i=50; i>0; i--))
do
./Project 90 10 >> outfile.txt
done
However when this is done, every run picks the same 'random' variables in the same order and so produces the same results. How can I make my program run differently each time??
Thanks!!
You need to initialize the random number seed, random numbers are not really random, add this to your main()
#include <time.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand(time(NULL)); /* here at the very beginnig of main */
.
.
.
return 0;
}
this will give a different seed every time the program is executed, since time(NULL) will return a different value.
Read this for more information.
Note: as commented by Ingo Leonhardt the effect will be the same, so try this option
#include <stdlib.h>
#include <sys/time.h>
int main(int argc, char **argv)
{
struct timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec); /* here at the very beginnig of main */
.
.
.
return 0;
}
or, since every process will have a different pid this could also work1
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char **argv)
{
srand((int)getpid()); /* here at the very beginnig of main */
.
.
.
return 0;
}
1This is a POSIX solution, if you want you can research what is your OS equivalent if it doesn't support POSIX.
I am looking for a way to find the name of the executable file which runs it. meaning that if I have a file called program which runs something I would like to get its name.
Using __FILE__ does not suite me since I need the executable name not the C files name which contains the code.
I am wondering if there is a gcc macro which can help me or a built in function which I couldn't find.
EDIT:
Also using argv[0] is not appropriate since I need to call the function not only inside main.
And passing the argv[0] parameter to all the functions that might need this parameter also isnt acceptable since it will be used in the entire system (I need to hash by it).
int main(int argc,char* argv[])
{
printf("%s",argv[0]);
return 0;
}
The first argument(argv[0]) contains the name of the program which is being run.
The standard definition for main() in C is:
int main(int argc, char **argv)
argv[0] contains the name of the program as executed.
From main, pass argv[0] to wherever you might need the program's name.
Or if a lot of functions need it and you want to avoid passing it around too much, assign it to a global variable.
You asked for macros as a solution, but they are expanded at compile time. And since the name of the executable file can be changed after compilation, what you want cannot be determined at compile time, so macros are out of question.
Often remembering argv[0] from main will be quite sufficient.
If this is not the case -- for example if you're a shared library, or if you worry that your caller started you with a faked argv[0] (this is possible but unusual), you can, on POSIX-compliant systems with a mounted /proc, use readlink to resolve /proc/self/exe and get a path to the main binary of the running process:
#include <limits.h>
#include <unistd.h>
// Note that readlink does not null-terminate the result itself. This
// is important if the link target contains null bytes itself, I suppose,
// but it means that you have to take care that the null-terminator is
// placed yourself if you're going to use the file name as a string.
char buf[PATH_MAX] = { 0 };
readlink("/proc/self/exe", buf, PATH_MAX);
And on Windows, there is the GetModuleFileName function:
#include <windows.h>
TCHAR buf[MAX_PATH];
GetModuleFileName(NULL, buf, MAX_PATH);
The startup name is given via main()'s argv[0] and can be considered constant.
So why not make it available through out the program using a global reference to it.
progname.h
#ifndef PROGNAME_H
#define PROGNAME_H
extern char * progname;
#endif
main.c
#include "progname.h"
char * progname = NULL;
int main(int argc, char ** argv)
{
progname = argv[0];
...
}
Access it from any where like so
module1.c
#include <stdio.h>
#include "progname.h"
void f(void)
{
printf("progname='%s'\n", progname ?progname :"<not set>");
}