Anyone written a script that turns gcov branch coverage output into compiler warning format? - gcov

Most code editors know how to take a reasonably standard format of file_path, line_number, message_text and hyperlink into code. They know how because that's how they display compiler warnings. Visual Studio does it, and Source Insight is trivial to configure for that. If I have to I will write the script myself, but maybe someone has done so already.
Looking for a script that takes gcc's gcov branch coverage output and translates it into that format.

You can process the output of gcov with a simple awk script:
/.*:.*:/ {
split($2,tokens,":");
LINE=tokens[1];
}
/#####:/ { print FILENAME ":" LINE ": warning: Line not executed"}
/branch/ {
if ($4 == 0)
print FILENAME ":" LINE ": warning: " $0;
}
Run with awk -f warn.awk main.c.gcov
and it will convert the output to:
main.c.gcov:35: warning: branch 0 taken 0 (fallthrough)
main.c.gcov:37: warning: Line not executed

Related

How to map a shell command in the lua nvim config?

How to map a shell command in the lua nvim config?
maps.n["<F4>"] = { function() io.popen("python3 " + vim.fn.expand("%")) end, desc = "Run current Python file"}
Error:
E5108: Error executing lua: /home/kobe/.config/nvim/lua/core/mappings.lua:19: attempt to perform arithmetic on a string value
stack traceback:
/home/kobe/.config/nvim/lua/core/mappings.lua:19: in function </home/kobe/.config/nvim/lua/core/mappings.lua:19>
Maybe this isn't exactly what you're looking for, but I use plugins like toggleterm for this. You can setup keymappings to run whatever shell command or program you want, and also have it show up in a floating or none-floating window, too.
As for just mapping it without any plugins and having the command be executing, I'm not entirely sure.
In Lua, operand to concatenate 2 strings is .. not + as in Python.
Correct your code : function() io.popen("python3 " .. vim.fn.expand("%")) end

dxl CreateProcess failed for system cmd instruction

