how make include import in flex/bison - c

I'm making a programming language converter and, and it has import and include.
For example:
import com.nanana.MyClassFile
include "myfile.any"
I'm newbie which means I'm lost in how can I make it.
I wondering if is possible parse another file while one is been parsing.
And how can I do it?
EDIT:
The code I'm using to parse files in main function is:
yyin = fopen( argv[1], "r" );
return yyparse();
Can I use this same code, or there is another?

The lexer uses the YY_INPUT macro to obtain its data. Within the parser, once the include "myfile.any" command has been parsed, the parser will need to open up the new file and arrange that its data will be returned from YY_INPUT, instead of the original file. Once EOF has been reached, then YY_INPUT will need to continue reading from the original file. You'll probably want to store those open files on a stack so that included files can in turn include other files, but watch out for an infinite include loop.

Related

Preprocessor C program to replace include headers

I have homework assignment where I need to write a program to replace include commands (assuming there are no standard library includes) of C file with the actual .h' file (performing the preprocessor's job).
I thought using regex matching, but since we are only allowed to use ansi-C's standard libraries regex is not allowed.
I am not sure what is the efficient way to do so?
edit: there is no need to check for #defines or #ifdefs.
I suggest you follow this guide to create your program:
Open the target c file read only.
Open the destination file write only.
Create a function that you pass the input file and the output file, i will call this function "expand_function".
In the expand_function read each byte of the input, and while reading each character check if it is a #, then test if it is a include keyword, and finally if all conditions matches open the filename that will be in front the include, then call again the expand_function with the new input file and the same output file (don't forget closing all open files), and finally continue the loop. If any conditions not match write all read bytes in the output file.
Extra: Check if you are not in a dead loop of includes in the beginning of expand_function.

How to interact with an external text editor in C

