cocci.inria.fr archive mirror
 help / color / mirror / Atom feed
* [Cocci] Blank space in front of function definition name confuses spatch
@ 2019-01-22 22:30 Timur Tabi
  2019-01-23  6:19 ` Julia Lawall
  2019-01-24 20:19 ` Julia Lawall
  0 siblings, 2 replies; 4+ messages in thread
From: Timur Tabi @ 2019-01-22 22:30 UTC (permalink / raw)
  To: cocci

[-- Attachment #1: Type: text/plain, Size: 653 bytes --]

If I have a blank space in front of the return parameter and function
name, spatch gets confused and rejects the file.  I've attached a
test.c and my nv_printf.cocci.  If I remove the blank space before
"NV_STATUS" and "mycrazyfunc", everything works.  But with the blank
space, it causes this error:

ERROR-RECOV: found sync '}' at line 14
parsing pass2: try again
ERROR-RECOV: found sync '}' at line 14
parsing pass3: try again
ERROR-RECOV: found sync '}' at line 14
parse error
 = File "/home/ttabi/test.c", line 1, column 1, charpos = 1
  around = 'NV_STATUS',
  whole content =  NV_STATUS
badcount: 13
BAD:!!!!!  NV_STATUS
bad:  mycrazyfunc
bad: (

[-- Attachment #2: nv_printf.cocci --]
[-- Type: application/octet-stream, Size: 8527 bytes --]

/*
 * Coccinelle file to replace DBG_PRINTF() calls with NV_PRINTF() 
 *
 * To work around an odd behavior of Coccinelle, we temporarily change
 * the DBG_PRINTx statements into NV_PRINT2, and do all our work on that
 * macro name.  Only at the very end do we change NV_PRINT2 to NV_PRINTF.
 * We do this so that Coccinelle won't touch existing NV_PRINTF statements.
 *
 * Python rules come in three parts:
 *  1. A rule to determine if the Python code should be run
 *  2. The Python code itself, inside a rule
 *  3. A final rule that applies the output of the Python script
 */

// Remove the double-parentheses in DBG_PRINTF statements
@rule0@
@@
DBG_PRINTF(
-(
...
-)
 );

// Replace DBG_PRINTF with NV_PRINTF2
@rule1 depends on rule0@
expression x;
expression list y;
@@
-DBG_PRINTF(x, y);
+NV_PRINTF2(y);

// Replace DBG_PRINT_STRING with NV_PRINTF2
@rule2@
expression list x;
@@
-DBG_PRINT_STRING(x);
+NV_PRINTF2(x);

// Replace DBG_PRINT_STRING_VALUE with NV_PRINTF2
@rule3@
expression x;
expression list y;
@@
-DBG_PRINT_STRING_VALUE(x, y);
+NV_PRINTF2(x, "%s 0x%x\n", y);

// Replace DBG_PRINT_STRING_PTR with NV_PRINTF2
@rule4@
expression x;
expression list y;
@@
-DBG_PRINT_STRING_PTR(x, y);
+NV_PRINTF2(x, "%s %p\n", y);

// Replace DBG_PRINT_STRING_VAL64 with NV_PRINTF2
@rule5@
expression x;
expression list y;
@@
-DBG_PRINT_STRING_VAL64(x, y);
+NV_PRINTF2(x, "%s 0x%llx\n", y);

// Collect all the previous rules as a dependecy, so that the rules below
// can depend only on "rules" instead of "rule1 || rule2 || ..."
@rules depends on rule1 || rule2 || rule3 || rule4 || rule5@
@@
NV_PRINTF2

// Replace the DBG_xxx or DEBUGLEVEL_xxx with LEVEL_xxx
@depends on rules@
@@
NV_PRINTF2(...,
-DBG_LEVEL_REGTRACE
+LEVEL_SILENT
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-\(DBG_LEVEL_INFO \| DEBUGLEVEL_TRACEINFO \| DBG_LEVEL_SETUPINFO \| DEBUGLEVEL_SETUPINFO\)
+LEVEL_INFO
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-\(DBG_LEVEL_USERERRORS \| DEBUGLEVEL_USERERRORS \| DBG_LEVEL_NOTICE\)
+LEVEL_NOTICE
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-\(DBG_LEVEL_WARNINGS \| DEBUGLEVEL_WARNINGS\)
+LEVEL_WARNING
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-\(DBG_LEVEL_ERRORS \| DEBUGLEVEL_ERRORS\)
+LEVEL_ERROR
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-DBG_LEVEL_HW_ERROR
+LEVEL_HW_ERROR
, ...);

@depends on rules@
@@
NV_PRINTF2(...,
-DBG_LEVEL_FATAL
+LEVEL_FATAL
, ...);

// -------------------------------

// Use Python to clean up the string literals.
// Comments are still C-style though
@r depends on rules@
expression x;
constant char[] c;
position p1;
@@
NV_PRINTF2(x, c@p1, ...)

@script:python s@
c << r.c;
c2;
p1 << r.p1;
@@
import re
import sys

// Convert a malformed multi-line string literal into one line
// Coccinelle sometimes takes care of this for us, but sometimes it doesn't
c = re.sub(r'\\\n[ ]*', '', c, re.DOTALL)

// Combine "xxx" "yyy" into "xxxyyy"
while True:
    m = re.match(r'(.*)"([^"]+)" "(.*)', c)
    if not m:
        break
    c = '%s"%s%s' % (m.group(1), m.group(2), m.group(3))

    // Warn if there's no delimeter between two merged strings.  This is
    // usually a sign that someone forgot to put a blank space between
    // two words.
    if m.group(2)[-2:] != r'\n' and m.group(2)[-1].isalpha() and m.group(3)[0].isalpha():
        print >>sys.stderr, 'Warning: string in function %s may have concatenated two words: "%s" and "%s"' % (p1[0].current_element, m.group(2).split()[-1], m.group(3).split()[0])

// Remove blank spaces before \n
// I don't know why we need four backslashes, but we do
c = re.sub(r'\s+\\n', '\\\\n', c)

// Remove the "NXXX: " prefix
c = re.sub(r'"N[A-Z]+(: |:| )', '"', c, 1)

// If the string ends with \n " then remove the spaces between \n and "
// Chances are, it's typo instead of an indentation for the next line
c = re.sub(r'\\n\s+"$', '\\\\n"', c, 1)

if len(c) > 3 and c.startswith(r'"\n'):
    print >>sys.stderr, 'Warning: string in function %s begins with a newline' % p1[0].current_element
    print >>sys.stderr, c

if c.endswith('"') and not c.endswith(r'\n"'):
    print >>sys.stderr, 'Warning: missing \\n in function %s' % p1[0].current_element
    print >>sys.stderr, c

// Finally, return the string
coccinelle.c2 = c

@depends on rules@
expression x;
constant char[] r.c;
identifier s.c2;
position r.p1;
@@
NV_PRINTF2(x,
-c@p1
+c2
,...)

// -------------------------------

// Replace __func__ with __FUNCTION__

@rx depends on rules@
symbol __func__;
@@
NV_PRINTF2(...
-,__func__
+,__FUNCTION__
,...)

// -------------------------------

// Look for NV_PRINTF2 calls that have __FUNCTION__ as the first parameter
@r2 depends on rules@
constant char[] c;
expression x;
symbol __func__;
@@
NV_PRINTF2(x, c, __FUNCTION__, ...)

// Get rid of __FUNCTION__ at the beginning of the string
@script:python s2@
c << r2.c;
c2;
@@
import re
coccinelle.c2 = re.sub('%s[:\(\)]*[ ]?', '', c, 1)

@depends on rules@
expression x;
constant char[] r2.c;
identifier s2.c2;
@@
NV_PRINTF2(x,
-c, __FUNCTION__
+c2
,...);

// -------------------------------

// Look for NV_PRINTF2 calls that have __FUNCTION__ as the last parameter
@r3 depends on rules@
constant char[] c;
expression x;
symbol __func__;
@@
NV_PRINTF2(x, c, ..., __FUNCTION__)

// Get rid of __FUNCTION__ at the end of the string
@script:python s3@
c << r3.c;
c2;
@@
import re
// Find the last [: ]*%s, and remove it
pos = [i.span() for i in re.finditer('[: ]*%s', c)][-1]
c = c[:pos[0]] + c[pos[1]:]

// Also remove the word "in" if it's the last word in the string,
// because that's supposed to be "in <function>", which no longer
// makes sense.
coccinelle.c2 = re.sub(' in \\\\n"$', '\n"', c)

@depends on rules@
expression x;
constant char[] r3.c;
identifier s3.c2;
@@
NV_PRINTF2(x,
-c
+c2
,...
-,__FUNCTION__
 );

// -------------------------------

// Look for NV_PRINTF2 calls that have the function name in the string
@r4 depends on rules@
expression x;
constant char[] c;
position p1;
@@
NV_PRINTF2(x@p1, c, ...)

// Get rid of the function name at the beginning of the string
@script:python s4@
c << r4.c;
c2;
p1 << r4.p1;
@@
import re

f = p1[0].current_element
coccinelle.c2 = re.sub('"%s[:\(\)]*[ ]?' % f, '"', c, 1)

@depends on rules@
expression x;
constant char[] r4.c;
identifier s4.c2;
position r4.p1;
@@
NV_PRINTF2(x@p1,
-c
+c2
,...);

// -------------------------------

// Rewrap the string literal if it's too long
@r5 depends on rules@
expression x;
constant char[] c;
position p1;
@@
NV_PRINTF2(x, c@p1, ...)

@script:python s5@
c << r5.c;
c2;
p1 << r5.p1;
@@
import re
import textwrap
import shlex
import sys

c2 = ''
nl = r'\n'

// Break up the parameter into individual string literals and iterate over them
// See https://stackoverflow.com/questions/53857669
//strings = re.match(r"\s*((?:\\[\S\s]|[^\"\\])+|\"[^\"\\]*(?:\\[\S\s][^\"\\]*)*\")\s*" , c)

for string in re.findall(r'"[^"\\]*(?:\\.[^"\\]*)*"|\S+', c):
    // Break up long strings literals.  Coccinelle will place them on separate lines.
    line = string.strip()
    if not line.startswith('"'):
        c2 += line + ' '
        continue

    line = line[1:-1]
    lines = [s+nl for s in line.split(nl)]

    if line[-2:] == nl:
        // split() adds an extra blank string if the input string ends in a \n
        del lines[-1]
    else:
        lines[-1] = lines[-1][:-2]

    // Merge a stand-alone \n with the adjacent string
    while lines[0] == nl and len(lines) > 1:
        lines[1] = nl + lines[1]
        del lines[0]

    i = 1
    while i < len(lines):
        if lines[i] == nl:
            lines[i-1] += nl
            del lines[i]
        else:
            i += 1

    // All strings are now perfect, so wrap each one.
    for l in lines:
        if len(l) > 80:
            for l2 in textwrap.wrap(l, width = 70, expand_tabs = False,
                               replace_whitespace = False, drop_whitespace = False,
                               break_long_words = False, break_on_hyphens = False):
                c2 += '"%s" ' % l2
        else:
            c2 += '"%s" ' % l

coccinelle.c2 = c2

@depends on rules@
expression x;
constant char[] r5.c;
identifier s5.c2;
position r5.p1;
@@
NV_PRINTF2(x,
-c@p1
+c2
,...)

// Remove any unnecessary braces
//@depends on rules@
//expression list x;
//@@
//-{
//NV_PRINTF2(x);
//-}

// Finally, change NV_PRINT2 to NV_PRINTF.  This has the side-effect of
// also compressing all the parameters into as few lines as possible.
@depends on rules@
expression list x;
@@
-NV_PRINTF2(x)
+NV_PRINTF(x)

[-- Attachment #3: test.c --]
[-- Type: text/x-csrc, Size: 325 bytes --]

 NV_STATUS
 mycrazyfunc
(
    POBJGPU pLocalGpu,
    POBJBUS pLocalBus
)
{
        DBG_PRINTF((DBG_MODULE_OS, DBG_LEVEL_ERRORS,
                    "NVRM: %s: this is a test \
                    of multiline " NvP64_fmt " strings %p\n ",
                    __FUNCTION__,
                    p1,
                    p2));
}

[-- Attachment #4: Type: text/plain, Size: 136 bytes --]

_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Cocci] Blank space in front of function definition name confuses spatch
  2019-01-22 22:30 [Cocci] Blank space in front of function definition name confuses spatch Timur Tabi
@ 2019-01-23  6:19 ` Julia Lawall
  2019-01-24 20:19 ` Julia Lawall
  1 sibling, 0 replies; 4+ messages in thread
From: Julia Lawall @ 2019-01-23  6:19 UTC (permalink / raw)
  To: Timur Tabi; +Cc: cocci



On Tue, 22 Jan 2019, Timur Tabi wrote:

> If I have a blank space in front of the return parameter and function
> name, spatch gets confused and rejects the file.  I've attached a
> test.c and my nv_printf.cocci.  If I remove the blank space before
> "NV_STATUS" and "mycrazyfunc", everything works.  But with the blank
> space, it causes this error:

The problem only comes when te return type is a typedef.  I will see if it
is possible to fix it.

julia

>
> ERROR-RECOV: found sync '}' at line 14
> parsing pass2: try again
> ERROR-RECOV: found sync '}' at line 14
> parsing pass3: try again
> ERROR-RECOV: found sync '}' at line 14
> parse error
>  = File "/home/ttabi/test.c", line 1, column 1, charpos = 1
>   around = 'NV_STATUS',
>   whole content =  NV_STATUS
> badcount: 13
> BAD:!!!!!  NV_STATUS
> bad:  mycrazyfunc
> bad: (
>
_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Cocci] Blank space in front of function definition name confuses spatch
  2019-01-22 22:30 [Cocci] Blank space in front of function definition name confuses spatch Timur Tabi
  2019-01-23  6:19 ` Julia Lawall
@ 2019-01-24 20:19 ` Julia Lawall
  2019-01-28 21:50   ` Timur Tabi
  1 sibling, 1 reply; 4+ messages in thread
From: Julia Lawall @ 2019-01-24 20:19 UTC (permalink / raw)
  To: Timur Tabi; +Cc: cocci



On Tue, 22 Jan 2019, Timur Tabi wrote:

> If I have a blank space in front of the return parameter and function
> name, spatch gets confused and rejects the file.  I've attached a
> test.c and my nv_printf.cocci.  If I remove the blank space before
> "NV_STATUS" and "mycrazyfunc", everything works.  But with the blank
> space, it causes this error:
>
> ERROR-RECOV: found sync '}' at line 14
> parsing pass2: try again
> ERROR-RECOV: found sync '}' at line 14
> parsing pass3: try again
> ERROR-RECOV: found sync '}' at line 14
> parse error
>  = File "/home/ttabi/test.c", line 1, column 1, charpos = 1
>   around = 'NV_STATUS',
>   whole content =  NV_STATUS
> badcount: 13
> BAD:!!!!!  NV_STATUS
> bad:  mycrazyfunc
> bad: (

This should be fixed in the version on github.  Please try again.

julia
_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [Cocci] Blank space in front of function definition name confuses spatch
  2019-01-24 20:19 ` Julia Lawall
@ 2019-01-28 21:50   ` Timur Tabi
  0 siblings, 0 replies; 4+ messages in thread
From: Timur Tabi @ 2019-01-28 21:50 UTC (permalink / raw)
  To: Julia Lawall; +Cc: cocci

On Thu, Jan 24, 2019 at 2:20 PM Julia Lawall <julia.lawall@lip6.fr> wrote:
>
> This should be fixed in the version on github.  Please try again.

Yes, it works, thanks.
_______________________________________________
Cocci mailing list
Cocci@systeme.lip6.fr
https://systeme.lip6.fr/mailman/listinfo/cocci

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2019-01-28 21:52 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-01-22 22:30 [Cocci] Blank space in front of function definition name confuses spatch Timur Tabi
2019-01-23  6:19 ` Julia Lawall
2019-01-24 20:19 ` Julia Lawall
2019-01-28 21:50   ` Timur Tabi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).