I want to call run a file called csvplot.vbs (from this site) to turn a .csv file I have written using dxl (has 5 columns, each with a heading and then just numerical data) into a graph (stored as .png).
I have run the following instruction directly through cmd with success:
#echo off
cscript //nologo C:\Users\Administrator\csvplot.vbs C:\PROGRA~1\IBM\Rational\DOORS\9.6\lib\dxl\addins\Verification\Statistics\statGenTest_Top_Level.csv C:\PROGRA~1\IBM\Rational\DOORS\9.6\lib\dxl\addins\Verification\Statistics\statGenTest_Top_Level.png 800 600 1 3 1 4 1 5
pause
This produces the desired .png file.
What I want, however, is to be able to execute this through DOORS, so that whenever the script that generates the raw data is run, it also produces a graph.
What I have is this as my test case:
string echostr = "#echo off"
string commands = "cscript //nologo C:\\Users\\Administrator\\csvplot.vbs C:\\PROGRA~1\\IBM\\Rational\\DOORS\\9.6\\lib\\dxl\\addins\\Verification\\Statistics\\statGenTest_Top_Level.csv C:\\PROGRA~1\\IBM\\Rational\\DOORS\\9.6\\lib\\dxl\\addins\\Verification\\Statistics\\statGenTest_Top_Level.png 800 600 1 3 1 4 1 5"
system("cmd /c start #echo off") // doesn't recognise echo command
system("cmd /c start " commands "")
I get an error:
"Windows cannot find '#echo'. Make sure you typed the name correctly,
and then try again."
I am at a loss on how to get the script to run though cmd from dxl, and I would appreciate any help. I've only had one previous foray into system() prompts through dxl, and it was only to open a .pdf. In the meantime I will keep trying to work this out. Please let me know if I can provide any further information.
Edit: Further Information
#echo: I removed the # to see how it operates, it brings up a blank
cmd window and performs no further action. In order to even run the things in the points below, I left the # off.
I deleted "/c start" from the second system() line: this opens one command line with the usual white text at the top, and a second over the top that is completely blank.
I changed the first line as follows, and commented out the second:
system("cmd /c start echo off" "\n" commands "")
--- this got a similar result to the second dot-point, but only with one cmd window, the black (no text one)
If I don't include the "\n" marker then I get a cmd window with text of "off" commands (where commands is the defined string above).
If I only have the system("cmd /c start " commands "") line, and not the echo line, then a cmd window briefly flashes and disappears and no further results demonstrating the success of the script appear.
So my issue is this: I know this script works when run directly through command line, the problem I have is that I cannot now run it through dxl.
I have developed a solid work-around that does exactly what I need.
The issue was that the input I had dxl writing was not going through command line correctly.
Knowing that the script ran from cmd correctly and, in turn, that the script executed from a batch file correctly, and that I could run the batch file from dxl, my solution was as follows:
Define the paths in dxl using the format C:\PROGRA~1\PATHNAME\
Using the Stream write() command to write the instructions directly
to a .bat file
Then using the system() command to run the .bat file
I have included some of my code, so that maybe it might help someone attempting to do the same thing. (I'll gladly take any advice on better programming conventions.)
// functions used: genFileName(), assume if a variable is not declared here, it was declared under my globals
// genFileName() returns a string of the file name, replacing any " " with "_" so cmd doesn't cry when I run it
string basename = genFileName()
string fcsv = basename ".csv"
string csvPath = "blahblahthefilepath" fcsv
if(fileExists_(csvPath)) isFile = true
Stream fOut = append(csvPath)
// === if file does not exist, create, give column names
if( !isFile){
fOut << "Date and Time,count1,count2,count3,count4" "\n"
}
else ack ("File name exists, append stats to file?" // may not be necessary
// === print to file ===
fOut << datetime "," ctot "," ctc "," cti "," ctnc "\n"
// ===== Create Batch file to run grapher ===
string columnsToPlot = "1 3 1 4 1 5" // ==> may develop this to allow user to choose
string graphDim = "800 600" // ==> px dim, may develop for user choice
string fbat = basename ".bat"
string batPath = "blahblahthefilepath"
Stream batOut = write(batPath fbat)
batOut << "#echo off" "\n"
batOut << "title Batch file to plot statistics for " fcsv "\n"
batOut << "cscript //nologo " batPath "csvplot.vbs " batPath fcsv " " batPath basename ".png " graphDim " " columnsToPlot ""
system("cmd /c start " batPath fbat "")
// some infoBox feedback DB to tell the user that the files were created
Good luck to anyone else who is attempting something similar, and I hope this is of use to someone.
Does running the dxl script without the # in front of the echo command work?

Getting return status AND program output

I need to use Lua to run a binary program that may write something in its stdout and also returns a status code (also known as "exit status").
I searched the web and couldn't find something that does what I need. However I found out that in Lua:
os.execute() returns the status code
io.popen() returns a file handler that can be used to read process output
However I need both. Writing a wrapper function that runs both functions behind the scene is not an option because of process overhead and possibly changes in result on consecutive runs. I need to write a function like this:
function run(binpath)
...
return output,exitcode
end
Does anyone has an idea how this problem can be solved?
PS. the target system rung Linux.
With Lua 5.2 I can do the following and it works
-- This will open the file
local file = io.popen('dmesg')
-- This will read all of the output, as always
local output = file:read('*all')
-- This will get a table with some return stuff
-- rc[1] will be true, false or nil
-- rc[3] will be the signal
local rc = {file:close()}
I hope this helps!
I can't use Lua 5.2, I use this helper function.
function execute_command(command)
local tmpfile = '/tmp/lua_execute_tmp_file'
local exit = os.execute(command .. ' > ' .. tmpfile .. ' 2> ' .. tmpfile .. '.err')
local stdout_file = io.open(tmpfile)
local stdout = stdout_file:read("*all")
local stderr_file = io.open(tmpfile .. '.err')
local stderr = stderr_file:read("*all")
stdout_file:close()
stderr_file:close()
return exit, stdout, stderr
end
This is how I do it.
local process = io.popen('command; echo $?') -- echo return code of last run command
local lastline
for line in process:lines() do
lastline = line
end
print(lastline) -- the return code is the last line of output
If the last line has fixed length you can read it directly using file:seek("end", -offset), offset should be the length of the last line in bytes.
This functionality is provided in C by pclose.
Upon successful return, pclose() shall return the termination status
of the command language interpreter.
The interpreter returns the termination status of its child.
But Lua doesn't do this right (io.close always returns true). I haven't dug into these threads but some people are complaining about this brain damage.
http://lua-users.org/lists/lua-l/2004-05/msg00005.html
http://lua-users.org/lists/lua-l/2011-02/msg00387.html
If you're running this code on Win32 or in a POSIX environment, you could try this Lua extension: http://code.google.com/p/lua-ex-api/
Alternatively, you could write a small shell script (assuming bash or similar is available) that:
executes the correct executable, capturing the exit code into a shell variable,
prints a newline and terminal character/string onto standard out
prints the shell variables value (the exit code) onto standard out
Then, capture all the output of io.popen and parse backward.
Full disclosure: I'm not a Lua developer.
yes , your are right that os.execute() has returns and it's very simple if you understand how to run your command with and with out lua
you also may want to know how many variables it returns , and it might take a while , but i think you can try
local a, b, c, d, e=os.execute(-what ever your command is-)
for my example a is an first returned argument , b is the second returned argument , and etc.. i think i answered your question right, based off of what you are asking.

Comparing generated executables for equivilance

I need to compare 2 executables and/or shared objects, compiled using the same compiler/flags and verify that they have not changed. We work in a regulated environment, so it would be really useful for testing purposes to isolate exactly what parts of the executable has changed.
Using MD5Sums/Hashes doesn't work due to the headers containing information about the file.
Does anyone know of a program or way to verify that 2 files are executionally the same even if they were built at a different time?
An interesting question. I have a similar problem on linux. Intrusion detection systems like OSSEC or tripwire may generate false positives if the hashsum of an executable changes all of a sudden. This may be nothing worse than the Linux "prelink" program patching the executable file for faster startups.
In order to compare two binaries (in the ELF format), one can use the "readelf" executable and then "diff" to compare outputs. I'm sure there are refined solutions, but without further ado, a poor man's comparator in Perl:
#!/usr/bin/perl -w
$exe = $ARGV[0];
if (!$exe) {
die "Please give name of executable\n"
}
if (! -f $exe) {
die "Executable $exe not found or not a file\n";
}
if (! (`file '$exe'` =~ /\bELF\b.*?\bexecutable\b/)) {
die "file command says '$exe' is not an ELF executable\n";
}
# Identify sections in ELF
#lines = pipeIt("readelf --wide --section-headers '$exe'");
#sections = ();
for my $line (#lines) {
if ($line =~ /^\s*\[\s*(\d+)\s*\]\s+(\S+)/) {
my $secnum = $1;
my $secnam = $2;
print "Found section $1 named $2\n";
push #sections, $secnam;
}
}
# Dump file header
#lines = pipeIt("readelf --file-header --wide '$exe'");
print #lines;
# Dump all interesting section headers
#lines = pipeIt("readelf --all --wide '$exe'");
print #lines;
# Dump individual sections as hexdump
for my $section (#sections) {
#lines = pipeIt("readelf --hex-dump='$section' --wide '$exe'");
print #lines;
}
sub pipeIt {
my($cmd) = #_;
my $fh;
open ($fh,"$cmd |") or die "Could not open pipe from command '$cmd': $!\n";
my #lines = <$fh>;
close $fh or die "Could not close pipe to command '$cmd': $!\n";
return #lines;
}
Now you can run for example, on machine 1:
./checkexe.pl /usr/bin/curl > curl_machine1
And on machine 2:
./checkexe.pl /usr/bin/curl > curl_machine2
After having copypasted, SFTP-ed or NSF-ed (you don't use FTP, do you?) the files into the same filetree, compare the files:
diff --side-by-side --width=200 curl_machine1 curl_machine2 | less
In my case, differences exist in section ".gnu.conflict", ".gnu.liblist", ".got.plt" and ".dynbss", which might be ok for a "prelink" intervention, but in the code section, ".text", which would be a Bad Sign.
To follow up, here is what I came up with finally:
Instead of comparing the final executables & shared objects, we compared the .o files output before linking. We assumed that the linking process was sufficiently reproducible that this would be fine.
It works in some of our cases, where we have two builds were we've made some small change that shouldn't effect the final code (Code pretty-printer) but doesn't help us if we do not have the build intermediary output.
You can compare the contents of RO and RW initialized sections by generating a binary file from the ELF file.
objcopy <elf_file> -O binary <binary_file>
Use the generated binary files to compare if they are identical, using diff, for example.
In my opinion, this is enough to grantee you are generating the same executable.
A few years back I had to do the same thing. We had to prove that we could rebuild the executable from source when given only a revision number, revision control repository, build tools, and build configuration. Note: If any of these change you may see a difference.
I remember there is some timestamps in the executable. The trick is to realize that the file is not just a bunch of bytes, that can not be interpreted. The file has sections, most will not change, but there will be a section for time of build (or some such thing).
I don't remember all the details, but the commands you will need are { objcopy, objdump, nm }, I think objdump would be the first to try.
Hope this helps.

Vim script to compile TeX source and launch PDF only if no errors

I am switching to using Vim for for my LaTeX editing environment. I would like to be able to tex the source file from within Vim, and launch an external viewing if the compile was successful.
I know about the Vim-Latex suite, but, if possible, would prefer to avoid using it: it is pretty heavy-weight, hijacks a lot of my keys, and clutters up my vimruntime with a lot of files.
Here is what I have now:
if exists('b:tex_build_mapped')
finish
endif
" use maparg or mapcheck to see if key is free
command! -buffer -nargs=* BuildTex call BuildTex(0, <f-args>)
command! -buffer -nargs=* BuildAndViewTex call BuildTex(1, <f-args>)
noremap <buffer> <silent> <F9> <Esc>:call BuildTex(0)<CR>
noremap <buffer> <silent> <S-F9> <Esc>:call BuildTex(1)<CR>
let b:tex_build_mapped = 1
if exists('g:tex_build_loaded')
finish
endif
let g:tex_build_loaded = 1
function! BuildTex(view_results, ...)
write
if filereadable("Makefile")
" If Makefile is available in current working directory, run 'make' with arguments
echo "(using Makefile)"
let l:cmd = "!make ".join(a:000, ' ')
echo l:cmd
execute l:cmd
if a:view_results && v:shell_error == 0
call ViewTexResults()
endif
else
let b:tex_flavor = 'pdflatex'
compiler tex
make %
if a:view_results && v:shell_error == 0
call ViewTexResults()
endif
endif
endfunction
function! ViewTexResults(...)
if a:0 == 0
let l:target = expand("%:p:r") . ".pdf"
else
let l:target = a:1
endif
if has('mac')
execute "! open -a Preview ".l:target
endif
endfunction
The problem is that v:shell_error is not set, even if there are compile errors. Any suggestions or insight on how to detect whether a compile was successful or not would be greatly appreciated! Thanks!
Between the answers given here, plus some study of other approaches, I think that this has been satisfactorily solved. I am posting the solution here in case anyone else is interested.
Basically, the best solution appears to be to use Rubber, a wrapper around LaTeX, that generally "just works", and provides very clean output/errors. The solution I present below preferentially uses Rubber if it is found on the system and no Makefile is found in the current directory. If a Makefile is found, it uses that instead. If there is no Makefile and Rubber is not installed, it uses pdflatex. In all cases, if the source fails to compile, the (filtered and parsed) errors are sent to the QuickFix buffer and the QuickFix window is automatically opened. If it compiles successfully, a short message is written, and if the user requested it, the PDF will be opened for viewing.
In my own installation, I have lifted the (excellent) "SetLatexEfm()" function from Vim-Latex to parse and filter the tex build output. If this function is not found, however, the function below defaults to setting an error message format that works fine enough for the errors to be identified and highlighted in the QuickFix window, albeit with lots of crud.
function! BuildTex(view_results, ...)
" record position
let save_cursor = getpos(".")
" save work
silent write
" From: http://stackoverflow.com/questions/2679475/vim-script-to-compile-tex-source-and-launch-pdf-only-if-no-errors
" If your shell is bash, you can use the ${PIPESTATUS} array variable to get
" the correct exit code (borrowed from this answer to another question).
silent setlocal shell=bash
silent setlocal shellpipe=2>&1\ \|\ tee\ %s;exit\ \${PIPESTATUS[0]}
let success = 1
if filereadable("Makefile")
" If Makefile is available in current working directory, run 'make' with arguments
echon "compiling using Makefile ..."
let l:makecmd = "make\\ ".join(a:000, '\\ ')
silent execute "setlocal makeprg=" . l:makecmd
try
" This function is defined in the Vim-Latex package,
" and provides excellent parsing and filtering of the error messages
" when running latex outside of the Rubber wrapper.
call s:SetLatexEfm()
catch /E117/
set errorformat=%E!\ LaTeX\ %trror:\ %m,
\%E!\ %m,
\%+WLaTeX\ %.%#Warning:\ %.%#line\ %l%.%#,
\%+W%.%#\ at\ lines\ %l--%*\\d,
\%WLaTeX\ %.%#Warning:\ %m,
\%Cl.%l\ %m,
\%+C\ \ %m.,
\%+C%.%#-%.%#,
\%+C%.%#[]%.%#,
\%+C[]%.%#,
\%+C%.%#%[{}\\]%.%#,
\%+C<%.%#>%.%#,
\%C\ \ %m,
\%-GSee\ the\ LaTeX%m,
\%-GType\ \ H\ <return>%m,
\%-G\ ...%.%#,
\%-G%.%#\ (C)\ %.%#,
\%-G(see\ the\ transcript%.%#),
\%-G\\s%#,
\%+O(%f)%r,
\%+P(%f%r,
\%+P\ %\\=(%f%r,
\%+P%*[^()](%f%r,
\%+P[%\\d%[^()]%#(%f%r,
\%+Q)%r,
\%+Q%*[^()])%r,
\%+Q[%\\d%*[^()])%r
endtry
silent make
else
let l:special_tex_compiler = "rubber"
if executable(l:special_tex_compiler)
echon "compiling with Rubber ..."
silent execute "setlocal makeprg=" . l:special_tex_compiler . "\\ -dfs\\ %"
setlocal errorformat=%f:%l:\ %m
silent make %
else
echon "compiling ..."
let b:tex_flavor = 'pdflatex'
compiler tex
silent make %
endif
endif
" set/report compile status
if v:shell_error
let l:success = 0
" let l:wheight = winheight(bufnr("%")) / 2
" execute "copen ".l:wheight
copen
else
let l:success = 1
cclose
redraw
echon "successfully compiled"
endif
" view results if successful compile
if l:success && a:view_results
call ViewTexResults()
endif
" restore position
call setpos('.', save_cursor)
endfunction
function! ViewTexResults(...)
if a:0 == 0
let l:target = expand("%:p:r") . ".pdf"
else
let l:target = a:1
endif
if has('mac')
silent execute "! open -a Preview ".l:target
" obviously, you will need to write specific commands for other systems
" left as an exercise for the reader ...
endif
endfunction
command! -buffer -nargs=* BuildTex call BuildTex(0, <f-args>)
command! -buffer -nargs=* BuildAndViewTex call BuildTex(1, <f-args>)
noremap <buffer> <silent> <F9> <Esc>:call BuildTex(0)<CR>
noremap <buffer> <silent> <S-F9> <Esc>:call BuildTex(1)<CR>
Update: I have packaged and published this as a Vim file-type plugin script, available at: http://www.vim.org/scripts/script.php?script_id=3230.
Assuming you're falling into the else-theres-no-makefile section, the issue may be with the shellpipe variable.
On my system (Ubuntu), shellpipe=2>&1| tee and the built-in make call doesn't set v:shell_error if it fails.
The return status of | tee might be what v:shell_error is getting set to.
If your shell is bash, you can use the ${PIPESTATUS} array variable to get the correct exit code (borrowed from this answer to another question).
:set shellpipe=2>&1\ \|\ tee\ %s;exit\ \${PIPESTATUS[0]}
Otherwise, you can try:
:set shellpipe=\>
:make %
This sets v:shell_error when it fails but I'm not sure if that will mess with the go-to-error-line-number functionality, if there is any.
To see what the variable is set to:
:set shellpipe?
I know it's not related to vim, but I think that latexmk does the job.
It's a script (written in perl) which compile the latex file and update the pdf. The most useful future is the auto-update one. As soon as you save your file, 'latexmk' compile it, and if your pdf viewer supports it, the view is updated.
latexmk -pdf -pvc
If latexmk runs latex with the '-halt-on-error' option (or in nonstop mode), compilation will cease without pausing for input.

Resources