I am developing a command line application in C (linux environment) to edit a particular file format. This file format is a plain XML file, which is compressed, then encrypted, then cryptographically signed.
I'd like to offer an option to the user to edit this kind of file in an easy way, without the hassle of manualy extracting the file, editing it, and then compressing, encrypting and signing it.
Ideally, when called, my application should do the following:
Open the encrypted/compressed file and extract it to a temporary location (like /tmp)
Call an external text editor like nano or sublime-text or gedit depending on which is installed and maybe the user preferences. Wait until the user have edited the file and closed the text editor.
Read the modified temporary file and encrypt/compress it, replacing the old encrypted/compressed file
How can I achieve point no. 2?
I thought about calling nano with system() and waiting for it to return, or placing an inotify() on the temp file to know when it is modified by the graphical text editor.
Which solution is better?
How can i call the default text editor of the user?
Anything that can be done in a better way?
First, consider not writing an actual application or wrapper yourself, which calls another editor, but rather writing some kind of plugin for some existing editor which is flexible enough to support additional formats and passing its input through decompression.
That's not the only solution, of course, but it might be easier for you.
With your particular approach, you could:
Use the EDITOR and/or VISUAL command-line variables (as also pointed out by #KamilCuk) to determine which editor to use.
Run the editor as a child process so that you know when it ends execution, rather than having to otherwise communicate with it. Being notified of changes to the file, or even to its opening or closing, is not good enough, since the editor may make changes multiple files, and some editors don't even keep the file open while you work on it in them.
Remember to handle the cases of the editor failing to come up; or hanging; or you getting some notification to stop waiting for the editor; etc.
Call an external text editor like nano or sublime-text or gedit depending on which is installed and maybe the user preferences. Wait until the user have edited the file and closed the text editor.
Interesting question. One way to open the xml file with the user's default editor is using the xdg-open, but it doesn't give the pid of the application, in which user will edit the file.
You can use xdg-mime query default application/xml to find out the .desktop file of the default editor, but then you have to parse this file to figure out the executable path of the program - this is exactly how xdg-open actually works, in the search_desktop_file() function the line starting with Exec= entry is simply extracted from the *.desktop to call the editor executable and pass the target file as argument... What I am trying to say, is, after you find the editor executable, you can start it, and wait until it's closed, and then check if the file content has been changed. Well, this looks like a lot of unnecessary work...
Instead, you can try a fixed well-known editor, such as gedit, to achieve the desired workflow. You can also provide user a way (i.e. a prompt or config file) to set a default xml editor, i.e. /usr/bin/sublime_text, which then can be used in your programm on next run.
However, the key is here to open an editor that blocks the calling process, until user closes the editor. After the editor is closed, you can simply check if the file has been changed and if so, perform further operations.
To find out, if the file contents have been modified, you can use the stat system call to get the inode change time of the file, before you open the file, and then compare the timestamp value with the current one once it is closed.
i.e.:
stat -c %Z filename
Output: 1558650334
Wrapping up:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
void execute_command(char* cmd, char* result) {
FILE *fp;
fp = popen(cmd, "r");
fscanf (fp, "%s" , result);
}
int get_changetime(char* filename) {
char cmd[4096];
char output[10];
sprintf(cmd, "stat -c %%Z %s", filename);
execute_command(cmd, output);
return atoi(output);
}
int main() {
char cmd[4096];
char* filename = "path/to/xml-file.xml";
uint ctime = get_changetime(filename);
sprintf(cmd, "gedit %s", filename);
execute_command(cmd, NULL);
if (ctime != get_changetime(filename)) {
printf("file modified!");
// do your work here...
}
return 0;
}

replace a substring in a string in C, windows

I want to do the following:
open and read and ASCII file
locate a substring (geographical coordinates)
create its replacement (apply corrections to the original coordinates)
overwrite the original substring (write in the original file the corrected coordinates).
The format of the ASCII file is:
$GPGGA,091306.00,4548.17420,N,00905.47990,E,1,09,0.87,233.5,M,47.2,M,,*53
I will paste here only the part of the code that is responsible for this operation:
opnmea = fopen (argv[1], "r+");
if (fgets(row_nmea, ROW, opnmea)==NULL){
if (strstr(row_nmea,"$GPGGA")!=NULL) {
sscanf(row_nmea+17, "%10c", old_phi);
sscanf(row_nmea+30, "%11c", old_lam);
sscanf(row_nmea+54, "%5c", old_h);
fputs();
}
}
What I do till now is to extract in a variable the old coordinates and I was thinking to use fputs() for overwriting the old with new values. But I could not do it. The other part of the code that is not here is computing the correct coordinates. My idea is to correct the rows one by one, as the fgets() function reads each line.
I would appreciate very much any suggestion that can show me how to use fputs() or another function to complete my work. I am looking for something simple as I am beginner with C.
Thank you in advance.
Patching a text file in place is not a good solution for this problem, for multiple reasons:
the modified version might have a different length, hence patching cannot be done in place.
the read-write operation of standard streams is not so easy to handle correctly and defeats the buffering mechanism.
if you encounter an error during the patching phase, a partially modified file can be considered corrupted as one cannot tell which coordinates have been modified and which have not.
other programs might be reading from the same file as you are writing it. They will read invalid or inconsistent data.
I strongly recommend to write a program that reads the original file and writes a modified version to a different output file.
For this you need to:
open the original file for reading opnmea = fopen(argv[1], "r");
open the output file for writing: outfile = fopen(temporary_file_name, "w");
copy the lines that do not require modification: just call fputs(row_nmea, outfile).
parse relevant data in lines that require modification with whatever method you are comfortable with: sscanf, strtok, ...
compute the modified fields and write the modified line to outfile with fprintf.
Once the file has been completely and correctly handled, you can replace the original file with rename. The rename operation is usually atomic at the file-system level, so other programs will either finish reading from the previous version or open the new version.
Of course, if the file has only one line, you could simply rewind the stream and write back the line with fprintf, but this is a special case and it will fail if the new version is shorter than the original. Truncating the extra data is not easy. An alternative is to reopen the file in write mode ("w") before writing the modified line.
I would recommend strtok(), followed by your revision, followed by strcat().
strtok() will let you separate the line using the comma as a delimiter, so you will get the field you want reliably. You can break up the line into separate strings, revise the coordinates you wish, and reassemble the line, including the commas, with strcat().
These pages include nice usage examples, too:
http://www.cplusplus.com/reference/cstring/strtok/
http://www.cplusplus.com/reference/cstring/strcat/?kw=strcat

C language, reading own source file and editing source file

I am currently working on a project which involves reading its own source code, editing it, then recompiling it. My question is how does the fopen function actually work? Is it affected when the source file calling it is open?
I have currently already written a function which reads in and finds the areas in the source code that I have to edit. When I open my source file I am able to read it in, store it in memory, iterate through it, and find what I need. The problem is when I attempt to check if the area to edit is correct through a strcmp function call nothing happens even though it is exact (I have accounted for newlines etc.).
When I copy the source code to another .c file, and have my program read that file instead (an exact copy) it works perfectly fine. I am really confused why that file works and why my source code file does not. They are exactly the same file.
If you are using windows, then beware that a file can usually only be open in a single process at a time.
So if the source file you are trying to open is already opened in your IDE, you may not be able to open in in your program using fopen.

Which method to use in searching for a line in a file

I have a file with path names to files:
/my/path1
/my/path11
/my/path12
/my/path13
The file structure is that it has individual paths in each line. All I want to do is search for the existence of a string /my/path1 or anyother in the above file many times
I could think of 2 methods.
every time get file contents line by line and then search the string. Advantage is that the file can be of anysize and I dont need to worry about buffer overflow.
Load the contents into a buffer and search it using the buffer. But as I dont have control over the file size I should be cautious here.
What is the best approach? I am working in unix. Is there any in-build library commands in C that I can make use of for this purpose? Or how can I accomplish the same task using awk in C code.
If you use stdio it will do the buffering for you. You can change its operation by using the function setvbuf to buffer more than a single line. getline can by used to check line by line.
I think loading all the file in memory is not a good idea. Using fgets and strcmp is the best way, I guess.

Resources