I am using clang matcher to obtain the result nodes. From the result nodes, I am able to get the line number, let us say 17. Now, I would like to get the entire source code in that line. Please help.
Let me explain in detail. I have a clang matcher that finds the floating literal in the source code. For example, line 17, sr = 2.0 * rt_urand_Upu32_Yd_f_pw_snf(u); is the source code, then it matches the 2.0. This is my matcher:
const auto PA = floatLiteral(
isExpansionInMainFile(),
unless(hasAncestor(arraySubscriptExpr()))
).bind("pa");
MatchFinder MatchFinder;
MatchFinder.addMatcher(PA, &Handler);
MatchFinder.matchAST(Context);
From the matcher, I am able to obtain the node where it got matched. I am able to retrieve the line number (line 17) and column number (6). Please find my code below:
const clang::FloatingLiteral* Variable = Result.Nodes.getNodeAs<clang::FloatingLiteral>("pa");
clang::SourceRange loc = Variable16->getSourceRange();
locStart = srcMgr.getPresumedLoc(loc.getBegin());
locEnd = srcMgr.getPresumedLoc(loc.getEnd());
std::cout << locStart.getLine()<< ":" << locEnd.getLine() << std::endl;
std::cout << locStart.getColumn() <<":" << locEnd.getColumn() << std::endl;
Now, if I try to retrieve the source code I am getting only the partial data. After doing some research in online, I tried to retrieve the source code in two ways. First approach is using lexer, please find the code below:
llvm::StringRef ref = Lexer::getSourceText(CharSourceRange::getCharRange(statement->getSourceRange()), srcMgr, LangOptions());
cout << ref.str() << endl;
Second approach is using rewriter, please find the code below:
clang::Rewriter rewriter;
rewriter.setSourceMgr(Result.Context->getSourceManager(),Result.Context->getLangOpts());
cout<<rewriter.getRewrittenText (loc)<<endl;
To my understanding, it seems that I need the sourcerange starting from column 0 of line 17 to end of column in line 17. The AST matcher only matches specific node, so my question is:
1) is it possible to get the final column number of line 17?
2) is there any other approach to get the source code from line number?
3) is there any other approach to get the source code from matcher?
Thanks for the help.
There is no direct way to get the last column of a line , but there is a solution to get the beginning of the line . I assume that you have the SourceManager(SM) and the SourceLocation(SL)
SM.translateLineCol(SM.getMainFileID(),SM.getSpellingLineNumber(SL),1);
If you really want to get the end of specific line you can set the column number to a incredible number , like 1000 . If the line has less than 1000 characters , it will stuck at last character , but if the line has more than 1000 characters , it will not appear at the end of line , so this solution is not stable . The example is getting the end location of line 17.
SM.translateLineCol(SM.getMainFileID(),17,1000);
By Using the solution above , you can get source code by using Rewriter(Rw) . For example , if you want to get the code in line 17 , and store it in string result
SourceLocation thisline=SM.translateLineCol(SM.getMainFileID(),17,1); // get the beginning of line 17
SourceLocation nextline=SM.translateLineCol(SM.getMainFileID(),18,1); // get the beginning of line 18
string result = Rw.getRewrittenText(SourceRange(thisline,nextline));
Yes , if you have proper SourceRange and Rewriter , you can use getRewrittenText() from match result .
Related
I have an binary file with shows glibberish infos if i open it in Notepad.
I am working on an plugin to use with wireshark.
So my problem is that I need help. I am reading in an File and need to find 'V' '0' '0' '1' (0x56 0x30 0x30 0x31) in the File, because its the start of an Header, with means there is an packet inside. And I need to do this for the whole file, like parsing. Also should start the Frame with V 0 0 1 and not end with it.
I currently have an Code where I am searching for 0x7E and parse it. What I need is the length of the frame. For example V 0 0 1 is found, so the Length from V to the Position before the next V 0 0 1 in the File. So that I can work with the length and add it to an captured length to get the positions, that wireshark can work with.
For example my unperfect Code for working with 0x7E:
local line = file:read()
local len = 0
for c in (line or ''):gmatch ('.') do
len = len + 1
if c:byte() == 0x7E then
break
end
end
if not line then
return false
end
frame.captured_length = len
Here is also the Problem that the Frame ends with 7E which is wrong. I need something that works perfectly for 'V' '0' '0' '1'. Maybe I need to use string.find?
Please help me!
Thats an example how my file looks like if i use the HEX-Editor in Visual Studio Code.
Lua has some neat pattern tools. Here's a summary:
(...) Exports all captured text within () and gives it to us.
-, +, *, ?, "Optional match as little as possible", "Mandatory match as much as possible", "optional match as much as possible", "Optional match only once", respectively.
^ and $: Root to start or end of file, respectively.
We'll be using this universal input and output to test with:
local output = {}
local input = "V001Packet1V001Packet2oooV001aaandweredonehere"
The easiest way to do this is probably to recursively split the string, with one ending at the character before "V", and the other starting at the character after "1". We'll use a pattern which exports the part before and after V001:
local this, next = string.match(input, "(.-)V001(.*)")
print(this,next) --> "", "Packet1V001Packet2..."
Simple enough. Now we need to do it again, and we also need to eliminate the first empty packet, because it's a quirk of the pattern. We can probably just say that any empty this string should not be added:
if this ~= "" then
table.insert(output, this)
end
Now, the last packet will return nil for both this and next, because there will not be another V001 at the end. We can prepare for that by simply adding the last part of the string when the pattern does not match.
All put together:
local function doStep(str)
local this, next = string.match(str, "(.-)V001(.*)")
print(this,next)
if this then
-- There is still more packets left
if this ~= "" then
-- This is an empty packet
table.insert(output, this)
end
if next ~= "" then
-- There is more out there!
doStep(next)
end
else
-- We are the last survivor.
table.insert(output, str)
end
end
Of course, this can be improved, but it should be a good starting point. To prove it works, this script:
doStep(input)
print(table.concat(output, "; "))
prints this:
Packet1; Packet2ooo; aaandweredonehere
I am using python to insert *Include, Input=file.inp into step load definition section to apply for pressure boundary condition on nodes. Here is my script, however, it is inserted in Part level section. I am wondering how to control the insert position using python. Thanks
def GetKeywordPosition(myModel, blockPrefix, occurrence=1):
if blockPrefix == '':
return len(myModel.keywordBlock.sieBlocks)+1
pos = 0
foundCount = 0
for block in myModel.keywordBlock.sieBlocks:
if string.lower(block[0:len(blockPrefix)])==\
string.lower(blockPrefix):
foundCount = foundCount + 1
if foundCount >= occurrence:
return pos
pos=pos+1
return +1
position = GetKeywordPosition(myModel, '*step')+24
myModel.keywordBlock.synchVersions(storeNodesAndElements=False)
myModel.keywordBlock.insert(position, "\n*INCLUDE, INPUT=file.inp")
You can adapt the re module. This should work
import re
# Get keywordBlock object
kw_block = myModel.keywordBlock
kw_block.synchVersions(storeNodesAndElements=False)
sie_blocks = kw_block.sieBlocks
# Define keywords for the search (don't forget to exclude special symbols with '\')
kw_list = ['\*Step, name="My Step"']
# Find index
idx = 0
for kw in kw_list:
r = re.compile(kw)
full_str = filter(r.match, sie_blocks[idx:])[0]
idx += sie_blocks[idx:].index(full_str)
UPD: Some explanations as requested
As keywords in the .inp file could be somewhat repetitive, the main idea here is to create a "search route", where the last pattern in the list will correspond to a place where you want to make your modifications (for example, if you want to find the "*End" keyword after a specific "*Instance" keyword).
So we proceed iteratively through our "search route" == list of search patterns:
Compile the regex expression;
Find the first appearance of the pattern in the sie_blocks starting from the index idx;
Update the idx so the next search is performed from this point.
Hope this will help
Been trying to find my way through Lua, so I have a file containing N lines of numbers, 3 per line, it is actually x,y,z coordinates. I could make it a CSV file and use some Lua CSV parser, but I guess it's better if I learn how to do this regardless.
So what would be the best way to deal with this? So far I am able to read each line into a table line by the code snippet below, but 1) I don't know if this is a string or number table, 2) if I print tbllinesx[1], it prints the whole line of three numbers. I would like to be able to have tbllines[1][1], tbllines[1][2] and tbllines[1][3] corresponding to the first 3 number of 1st line of my file.
local file = io.open("locations.txt")
local tbllinesx = {}
local i = 0
if file then
for line in file:lines() do
i = i + 1
tbllinesx[i] = line
end
file:close()
else
error('file not found')
end
From Programming in Lua https://www.lua.org/pil/21.1.html
You can call read with multiple options; for each argument, the
function will return the respective result. Suppose you have a file
with three numbers per line:
6.0 -3.23 15e12
4.3 234 1000001
... Now you want to print the maximum of each line. You can read all three numbers in a single call to read:
while true do
local n1, n2, n3 = io.read("*number", "*number", "*number")
if not n1 then break end
print(math.max(n1, n2, n3))
end
In any case, you should always consider the alternative of reading the
whole file with option "*all" from io.read and then using
gfind to break it up:
local pat = "(%S+)%s+(%S+)%s+(%S+)%s+"
for n1, n2, n3 in string.gfind(io.read("*all"), pat) do
print(math.max(n1, n2, n3))
end
I'm sure you can figure out how to modify this to put the numbers into table fields on your own.
If you're using three captures you can just use table.pack to create your line table with three entries.
Assuming you only have valid lines in your data file (locations.txt) all you need is change the line:
tbllinesx[i] = line
to:
tbllinesx[i] = { line:match '(%d+)%s+(%d+)%s+(%d+)' }
This will put each of the three space-delimited numbers into its own spot in a table for each line separately.
Edit: The repeated %d+ part of the pattern will need to be adjusted according to your actual input. %d+ assumes plain integers, you need something more involved for possible minus sign (%-?%d+) and for possible dot (%-?%d-%.?%d+), and so on. Of course the easy way would be to grab everything that is not space (%S+) as a potential number.
I am trying to solve a HackerEarth problem using Ruby
The problem is provided in the following link:
https://www.hackerearth.com/problem/algorithm/find-product/
My solution for the problem is here :
n = gets.chomp.to_i
a = Array.new
if n <= 1000
n.times do
a << gets.chomp.to_i
end
end
a.each { |m| print m.to_s + " " }
print "\n"
answer = 1
a.each do |m|
answer = ( answer * m ) % ( (10**9) + 7)
end
puts "#{answer}"
The code throws a Runtime Non zero exit code (NZEC).I am not able to understand the concept of NZEC and what particulary wrong I am doing in this code. Can someone pls help me to understand NZEC and find a work around for it.
The NZEC error appears because, you read the problem a bit quickly.
The first line must contain a single integer n, and the second line must contain each element separated by a space.
When I launch your script, it seems I need to press enter between each entry of the array. so when you test your code in hackerhearth I presume that execution failed because it receives no response after the second entry.
There is also a similar problem with your output, you print the full array before display the answer. The problem definition specifies you have to only display the answer.
One possible solution could be the following:
n = gets.chomp.to_i
a = gets.chomp.split.map(&:to_i)
answer = 1
a.each do |m|
answer = ( answer * m ) % ( (10**9) + 7)
end
puts "#{answer}"
I want to display the progress of a calculation done with a DO-loop, on the console screen. I can print out the progress variable to the terminal like this:
PROGRAM TextOverWrite_WithLoop
IMPLICIT NONE
INTEGER :: Number, Maximum = 10
DO Number = 1, MAXIMUM
WRITE(*, 100, ADVANCE='NO') REAL(Number)/REAL(Maximum)*100
100 FORMAT(TL10, F10.2)
! Calcultations on Number
END DO
END PROGRAM TextOverWrite_WithLoop
The output of the above code on the console screen is:
10.00 20.00 30.00 40.00 50.00 60.00 70.00 80.00
90.00 100.00
All on the same line, wrapped only by the console window.
The ADVANCE='No' argument and the TL10 (tab left so many spaces) edit descriptor works well to overwrite text on the same line, e.g. the output of the following code:
WRITE(*, 100, ADVANCE='NO') 100, 500
100 FORMAT(I3, 1X, TL4, I3)
Is:
500
Instead of:
100 500
Because of the TL4 edit descriptor.
From these two instances one can conclude that the WRITE statement cannot overwrite what has been written by another WRITE statement or by a previous execution of the same WRITE satement (as in a DO-loop).
Can this be overcome somehow?
I am using the FTN95 compiler on Windows 7 RC1. (The setup program of the G95 compiler bluescreens Windows 7 RC1, even thought it works fine on Vista.)
I know about the question Supressing line breaks in Fortran 95 write statements, but it does not work for me, because the answer to that question means new ouput is added to the previous output on the same line; instead of new output overwriting the previous output.
Thanks in advance.
The following should be portable across systems by use of ACHAR(13) to encode the carriage return.
character*1 creturn
! CODE::
creturn = achar(13) ! generate carriage return
! other code ...
WRITE( * , 101 , ADVANCE='NO' ) creturn , i , npoint
101 FORMAT( a , 'Point number : ',i7,' out of a total of ',i7)
There is no solution to this question within the scope of the Fortran standards. However, if your compiler understand backslash in Fortran strings (GNU Fortran does if you use the option -fbackslash), you can write
write (*,"(A)",advance="no") "foo"
call sleep(1)
write (*,"(A)",advance="no") "\b\b\bbar"
call sleep(1)
write (*,"(A)",advance="no") "\b\b\bgee"
call sleep(1)
write (*,*)
end
This uses the backslash character (\b) to erase previously written characters on that line.
NB: if your compiler does not understand advance="no", you can use related non-standard tricks, such as using the $ specifier in the format string.
The following worked perfectly using g95 fortran:
NF = NF + 1
IF(MOD(NF,5).EQ.0) WRITE(6,42,ADVANCE='NO') NF, ' PDFs'//CHAR(13)
42 FORMAT(I6,A)
gave:
5 PDFs
leaving the cursor at the #1 position on the same line. On the next update,
the 5 turned into a 10. ASCII 13 (decimal) is a carriage return.
OPEN(6,CARRIAGECONTROL ='FORTRAN')
DO I=1,5
WRITE(6,'(1H+" ",I)') I
ENDDO