Can't add reg expression for a #define in ctags - ctags

I can't figure out how to make ctags detect the __mrs_s definition. It doesn't add the search pattern so I can't find it in vi.
$cat /tmp/qq.h
int test(int i)
{
printf("Hello!");
return 0;
}
#define __mrs_s(v, r) \
DEFINE_MRS_S \
" mrs_s " v ", " __stringify(r) "\n" \
UNDEFINE_MRS_S
$ctags --regex-C++='/^#define \([a-zA-Z_0-9]+\)([a-zA-Z,\ ]+)[\t ]+/\1/d/' -o - /tmp/qq.h
__mrs_s /tmp/qq.h 7;" d
test /tmp/qq.h /^int test(int i)$/;" f

Use --excmd=pattern option like:
[root#localhost ~]# cat /tmp/qq.h
int test(int i)
{
printf("Hello!");
return 0;
}
#define __mrs_s(v, r) \
DEFINE_MRS_S \
" mrs_s " v ", " __stringify(r) "\n" \
UNDEFINE_MRS_S
[root#localhost ~]# ctags --excmd=pattern -o - /tmp/qq.h
__mrs_s /tmp/qq.h /^#define __mrs_s(/;" d
test /tmp/qq.h /^int test(int i)$/;" f

Related

Boost Spirit failing on empty string input

I am trying to parse the following string and extract the parts inside the parenthesis.
This string fails:
_FIND('Something', '')_
Should return
part1 = 'Something'
part2 = ''
This string passes:
_FIND('Something', '*')_
Returns
part1 = 'Something'
part2 = '*'
I assume the problem lies with the "quoted_string"
find_parser() : find_parser::base_type(start)
{
using qi::lit;
using qi::lexeme;
using standard_wide::char_;
/// simple quoted string.
quoted_string %= lexeme['\'' >> +(char_ - '\'') >> '\''];
start %=
-(lit("$(")) // optional
>> lit("_FIND")
>> '('
>> quoted_string
>> -(',' >> quoted_string) // 2nd parameter optional
>> ")_"
>> -(lit(")")) // optional
;
}
I tried added an "empty" string lexeme like this, but it does not work.
quoted_string %= lexeme['\'' >> +(char_ - '\'') >> '\''];
empty_quoted_string %= lexeme['\'' >> +(qi::space - '\'') >> '\''];
start %=
lit("_FIND")
>> '('
>> (quoted_string|empty_quoted_string)
>> -(',' >> (quoted_string|empty_quoted_string)) // 2nd parameter optional
>> ")_"
;
I know it must be a simple thing, but I cannot put my finger on it.
Thanks for any inputs, hints or tips.
lexeme['\'' >> +(char_ - '\'') >> '\''];
+p means that p must match one-or-more times. If an empty string must be accepted, use the Kleene-star operator, which allows zero-or-more matches.
lexeme['\'' >> *(char_ - '\'') >> '\''];
Live Demo
Some inefficiencies/style issues resolves
Also, an incorrectness, where "$(_FIND('')" or "_FIND('')" would parse as "correct"
Live On Coliru
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/std_pair.hpp>
using Params = std::pair<std::string, std::string>;
namespace qi = boost::spirit::qi;
template <typename It>
struct find_parser : qi::grammar<It, Params()> {
find_parser() : find_parser::base_type(start)
{
using namespace qi;
start = skip(space) [ "$(" >> find >> ")" | find ];
find
= '_' >> lit("FIND") >> lit('(')
>> quoted_string >> -(',' >> quoted_string) // 2nd parameter optional
>> ')' >> '_'
;
quoted_string = "'" >> *~char_("'") >> "'";
BOOST_SPIRIT_DEBUG_NODES((start)(find)(quoted_string))
}
private:
qi::rule<It, Params()> start;
// rules with skipper
qi::rule<It, Params(), qi::space_type> find;
// implicit lexemes
qi::rule<It, std::string()> quoted_string;
};
int main() {
using It = std::string::const_iterator;
find_parser<It> const p;
for (std::string const input : {
"_FIND('Something', 'Something else')_",
"_ FIND('Something', 'Something else') _",
"$(_FIND('Something', 'Something else')_)",
"$( _FIND( 'Something', 'Something else' )_ )",
// second arg empty
"_FIND('Something', '')_",
"_ FIND('Something', '') _",
"$(_FIND('Something', '')_)",
"$( _FIND( 'Something', '' )_ )",
// optional args omitted
"_FIND('Something')_",
"_ FIND('Something') _",
"$(_FIND('Something')_)",
"$( _FIND( 'Something' )_ )",
})
{
std::cout << "-------- " << input << " ------------\n";
It f = input.begin(), l = input.end();
Params parsed;
if (parse(f, l, p, parsed))
std::cout << "Parsed: '" << parsed.first << "', '" << parsed.second << "'\n";
else
std::cout << "Parsing failed\n";
if (f!=l)
std::cout << " -- Remaining unparsed: '" << std::string(f,l) << "'\n";
}
}

OSX: dtrace printf(), write_nocancel() output base on dtruss script

I need to see my program's printf output in sync with the dtrace output.
I like to build my own version of dtrace command that produce the equivalent output of the "sudo dtruss -t write_nocancel ls" command.
This is the "correct dtruss command/output":
sudo dtruss -t write_nocancel ls
Chap1 Chap10 Chap11 Chap12 Chap2 Chap3 Chap4 Chap5 Chap6 Chap7 Chap8 Chap9 README
SYSCALL(args) = return
write_nocancel(0x1, "Chap1\tChap10\tChap11\tChap12\tChap2\tChap3\tChap4\tChap5\tChap6\tChap7\tChap8\tChap9\tREADME\n\0", 0x52) = 82 0
Base on looking at the dtruss script source code, I tried this dtrace command, but it failed.
sudo dtrace -q \
-n '*:*:write_nocancel:entry {self->arg0=arg0; self->arg1 =arg1; \
self->arg2 =arg2; self->code=0; } ' \
-n '*:*:write_nocancel:return { \
printf("return %s(0x%X, \"%S\", 0x%X) = %d %d", \
probefunc,self->arg0, arg0 == -1 ? "" : stringof(copyin(self->arg1,arg0)),self->arg2,(int)arg0, \
(int)errno); }' \
-c ls 2>&1
Chap1
Chap10
Chap11
Chap12
Chap2
Chap3
Chap4
Chap5
Chap6
Chap7
Chap8
Chap9
README
dtrace: error on enabled probe ID 3 (ID 209288: fbt:mach_kernel:write_nocancel:return): invalid address (0xffffff80218dfc40) in action #3 at DIF offset 92
dtrace: error on enabled probe ID 4 (ID 958: syscall::write_nocancel:return): invalid address (0xffffff80218dfc40) in action #3 at DIF offset 92
dtrace: error on enabled probe ID 3 (ID 209288: fbt:mach_kernel:write_nocancel:return): invalid address (0xffffff801a7c0010) in action #3 at DIF offset 92
Any dtrace experts out there might have a clue on how to fixe this?
Find the answer: (The issue of two -n options).
sudo dtrace -q -n \
'syscall::write_nocancel:entry{self->start = 1; \
self->vstart = 1; self->arg0 = arg0; \
self->arg1 = arg1; self->arg2 = arg2;} \
*:*:write_nocancel:return /self->start/ \
{ printf("return %s(0x%X, \"%S\", 0x%X) = %d %d" \
,probefunc,self->arg0, \
arg0 == -1 ? "" : stringof(copyin(self->arg1,arg0)),\
self->arg2,(int)arg0, (int)errno); }' \
-c ls 2>&1

issue with awk and variables from previous line

Code typically speaks better than thousand bytes. So did this demo code that does not obey my logic. Typically I trust compilers and programs, so I think I have a typo or something somewhere.
Please, could you point it out to me?
copy & paste code below into mydemo.sh file, and run it using command sh ./mydemo.sh
in my ref system this prints out:
mytux:~# ./mydemo.sh
This should spit out:
{USER1NAME} {Firstname Surname} {user1name}
{USER2NAME} {Secondname Surname} {user2name}
{USER3NAME} {Thirdname Surname} {user3name}
---- but it spits out:
{USER1NAME} {somestring: user1name}, {user1name}
{USER2NAME} {somestring: user2name}, {user2name}
{USER3NAME} {somestring: user3name}, {user3name}
----
Why so and how to fix it?
and here's the code:
#!/bin/sh
echo "# Firstname Surname, Company">usernames.txt
echo "somestring: user1name">>usernames.txt
echo "# Secondname Surname, Company">>usernames.txt
echo "somestring: user2name">>usernames.txt
echo "# Thirdname Surname, Company">>usernames.txt
echo "somestring: user3name">>usernames.txt
echo "This should spit out:"
echo "{USER1NAME} {Firstname Surname}, {user1name}"
echo "{USER2NAME} {Secondname Surname}, {user2name}"
echo "{USER3NAME} {Thirdname Surname}, {user3name}"
echo "---- but it spits out:"
echo "{USER1NAME} {somestring: user1name}, {user1name}"
echo "{USER2NAME} {somestring: user2name}, {user2name}"
echo "{USER3NAME} {somestring: user3name}, {user3name}"
echo "---- See:"
cat usernames.txt|awk \
'BEGIN { $mylink="";} \
{ \
if(match($0,"^#")!=0) \
{ \
split($0, a, ","); \
$mylink=$a[1]; \
} \
else \
{ \
if(length($mylink)>0) \
{ \
print "{" toupper($2) "} {" $mylink "}, {" $2 "}"; \
} \
$mylink=""; \
} \
}'
echo "----"
echo "Why so and how to fix it?"
Is this what you're trying to achieve? It would be easier to post the input text as is.
$ awk -F"[, ]" -v OFS="}, {" '
/^#/{n=$2" "$3;next}
{print "{" toupper($2), n, $2"}"}
' usernames.txt
{USER1NAME}, {Firstname Surname}, {user1name}
{USER2NAME}, {Secondname Surname}, {user2name}
{USER3NAME}, {Thirdname Surname}, {user3name}

How to use a gnu command in c#

I have a problem using a porting of the Gnu "find" in my c# app. Let me explain better:
in my winform application i have a button. When i press this button i need to launch this command (in cmd.exe this works well):
gfind training_set\positives\*.jpg -exec identify -format "%i 1 0 0 %w %h \n" {} ; > training_set\positives.dat
I used this:
string find = "gfind.exe ";
string command = textBox4.Text + "\\positives\\*.jpg -exec identify -format \" %i 1 0 0 %w %h \n\" {} /; > " + textBox4.Text + "\\positives.dat";
System.Diagnostics.Process.Start("CMD.exe", "/C "+find + command);
but the shell opens and tell me that i haven't passed any argument to the -exec
Any ideas?
EDIT:
this work:
string path = textBox4.Text + #"\positives\";
System.Diagnostics.Process.Start("CMD.exe", "/C cd " + textBox4.Text + " && gfind positives\*.png -exec identify -format ; > " + textBox4.Text + "\positives.dat");
BUT
-format requires this argument: '%i 1 0 0 %w %h \n' {}
in this way don't work...
EDIT2:
OK almost done..
System.Diagnostics.Process.Start("CMD.exe", "/C cd " + textBox4.Text + " && gfind positives\\*.png -exec identify -format \"%i 1 0 0 %w %h\" {} ; > " + textBox4.Text + "\\positives.dat");
Ok this work, but print every entry in the same row:
positives\3LiIIH8.png 1 0 0 28 20positives\5NoLpfy.png 1 0 0 28 20positives\7XNpLX0.png 1 0 0 28 20
I need one entry per row like:
positives\3LiIIH8.png 1 0 0 28 20
positives\5NoLpfy.png 1 0 0 28 20
positives\7XNpLX0.png 1 0 0 28 20
\n break the sintax
Solved... quotes and escapes characters make me crazy
System.Diagnostics.Process.Start("CMD.exe", "/C cd " + textBox4.Text + " && gfind positives\\*.png -exec identify -format \"%i 1 0 0 %w %h\\n\" {} ; > " + textBox4.Text + "\\positives.dat");

Os Exec Sudo Command in Go

In the process of familiarizing myself with Go and goroutines I have hit a road block with executing commands. The format of these commands are:
sudo find /folder -type f | while read i; do sudo -S chmod 644 "$i"; done
With code taken from How to execute system command in Golang with unknown arguments I'm trying to execute this command but I believe it's not executing due to the first argument being sudo, I could be wrong. I have just two questions.
When these commands fail to run I am returned "exit status 1", is there a way to get a more detailed error than what I am doing? Question two, why would I be getting "exit status 1" with this script? What is going on that isn't supposed to?
package main
import (
"bufio"
"fmt"
"os"
"os/exec"
"strings"
"sync"
)
func ExeCmd(cmd string, wg *sync.WaitGroup) {
parts := strings.Fields(cmd)
head := parts[0]
// Head at this point is "sudo"
parts = parts[1:len(parts)]
out, err := exec.Command(head,parts...).Output()
if err != nil {
fmt.Printf("%s\n", err)
}
fmt.Printf("%s\n", out)
wg.Done() // Signal to WaitGroup goroutine finished
}
func InArray(a []string, e string) bool {
for _, x := range a {
if x == e {
return true
fmt.Print("True")
}
}
return false
}
func main() {
exec.Command("sudo ls > /dev/null") // Get sudo password just once, doesn't seem to work with Go
wg := new(sync.WaitGroup)
reader := bufio.NewReader(os.Stdin)
fdbslices := []string{"f", "d", "b", "files", "directories", "both"}
commands := []string{}
fdb := ""
filep := ""
dirp := ""
// Grab Path
fmt.Print("Path: ")
findpath, _ := reader.ReadString('\n')
findpath = strings.ToLower(strings.Trim(findpath, "\n"))
// Grab Files, Directories, or Both
for {
fmt.Print("Files, Directories, or Both: ")
fdb, _ = reader.ReadString('\n')
fdb = strings.ToLower(strings.Trim(fdb, "\n"))
if InArray(fdbslices, fdb) == true { break }
}
// Build commands string, these come out as they should
for {
if fdb == "f" || fdb == "files" {
fmt.Print("Permissions for Files: ")
filep, _ = reader.ReadString('\n')
filep = strings.Trim(filep, "\n")
commands = append(commands, "sudo find " + findpath + " -type f | while read i; do sudo -S chmod " + filep + " \"$i\"; done")
}
if fdb == "d" || fdb == "directories" {
fmt.Print("Permissions for Directories: ")
dirp, _ = reader.ReadString('\n')
dirp = strings.Trim(dirp, "\n")
commands = append(commands, "sudo find " + findpath + " -type d | while read i; do sudo -S chmod " + dirp + " \"$i\"; done")
}
if fdb == "b" || fdb == "both" {
fmt.Print("Permissions for Files: ")
filep, _ = reader.ReadString('\n')
filep = strings.Trim(filep, "\n")
commands = append(commands, "sudo find " + findpath + " -type f | while read i; do sudo -S chmod " + filep + " \"$i\"; done")
fmt.Print("Permissions for Directories: ")
dirp, _ = reader.ReadString('\n')
dirp = strings.Trim(dirp, "\n")
commands = append(commands, "sudo find " + findpath + " -type d | while read i; do sudo -S chmod " + dirp + " \"$i\"; done")
}
break
}
// Execute Commands
for _, str := range commands {
wg.Add(1)
fmt.Print("Doing: " + str + "\r\n")
go ExeCmd(str, wg)
}
wg.Wait()
}
Example Terminal output:
Path: test
Files, Directories, or Both: b
Permissions for Files: 644
Permissions for Directories: 755
Doing: find test -type f | while read i; do sudo -S chmod 644 "$i"; done
Doing: find test -type d | while read i; do sudo -S chmod 755 "$i"; done
exit status 1
exit status 1
Thank you for your time.
exec.Command() will ask the kernel to execute the given process directly. However, the command you are passing is a string of multiple programs hooked together by a shell script.
If you want to execute a shell script, you should use something like this:
cmd := exec.Command("/bin/sh", "-c", "sudo find ...")

Resources