Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
ccan
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
mirror
ccan
Commits
c8acddea
Commit
c8acddea
authored
Jun 02, 2008
by
Rusty Russell
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First primitive cut of ccanlint
parent
89afb563
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
862 additions
and
0 deletions
+862
-0
ccan_tools/ccanlint/Makefile
ccan_tools/ccanlint/Makefile
+31
-0
ccan_tools/ccanlint/ccanlint.c
ccan_tools/ccanlint/ccanlint.c
+165
-0
ccan_tools/ccanlint/ccanlint.h
ccan_tools/ccanlint/ccanlint.h
+76
-0
ccan_tools/ccanlint/file_analysis.c
ccan_tools/ccanlint/file_analysis.c
+149
-0
ccan_tools/ccanlint/get_file_lines.c
ccan_tools/ccanlint/get_file_lines.c
+85
-0
ccan_tools/ccanlint/get_file_lines.h
ccan_tools/ccanlint/get_file_lines.h
+6
-0
ccan_tools/ccanlint/has_main_header.c
ccan_tools/ccanlint/has_main_header.c
+41
-0
ccan_tools/ccanlint/has_tests.c
ccan_tools/ccanlint/has_tests.c
+118
-0
ccan_tools/ccanlint/idempotent.c
ccan_tools/ccanlint/idempotent.c
+71
-0
ccan_tools/ccanlint/no_info.c
ccan_tools/ccanlint/no_info.c
+78
-0
ccan_tools/ccanlint/trailing_whitespace.c
ccan_tools/ccanlint/trailing_whitespace.c
+42
-0
No files found.
ccan_tools/ccanlint/Makefile
0 → 100644
View file @
c8acddea
OBJS
:=
ccan_tools/ccanlint/no_info.o
\
ccan_tools/ccanlint/has_main_header.o
\
ccan_tools/ccanlint/has_tests.o
\
ccan_tools/ccanlint/trailing_whitespace.o
\
ccan_tools/ccanlint/idempotent.o
\
FUTURE
:=
ccan_tools/ccanlint/if_have_not_ifdef.o
\
ccan_tools/ccanlint/needs_depends.o
\
ccan_tools/ccanlint/has_info_documentation.o
\
ccan_tools/ccanlint/has_header_documentation.o
\
ccan_tools/ccanlint/has_tests.o
\
ccan_tools/ccanlint/builds_ok.o
\
ccan_tools/ccanlint/builds_ok_all_have_variants.o
\
ccan_tools/ccanlint/run_tests.o
\
ccan_tools/ccanlint/test_coverage.o
\
ccan_tools/ccanlint/generated-init-tests
:
$(OBJS)
cat
$(OBJS:.o=.c)
|
sed
-n
's/^struct ccanlint \([A-Za-z0-9_]*\) = {/{ extern struct ccanlint \1; list_add(\&tests, \&\1.list); }/p'
>
$@
ccan_tools/ccanlint/ccanlint.o
:
ccan_tools/ccanlint/generated-init-tests
ccan_tools/ccanlint/ccanlint
:
\
$(OBJS)
\
ccan_tools/ccanlint/ccanlint.o
\
ccan_tools/ccanlint/get_file_lines.o
\
ccan_tools/ccanlint/file_analysis.o
\
talloc/talloc.o noerr/noerr.o
ccanlint-clean
:
$(RM)
ccan_tools/ccanlint/generated-init-tests
ccan_tools/ccanlint/ccanlint.c
0 → 100644
View file @
c8acddea
/*
* ccanlint: assorted checks and advice for a ccan package
* Copyright (C) 2008 Rusty Russell
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "ccanlint.h"
#include <unistd.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <ctype.h>
static
unsigned
int
verbose
=
0
;
static
LIST_HEAD
(
tests
);
static
void
init_tests
(
void
)
{
#include "generated-init-tests"
}
static
void
usage
(
const
char
*
name
)
{
fprintf
(
stderr
,
"Usage: %s [-s] [-v] [-d <dirname>]
\n
"
" -v: verbose mode
\n
"
" -s: simply give one line per FAIL and total score
\n
"
" -d: use this directory instead of the current one
\n
"
,
name
);
exit
(
1
);
}
static
void
indent_print
(
const
char
*
string
)
{
while
(
*
string
)
{
unsigned
int
line
=
strcspn
(
string
,
"
\n
"
);
printf
(
"
\t
%.*s"
,
line
,
string
);
if
(
string
[
line
]
==
'\n'
)
{
printf
(
"
\n
"
);
line
++
;
}
string
+=
line
;
}
}
bool
ask
(
const
char
*
question
)
{
char
reply
[
2
];
printf
(
"%s "
,
question
);
fflush
(
stdout
);
return
fgets
(
reply
,
sizeof
(
reply
),
stdin
)
!=
NULL
&&
toupper
(
reply
[
0
])
==
'Y'
;
}
static
bool
run_test
(
const
struct
ccanlint
*
i
,
bool
summary
,
unsigned
int
*
score
,
unsigned
int
*
total_score
,
struct
manifest
*
m
)
{
void
*
result
;
unsigned
int
this_score
;
if
(
i
->
total_score
)
*
total_score
+=
i
->
total_score
;
result
=
i
->
check
(
m
);
if
(
!
result
)
{
if
(
verbose
)
printf
(
" %s: OK
\n
"
,
i
->
name
);
if
(
i
->
total_score
)
*
score
+=
i
->
total_score
;
return
true
;
}
if
(
i
->
score
)
this_score
=
i
->
score
(
m
,
result
);
else
this_score
=
0
;
*
score
+=
this_score
;
if
(
summary
)
{
printf
(
"%s FAILED (%u/%u)
\n
"
,
i
->
name
,
this_score
,
i
->
total_score
);
if
(
verbose
)
indent_print
(
i
->
describe
(
m
,
result
));
return
false
;
}
printf
(
"%s
\n
"
,
i
->
describe
(
m
,
result
));
if
(
i
->
handle
)
i
->
handle
(
m
,
result
);
return
false
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
int
c
;
bool
summary
=
false
;
unsigned
int
score
,
total_score
;
struct
manifest
*
m
;
const
struct
ccanlint
*
i
;
/* I'd love to use long options, but that's not standard. */
/* FIXME: getopt_long ccan package? */
while
((
c
=
getopt
(
argc
,
argv
,
"sd:v"
))
!=
-
1
)
{
switch
(
c
)
{
case
'd'
:
if
(
chdir
(
optarg
)
!=
0
)
err
(
1
,
"Changing into directory '%s'"
,
optarg
);
break
;
case
's'
:
summary
=
true
;
break
;
case
'v'
:
verbose
++
;
break
;
default:
usage
(
argv
[
0
]);
}
}
if
(
optind
<
argc
)
usage
(
argv
[
0
]);
m
=
get_manifest
();
init_tests
();
/* If you don't pass the compulsory tests, you don't even get a score */
if
(
verbose
)
printf
(
"Compulsory tests:
\n
"
);
list_for_each
(
&
tests
,
i
,
list
)
if
(
!
i
->
total_score
&&
!
run_test
(
i
,
summary
,
NULL
,
NULL
,
m
))
exit
(
1
);
if
(
verbose
)
printf
(
"
\n
Normal tests:
\n
"
);
score
=
total_score
=
0
;
list_for_each
(
&
tests
,
i
,
list
)
if
(
i
->
total_score
)
run_test
(
i
,
summary
,
&
score
,
&
total_score
,
m
);
printf
(
"Total score: %u/%u
\n
"
,
score
,
total_score
);
return
0
;
}
ccan_tools/ccanlint/ccanlint.h
0 → 100644
View file @
c8acddea
#ifndef CCAN_LINT_H
#define CCAN_LINT_H
#include <list/list.h>
#include <stdbool.h>
struct
manifest
{
char
*
basename
;
struct
ccan_file
*
info_file
;
struct
list_head
c_files
;
struct
list_head
h_files
;
struct
list_head
run_tests
;
struct
list_head
compile_ok_tests
;
struct
list_head
compile_fail_tests
;
struct
list_head
other_test_files
;
struct
list_head
other_files
;
};
struct
manifest
*
get_manifest
(
void
);
struct
ccanlint
{
struct
list_node
list
;
/* Unique name of test */
const
char
*
name
;
/* Total score that this test is worth. 0 means compulsory tests. */
unsigned
int
total_score
;
/* If this returns non-NULL, it means the check failed. */
void
*
(
*
check
)(
struct
manifest
*
m
);
/* The non-NULL return from check is passed to one of these: */
/* So, what did this get out of the total_score? (NULL means 0). */
unsigned
int
(
*
score
)(
struct
manifest
*
m
,
void
*
check_result
);
/* Verbose description of what was wrong. */
const
char
*
(
*
describe
)(
struct
manifest
*
m
,
void
*
check_result
);
/* Can we do something about it? (NULL if not) */
void
(
*
handle
)(
struct
manifest
*
m
,
void
*
check_result
);
};
/* Ask the user a yes/no question: the answer is NO if there's an error. */
bool
ask
(
const
char
*
question
);
struct
ccan_file
{
struct
list_node
list
;
char
*
name
;
unsigned
int
num_lines
;
char
**
lines
;
};
/* Use this rather than accessing f->lines directly: loads on demand. */
char
**
get_ccan_file_lines
(
struct
ccan_file
*
f
);
/* Call the reporting on every line in the file. sofar contains
* previous results. */
char
*
report_on_lines
(
struct
list_head
*
files
,
char
*
(
*
report
)(
const
char
*
),
char
*
sofar
);
/* The critical tests which mean fail if they don't pass. */
extern
struct
ccanlint
no_info
;
extern
struct
ccanlint
has_main_header
;
/* Normal tests. */
extern
struct
ccanlint
trailing_whitespace
;
#endif
/* CCAN_LINT_H */
ccan_tools/ccanlint/file_analysis.c
0 → 100644
View file @
c8acddea
#include "ccanlint.h"
#include "get_file_lines.h"
#include <talloc/talloc.h>
#include <string/string.h>
#include <noerr/noerr.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <err.h>
#include <errno.h>
#include <dirent.h>
char
**
get_ccan_file_lines
(
struct
ccan_file
*
f
)
{
if
(
!
f
->
lines
)
f
->
lines
=
get_file_lines
(
f
,
f
->
name
,
&
f
->
num_lines
);
return
f
->
lines
;
}
static
void
add_files
(
struct
manifest
*
m
,
const
char
*
dir
)
{
DIR
*
d
;
struct
dirent
*
ent
;
if
(
dir
[
0
])
d
=
opendir
(
dir
);
else
d
=
opendir
(
"."
);
if
(
!
d
)
err
(
1
,
"Opening directory %s"
,
dir
[
0
]
?
dir
:
"."
);
while
((
ent
=
readdir
(
d
))
!=
NULL
)
{
struct
stat
st
;
struct
ccan_file
*
f
;
struct
list_head
*
dest
;
bool
is_c_src
;
if
(
ent
->
d_name
[
0
]
==
'.'
)
continue
;
f
=
talloc
(
m
,
struct
ccan_file
);
f
->
lines
=
NULL
;
f
->
name
=
talloc_asprintf
(
f
,
"%s%s"
,
dir
,
ent
->
d_name
);
if
(
lstat
(
f
->
name
,
&
st
)
!=
0
)
err
(
1
,
"lstat %s"
,
f
->
name
);
if
(
S_ISDIR
(
st
.
st_mode
))
{
f
->
name
=
talloc_append_string
(
f
->
name
,
"/"
);
add_files
(
m
,
f
->
name
);
continue
;
}
if
(
!
S_ISREG
(
st
.
st_mode
))
{
talloc_free
(
f
);
continue
;
}
if
(
streq
(
f
->
name
,
"_info.c"
))
{
m
->
info_file
=
f
;
continue
;
}
is_c_src
=
strends
(
f
->
name
,
".c"
);
if
(
!
is_c_src
&&
!
strends
(
f
->
name
,
".h"
))
dest
=
&
m
->
other_files
;
else
if
(
!
strchr
(
f
->
name
,
'/'
))
{
if
(
is_c_src
)
dest
=
&
m
->
c_files
;
else
dest
=
&
m
->
h_files
;
}
else
if
(
strstarts
(
f
->
name
,
"test/"
))
{
if
(
is_c_src
)
{
if
(
strstarts
(
f
->
name
,
"test/run"
))
dest
=
&
m
->
run_tests
;
else
if
(
strstarts
(
f
->
name
,
"test/compile_ok"
))
dest
=
&
m
->
compile_ok_tests
;
else
if
(
strstarts
(
f
->
name
,
"test/compile_fail"
))
dest
=
&
m
->
compile_fail_tests
;
else
dest
=
&
m
->
other_test_files
;
}
else
dest
=
&
m
->
other_test_files
;
}
else
dest
=
&
m
->
other_files
;
list_add
(
dest
,
&
f
->
list
);
}
closedir
(
d
);
}
char
*
report_on_lines
(
struct
list_head
*
files
,
char
*
(
*
report
)(
const
char
*
),
char
*
sofar
)
{
struct
ccan_file
*
f
;
list_for_each
(
files
,
f
,
list
)
{
unsigned
int
i
;
char
**
lines
=
get_ccan_file_lines
(
f
);
for
(
i
=
0
;
i
<
f
->
num_lines
;
i
++
)
{
char
*
r
=
report
(
lines
[
i
]);
if
(
!
r
)
continue
;
sofar
=
talloc_asprintf_append
(
sofar
,
"%s:%u:%s
\n
"
,
f
->
name
,
i
+
1
,
r
);
talloc_free
(
r
);
}
}
return
sofar
;
}
struct
manifest
*
get_manifest
(
void
)
{
struct
manifest
*
m
=
talloc
(
NULL
,
struct
manifest
);
unsigned
int
len
;
m
->
info_file
=
NULL
;
list_head_init
(
&
m
->
c_files
);
list_head_init
(
&
m
->
h_files
);
list_head_init
(
&
m
->
run_tests
);
list_head_init
(
&
m
->
compile_ok_tests
);
list_head_init
(
&
m
->
compile_fail_tests
);
list_head_init
(
&
m
->
other_test_files
);
list_head_init
(
&
m
->
other_files
);
/* *This* is why people hate C. */
len
=
32
;
m
->
basename
=
talloc_array
(
m
,
char
,
len
);
while
(
!
getcwd
(
m
->
basename
,
len
))
{
if
(
errno
!=
ERANGE
)
err
(
1
,
"Getting current directory"
);
m
->
basename
=
talloc_realloc
(
m
,
m
->
basename
,
char
,
len
*=
2
);
}
len
=
strlen
(
m
->
basename
);
while
(
len
&&
m
->
basename
[
len
-
1
]
==
'/'
)
m
->
basename
[
--
len
]
=
'\0'
;
m
->
basename
=
strrchr
(
m
->
basename
,
'/'
);
if
(
!
m
->
basename
)
errx
(
1
,
"I don't expect to be run from the root directory"
);
m
->
basename
++
;
add_files
(
m
,
""
);
return
m
;
}
ccan_tools/ccanlint/get_file_lines.c
0 → 100644
View file @
c8acddea
#include "get_file_lines.h"
#include <talloc/talloc.h>
#include <string/string.h>
#include <noerr/noerr.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <err.h>
#include <dirent.h>
static
void
*
grab_fd
(
const
void
*
ctx
,
int
fd
)
{
int
ret
;
unsigned
int
max
=
16384
,
size
=
0
;
char
*
buffer
;
buffer
=
talloc_array
(
ctx
,
char
,
max
+
1
);
while
((
ret
=
read
(
fd
,
buffer
+
size
,
max
-
size
))
>
0
)
{
size
+=
ret
;
if
(
size
==
max
)
buffer
=
talloc_realloc
(
ctx
,
buffer
,
char
,
max
*=
2
+
1
);
}
if
(
ret
<
0
)
{
talloc_free
(
buffer
);
buffer
=
NULL
;
}
else
buffer
[
size
]
=
'\0'
;
return
buffer
;
}
/* This version adds one byte (for nul term) */
static
void
*
grab_file
(
const
void
*
ctx
,
const
char
*
filename
)
{
int
fd
;
char
*
buffer
;
if
(
streq
(
filename
,
"-"
))
fd
=
dup
(
STDIN_FILENO
);
else
fd
=
open
(
filename
,
O_RDONLY
,
0
);
if
(
fd
<
0
)
return
NULL
;
buffer
=
grab_fd
(
ctx
,
fd
);
close_noerr
(
fd
);
return
buffer
;
}
/* This is a dumb one which copies. We could mangle instead. */
static
char
**
split
(
const
void
*
ctx
,
const
char
*
text
,
const
char
*
delims
,
unsigned
int
*
nump
)
{
char
**
lines
=
NULL
;
unsigned
int
max
=
64
,
num
=
0
;
lines
=
talloc_array
(
ctx
,
char
*
,
max
+
1
);
while
(
*
text
!=
'\0'
)
{
unsigned
int
len
=
strcspn
(
text
,
delims
);
lines
[
num
]
=
talloc_array
(
lines
,
char
,
len
+
1
);
memcpy
(
lines
[
num
],
text
,
len
);
lines
[
num
][
len
]
=
'\0'
;
text
+=
len
;
text
+=
strspn
(
text
,
delims
);
if
(
++
num
==
max
)
lines
=
talloc_realloc
(
ctx
,
lines
,
char
*
,
max
*=
2
+
1
);
}
lines
[
num
]
=
NULL
;
if
(
nump
)
*
nump
=
num
;
return
lines
;
}
char
**
get_file_lines
(
void
*
ctx
,
const
char
*
name
,
unsigned
int
*
num_lines
)
{
char
*
buffer
=
grab_file
(
ctx
,
name
);
if
(
!
buffer
)
err
(
1
,
"Getting file %s"
,
name
);
return
split
(
buffer
,
buffer
,
"
\n
"
,
num_lines
);
}
ccan_tools/ccanlint/get_file_lines.h
0 → 100644
View file @
c8acddea
#ifndef GET_FILE_LINES_H
#define GET_FILE_LINES_H
char
**
get_file_lines
(
void
*
ctx
,
const
char
*
name
,
unsigned
int
*
num_lines
);
#endif
/* GET_FILE_LINES_H */
ccan_tools/ccanlint/has_main_header.c
0 → 100644
View file @
c8acddea
#include "ccanlint.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string/string.h>
#include <talloc/talloc.h>
#include <noerr/noerr.h>
static
void
*
check_has_main_header
(
struct
manifest
*
m
)
{
struct
ccan_file
*
f
;
list_for_each
(
&
m
->
h_files
,
f
,
list
)
{
if
(
strstarts
(
f
->
name
,
m
->
basename
)
&&
strlen
(
f
->
name
)
==
strlen
(
m
->
basename
)
+
2
)
return
NULL
;
}
return
m
;
}
static
const
char
*
describe_has_main_header
(
struct
manifest
*
m
,
void
*
check_result
)
{
return
talloc_asprintf
(
m
,
"You have no %s/%s.h header file.
\n\n
"
"CCAN modules have a name, the same as the directory name. They're
\n
"
"expected to have an interface in the header of the same name.
\n
"
,
m
->
basename
,
m
->
basename
);
}
struct
ccanlint
has_main_header
=
{
.
name
=
"No main header file"
,
.
check
=
check_has_main_header
,
.
describe
=
describe_has_main_header
,
};
ccan_tools/ccanlint/has_tests.c
0 → 100644
View file @
c8acddea
#include "ccanlint.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string/string.h>
#include <talloc/talloc.h>
#include <noerr/noerr.h>
static
char
test_is_not_dir
[]
=
"test is not a directory"
;
static
void
*
check_has_tests
(
struct
manifest
*
m
)
{
struct
stat
st
;
if
(
lstat
(
"test"
,
&
st
)
!=
0
)
{
if
(
errno
!=
ENOENT
)
err
(
1
,
"statting test/"
);
return
"You have no test directory"
;
}
if
(
!
S_ISDIR
(
st
.
st_mode
))
return
test_is_not_dir
;
if
(
list_empty
(
&
m
->
run_tests
)
&&
list_empty
(
&
m
->
compile_ok_tests
))
{
if
(
list_empty
(
&
m
->
compile_fail_tests
))
return
"You have no tests in the test directory"
;
else
return
"You have no positive tests in the test directory"
;
}
return
NULL
;
}
static
const
char
*
describe_has_tests
(
struct
manifest
*
m
,
void
*
check_result
)
{
return
talloc_asprintf
(
m
,
"%s
\n\n
"
"CCAN modules have a directory called test/ which contains tests.
\n
"
"There are three kinds of tests: run, compile_ok and compile_fail:
\n
"
"you can tell which type of test a C file is by its name, eg 'run.c'
\n
"
"and 'run-simple.c' are both run tests.
\n\n
"
"The simplest kind of test is a run test, which must compile with no
\n
"
"warnings, and then run: it is expected to use libtap to report its
\n
"
"results in a simple and portable format.
\n
"
"compile_ok tests are a subset of run tests: they must compile and
\n
"
"link, but aren't run.
\n
"
"compile_fail tests are tests which should fail to compile (or emit
\n
"
"warnings) or link when FAIL is defined, but should compile and link
\n
"
"when it's not defined: this helps ensure unrelated errors don't make
\n
"
"compilation fail.
\n\n
"
"Note that the tests are not linked against the files in the
\n
"
"above: you should directly #include those C files you want. This
\n
"
"allows access to static functions and use special effects inside
\n
"
"test files
\n
"
,
(
char
*
)
check_result
);
}
static
void
handle_no_tests
(
struct
manifest
*
m
,
void
*
check_result
)
{
FILE
*
run
;
struct
ccan_file
*
i
;
if
(
check_result
==
test_is_not_dir
)
return
;
if
(
!
ask
(
"Should I create a template test/run.c file for you?"
))
return
;
if
(
mkdir
(
"test"
,
0600
)
!=
0
)
{
if
(
errno
!=
EEXIST
)
err
(
1
,
"Creating test/ directory"
);
}
run
=
fopen
(
"test/run.c"
,
"w"
);
if
(
!
run
)
err
(
1
,
"Trying to create a test/run.c"
);
fputs
(
"/* Include the main header first, to test it works */
\n
"
,
run
);
fprintf
(
run
,
"#include
\"
%s/%s.h
\"\n
"
,
m
->
basename
,
m
->
basename
);
fputs
(
"/* Include the C files directly. */
\n
"
,
run
);
list_for_each
(
&
m
->
c_files
,
i
,
list
)
fprintf
(
run
,
"#include
\"
%s/%s
\"\n
"
,
m
->
basename
,
i
->
name
);
fputs
(
"#include
\"
tap/tap.h
\"\n
"
,
run
);
fputs
(
"
\n
"
,
run
);
fputs
(
"int main(int argc, char *argv[])
\n
"
,
run
);
fputs
(
"{
\n
"
,
run
);
fputs
(
"
\t
/* This is how many tests you plan to run
\n
"
,
run
);
fputs
(
"
\t
plan_tests(3);
\n
"
,
run
);
fputs
(
"
\n
"
,
run
);
fputs
(
"
\t
/* Simple thing we expect to succeed */
\n
"
,
run
);
fputs
(
"
\t
ok1(some_test())
\n
"
,
run
);
fputs
(
"
\t
/* Same, with an explicit description of the test. */
\n
"
,
run
);
fputs
(
"
\t
ok(some_test(),
\"
%s with no args should return 1
\"
,
\"
some_test
\"
)
\n
"
,
run
);
fputs
(
"
\t
/* How to print out messages for debugging. */
\n
"
,
run
);
fputs
(
"
\t
diag(
\"
Address of some_test is %p
\"
, &some_test)
\n
"
,
run
);
fputs
(
"
\t
/* Conditional tests must be explicitly skipped. */
\n
"
,
run
);
fputs
(
"#if HAVE_SOME_FEATURE
\n
"
,
run
);
fputs
(
"
\t
ok1(test_some_feature())
\n
"
,
run
);
fputs
(
"#else
\n
"
,
run
);
fputs
(
"
\t
skip(1,
\"
Don
\'
t have SOME_FEATURE
\"
)
\n
"
,
run
);
fputs
(
"#endif
\n
"
,
run
);
fputs
(
"
\n
"
,
run
);
fputs
(
"
\t
/* This exits depending on whether all tests passed */
\n
"
,
run
);
fputs
(
"
\r
eturn exit_status()
\n
"
,
run
);
fclose
(
run
);
}
struct
ccanlint
has_tests
=
{
.
name
=
"No tests"
,
.
check
=
check_has_tests
,
.
describe
=
describe_has_tests
,
.
handle
=
handle_no_tests
,
};
ccan_tools/ccanlint/idempotent.c
0 → 100644
View file @
c8acddea
#include "ccanlint.h"
#include <talloc/talloc.h>
#include <string/string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string.h>
static
const
char
explain
[]
=
"Headers usually start with the C preprocessor lines to prevent multiple
\n
"
"inclusions. These look like the following:
\n
"
"#ifndef MY_HEADER_H
\n
"
"#define MY_HEADER_H
\n
"
"...
\n
"
"#endif /* MY_HEADER_H */
\n
"
;
static
char
*
report_idem
(
struct
ccan_file
*
f
,
char
*
sofar
)
{
char
**
lines
;
char
*
secondline
;
lines
=
get_ccan_file_lines
(
f
);
if
(
f
->
num_lines
<
3
)
/* FIXME: We assume small headers probably uninteresting. */
return
NULL
;
if
(
!
strstarts
(
lines
[
0
],
"#ifndef "
))
return
talloc_asprintf_append
(
sofar
,
"%s:1:expect first line to be #ifndef.
\n
"
,
f
->
name
);
secondline
=
talloc_asprintf
(
f
,
"#define %s"
,
lines
[
0
]
+
strlen
(
"#ifndef "
));
if
(
!
streq
(
lines
[
1
],
secondline
))
return
talloc_asprintf_append
(
sofar
,
"%s:2:expect second line to be '%s'.
\n
"
,
f
->
name
,
secondline
);
return
sofar
;
}
static
void
*
check_idempotent
(
struct
manifest
*
m
)
{
struct
ccan_file
*
f
;
char
*
report
=
NULL
;
list_for_each
(
&
m
->
h_files
,
f
,
list
)
report
=
report_idem
(
f
,
report
);
return
report
;
}
static
const
char
*
describe_idempotent
(
struct
manifest
*
m
,
void
*
check_result
)
{
return
talloc_asprintf
(
check_result
,
"Some headers not idempotent:
\n
"
"%s
\n
%s"
,
(
char
*
)
check_result
,
explain
);
}
struct
ccanlint
idempotent
=
{
.
name
=
"Headers are #ifndef/#define idempotent wrapped"
,
.
total_score
=
1
,
.
check
=
check_idempotent
,
.
describe
=
describe_idempotent
,
};
ccan_tools/ccanlint/no_info.c
0 → 100644
View file @
c8acddea
#include "ccanlint.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <limits.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>
#include <err.h>
#include <string.h>
#include <noerr/noerr.h>
static
void
*
check_no_info
(
struct
manifest
*
m
)
{
if
(
m
->
info_file
)
return
NULL
;
return
m
;
}
static
const
char
*
describe_no_info
(
struct
manifest
*
m
,
void
*
check_result
)
{
return
"You have no _info.c file.
\n\n
"
"The file _info.c contains the metadata for a ccan package: things
\n
"
"like the dependencies, the documentation for the package as a whole
\n
"
"and license information.
\n
"
;
}
static
const
char
template
[]
=
"#include <string.h>
\n
"
"#include
\"
config.h
\"\n
"
"
\n
"
"/**
\n
"
" * %s - YOUR-ONE-LINE-DESCRIPTION-HERE
\n
"
" *
\n
"
" * This code ... YOUR-BRIEF-SUMMARY-HERE
\n
"
" *
\n
"
" * Example:
\n
"
" * FULLY-COMPILABLE-INDENTED-TRIVIAL-BUT-USEFUL-EXAMPLE-HERE
\n
"
" */
\n
"
"int main(int argc, char *argv[])
\n
"
"{
\n
"
" /* Expect exactly one argument
\n
"
" if (argc != 2)
\n
"
" return 1;
\n
"
"
\n
"
" if (strcmp(argv[1],
\"
depends
\"
) == 0) {
\n
"
" PRINTF-CCAN-PACKAGES-YOU-NEED-ONE-PER-LINE-IF-ANY
\n
"
" return 0;
\n
"
" }
\n
"
"
\n
"
" return 1;
\n
"
"}
\n
"
;
static
void
create_info_template
(
struct
manifest
*
m
,
void
*
check_result
)
{
FILE
*
info
;
if
(
!
ask
(
"Should I create a template _info.c file for you?"
))
return
;
info
=
fopen
(
"_info.c"
,
"w"
);
if
(
!
info
)
err
(
1
,
"Trying to create a template _info.c"
);
if
(
fprintf
(
info
,
template
,
m
->
basename
)
<
0
)
{
unlink_noerr
(
"_info.c"
);
err
(
1
,
"Writing template into _info.c"
);
}
fclose
(
info
);
}
struct
ccanlint
no_info
=
{
.
name
=
"No _info.c file"
,
.
check
=
check_no_info
,
.
describe
=
describe_no_info
,
.
handle
=
create_info_template
,
};
ccan_tools/ccanlint/trailing_whitespace.c
0 → 100644
View file @
c8acddea
/* Trailing whitespace test. Almost embarrassing, but trivial. */
#include "ccanlint.h"
#include <talloc/talloc.h>
#include <string/string.h>
static
char
*
report_on_trailing_whitespace
(
const
char
*
line
)
{
if
(
!
strends
(
line
,
" "
)
&&
!
strends
(
line
,
"
\t
"
))
return
NULL
;
if
(
strlen
(
line
)
>
20
)
return
talloc_asprintf
(
line
,
"...'%s'"
,
line
+
strlen
(
line
)
-
20
);
return
talloc_asprintf
(
line
,
"'%s'"
,
line
);
}
static
void
*
check_trailing_whitespace
(
struct
manifest
*
m
)
{
char
*
report
;
report
=
report_on_lines
(
&
m
->
c_files
,
report_on_trailing_whitespace
,
NULL
);
report
=
report_on_lines
(
&
m
->
h_files
,
report_on_trailing_whitespace
,
report
);
return
report
;
}
static
const
char
*
describe_trailing_whitespace
(
struct
manifest
*
m
,
void
*
check_result
)
{
return
talloc_asprintf
(
check_result
,
"Some source files have trailing whitespace:
\n
"
"%s"
,
(
char
*
)
check_result
);
}
struct
ccanlint
trailing_whitespace
=
{
.
name
=
"Lines with unnecessary trailing whitespace"
,
.
total_score
=
1
,
.
check
=
check_trailing_whitespace
,
.
describe
=
describe_trailing_whitespace
,
};
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment