Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sun, Dec 17, 2017 at 01:46:45PM -0800, Linus Torvalds wrote: > On Sat, Dec 16, 2017 at 5:26 PM, Joe Percheswrote: > >> > >>I'm not expecting you to be able to write a perl script that checks > >>the first line, but we have way too many 200-plus line functions in > >>the kernel. I'd like a warning on anything over 200 lines (a factor > >>of 4 over Linus's stated goal). > > > > In response to Matthew's request: > > > > This is a possible checkpatch warning for long > > function definitions. > > So I'm not sure a line count makes sense. > > Sometimes long functions can be sensible, if they are basically just > one big case-statement or similar. > > Looking at one of your examples: futex_requeue() is indeed a long > function, but that's mainly because it has a lot of comments about > exactly what is going on, and while it only has one (fairly small) > case statement, the rest of it is very similar (ie "in this case, do > XYZ"). > > Another case I looked at - try_to_unmap_one() - had very similar > behavior. It's long, but it's not long for the wrong reasons. > > And yes, "copy_process()" is disgusting, and probably _could_ be split > up a bit, but at the same time the bulk of the lines there really is > just the "initialize all the parts of the "struct task_struct". > > And other times, I suspect even a 50-line function is way too dense, > just because it's doing crazy things. > > So I have a really hard time with some arbitrary line limit. At eh > very least, I think it should ignore comments and whitespace lines. > > And yes, some real "complexity analysis" might give a much more sane > limit, but I don't even know what that would be or how it would work. > It would be very easy to let sparse calculate the cyclomatic complexity of each function (and then either printing it or warn if too high), but: - warning would also need a hard limit - cyclomatic complexity of a function with a big (but simple) switch will also be high. I far from sure that the cyclomatic complexity is very useful but maybe some variation of it (like counting a switch as a single edge) could have some value here. -- Luc Van Oostenryck
Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sun, Dec 17, 2017 at 01:46:45PM -0800, Linus Torvalds wrote: > On Sat, Dec 16, 2017 at 5:26 PM, Joe Perches wrote: > >> > >>I'm not expecting you to be able to write a perl script that checks > >>the first line, but we have way too many 200-plus line functions in > >>the kernel. I'd like a warning on anything over 200 lines (a factor > >>of 4 over Linus's stated goal). > > > > In response to Matthew's request: > > > > This is a possible checkpatch warning for long > > function definitions. > > So I'm not sure a line count makes sense. > > Sometimes long functions can be sensible, if they are basically just > one big case-statement or similar. > > Looking at one of your examples: futex_requeue() is indeed a long > function, but that's mainly because it has a lot of comments about > exactly what is going on, and while it only has one (fairly small) > case statement, the rest of it is very similar (ie "in this case, do > XYZ"). > > Another case I looked at - try_to_unmap_one() - had very similar > behavior. It's long, but it's not long for the wrong reasons. > > And yes, "copy_process()" is disgusting, and probably _could_ be split > up a bit, but at the same time the bulk of the lines there really is > just the "initialize all the parts of the "struct task_struct". > > And other times, I suspect even a 50-line function is way too dense, > just because it's doing crazy things. > > So I have a really hard time with some arbitrary line limit. At eh > very least, I think it should ignore comments and whitespace lines. > > And yes, some real "complexity analysis" might give a much more sane > limit, but I don't even know what that would be or how it would work. > It would be very easy to let sparse calculate the cyclomatic complexity of each function (and then either printing it or warn if too high), but: - warning would also need a hard limit - cyclomatic complexity of a function with a big (but simple) switch will also be high. I far from sure that the cyclomatic complexity is very useful but maybe some variation of it (like counting a switch as a single edge) could have some value here. -- Luc Van Oostenryck
Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sun, 2017-12-17 at 13:46 -0800, Linus Torvalds wrote: > On Sat, Dec 16, 2017 at 5:26 PM, Joe Percheswrote: > > > > > >I'm not expecting you to be able to write a perl script that checks > > >the first line, but we have way too many 200-plus line functions in > > >the kernel. I'd like a warning on anything over 200 lines (a factor > > >of 4 over Linus's stated goal). > > > > In response to Matthew's request: > > > > This is a possible checkpatch warning for long > > function definitions. > > So I'm not sure a line count makes sense. > > Sometimes long functions can be sensible, if they are basically just > one big case-statement or similar. > > Looking at one of your examples: futex_requeue() is indeed a long > function, but that's mainly because it has a lot of comments about > exactly what is going on, and while it only has one (fairly small) > case statement, the rest of it is very similar (ie "in this case, do > XYZ"). > > Another case I looked at - try_to_unmap_one() - had very similar > behavior. It's long, but it's not long for the wrong reasons. > > And yes, "copy_process()" is disgusting, and probably _could_ be split > up a bit, but at the same time the bulk of the lines there really is > just the "initialize all the parts of the "struct task_struct". > > And other times, I suspect even a 50-line function is way too dense, > just because it's doing crazy things. > > So I have a really hard time with some arbitrary line limit. At eh > very least, I think it should ignore comments and whitespace lines. That part is easy enough to do. (below) > And yes, some real "complexity analysis" might give a much more sane > limit, but I don't even know what that would be or how it would work. I suspect there are better tools (like gnu complexity) for this and I'm not at all tied to this as a checkpatch feature. btw: futex_requeue line count is now 140 so it doesn't warn. --- scripts/checkpatch.pl | 21 + 1 file changed, 21 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 168687ae24fa..99c065f90360 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -59,6 +59,7 @@ my $conststructsfile = "$D/const_structs.checkpatch"; my $typedefsfile = ""; my $color = "auto"; my $allow_c99_comments = 1; +my $max_function_length = 200; sub help { my ($exitcode) = @_; @@ -2202,6 +2203,8 @@ sub process { my $realcnt = 0; my $here = ''; my $context_function; #undef'd unless there's a known function + my $context_function_start; + my $context_function_lines; my $in_comment = 0; my $comment_edge = 0; my $first_line = 0; @@ -2341,6 +2344,8 @@ sub process { } else { undef $context_function; } + undef $context_function_start; + $context_function_lines = 0; next; # track the line number as we move through the hunk, note that @@ -3200,11 +3205,25 @@ sub process { if ($sline =~ /^\+\{\s*$/ && $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) { $context_function = $1; + $context_function_start = $realline; + $context_function_lines = 0; + } + +# if in a function, count the non-blank lines + if (defined ($context_function) && $sline !~ /^[ \+]\s*$/) { + $context_function_lines++; } # check if this appears to be the end of function declaration if ($sline =~ /^\+\}\s*$/) { + if (defined($context_function_start) && + $context_function_lines > $max_function_length) { + WARN("LONG_FUNCTION", +"'$context_function' function definition is " . $context_function_lines . " statement lines, perhaps refactor\n" . $herecurr); + } undef $context_function; + undef $context_function_start; + $context_function_lines = 0; } # check indentation of any line with a bare else @@ -5983,6 +6002,8 @@ sub process { defined $stat && $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) { $context_function = $1; + $context_function_start = $realline; + $context_function_lines = 0; # check for multiline function definition with misplaced open brace my $ok = 0;
Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sun, 2017-12-17 at 13:46 -0800, Linus Torvalds wrote: > On Sat, Dec 16, 2017 at 5:26 PM, Joe Perches wrote: > > > > > >I'm not expecting you to be able to write a perl script that checks > > >the first line, but we have way too many 200-plus line functions in > > >the kernel. I'd like a warning on anything over 200 lines (a factor > > >of 4 over Linus's stated goal). > > > > In response to Matthew's request: > > > > This is a possible checkpatch warning for long > > function definitions. > > So I'm not sure a line count makes sense. > > Sometimes long functions can be sensible, if they are basically just > one big case-statement or similar. > > Looking at one of your examples: futex_requeue() is indeed a long > function, but that's mainly because it has a lot of comments about > exactly what is going on, and while it only has one (fairly small) > case statement, the rest of it is very similar (ie "in this case, do > XYZ"). > > Another case I looked at - try_to_unmap_one() - had very similar > behavior. It's long, but it's not long for the wrong reasons. > > And yes, "copy_process()" is disgusting, and probably _could_ be split > up a bit, but at the same time the bulk of the lines there really is > just the "initialize all the parts of the "struct task_struct". > > And other times, I suspect even a 50-line function is way too dense, > just because it's doing crazy things. > > So I have a really hard time with some arbitrary line limit. At eh > very least, I think it should ignore comments and whitespace lines. That part is easy enough to do. (below) > And yes, some real "complexity analysis" might give a much more sane > limit, but I don't even know what that would be or how it would work. I suspect there are better tools (like gnu complexity) for this and I'm not at all tied to this as a checkpatch feature. btw: futex_requeue line count is now 140 so it doesn't warn. --- scripts/checkpatch.pl | 21 + 1 file changed, 21 insertions(+) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 168687ae24fa..99c065f90360 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -59,6 +59,7 @@ my $conststructsfile = "$D/const_structs.checkpatch"; my $typedefsfile = ""; my $color = "auto"; my $allow_c99_comments = 1; +my $max_function_length = 200; sub help { my ($exitcode) = @_; @@ -2202,6 +2203,8 @@ sub process { my $realcnt = 0; my $here = ''; my $context_function; #undef'd unless there's a known function + my $context_function_start; + my $context_function_lines; my $in_comment = 0; my $comment_edge = 0; my $first_line = 0; @@ -2341,6 +2344,8 @@ sub process { } else { undef $context_function; } + undef $context_function_start; + $context_function_lines = 0; next; # track the line number as we move through the hunk, note that @@ -3200,11 +3205,25 @@ sub process { if ($sline =~ /^\+\{\s*$/ && $prevline =~ /^\+(?:(?:(?:$Storage|$Inline)\s*)*\s*$Type\s*)?($Ident)\(/) { $context_function = $1; + $context_function_start = $realline; + $context_function_lines = 0; + } + +# if in a function, count the non-blank lines + if (defined ($context_function) && $sline !~ /^[ \+]\s*$/) { + $context_function_lines++; } # check if this appears to be the end of function declaration if ($sline =~ /^\+\}\s*$/) { + if (defined($context_function_start) && + $context_function_lines > $max_function_length) { + WARN("LONG_FUNCTION", +"'$context_function' function definition is " . $context_function_lines . " statement lines, perhaps refactor\n" . $herecurr); + } undef $context_function; + undef $context_function_start; + $context_function_lines = 0; } # check indentation of any line with a bare else @@ -5983,6 +6002,8 @@ sub process { defined $stat && $stat =~ /^.\s*(?:$Storage\s+)?$Type\s*($Ident)\s*$balanced_parens\s*{/s) { $context_function = $1; + $context_function_start = $realline; + $context_function_lines = 0; # check for multiline function definition with misplaced open brace my $ok = 0;
Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sat, Dec 16, 2017 at 5:26 PM, Joe Percheswrote: >> >>I'm not expecting you to be able to write a perl script that checks >>the first line, but we have way too many 200-plus line functions in >>the kernel. I'd like a warning on anything over 200 lines (a factor >>of 4 over Linus's stated goal). > > In response to Matthew's request: > > This is a possible checkpatch warning for long > function definitions. So I'm not sure a line count makes sense. Sometimes long functions can be sensible, if they are basically just one big case-statement or similar. Looking at one of your examples: futex_requeue() is indeed a long function, but that's mainly because it has a lot of comments about exactly what is going on, and while it only has one (fairly small) case statement, the rest of it is very similar (ie "in this case, do XYZ"). Another case I looked at - try_to_unmap_one() - had very similar behavior. It's long, but it's not long for the wrong reasons. And yes, "copy_process()" is disgusting, and probably _could_ be split up a bit, but at the same time the bulk of the lines there really is just the "initialize all the parts of the "struct task_struct". And other times, I suspect even a 50-line function is way too dense, just because it's doing crazy things. So I have a really hard time with some arbitrary line limit. At eh very least, I think it should ignore comments and whitespace lines. And yes, some real "complexity analysis" might give a much more sane limit, but I don't even know what that would be or how it would work. LInus
Re: [RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Sat, Dec 16, 2017 at 5:26 PM, Joe Perches wrote: >> >>I'm not expecting you to be able to write a perl script that checks >>the first line, but we have way too many 200-plus line functions in >>the kernel. I'd like a warning on anything over 200 lines (a factor >>of 4 over Linus's stated goal). > > In response to Matthew's request: > > This is a possible checkpatch warning for long > function definitions. So I'm not sure a line count makes sense. Sometimes long functions can be sensible, if they are basically just one big case-statement or similar. Looking at one of your examples: futex_requeue() is indeed a long function, but that's mainly because it has a lot of comments about exactly what is going on, and while it only has one (fairly small) case statement, the rest of it is very similar (ie "in this case, do XYZ"). Another case I looked at - try_to_unmap_one() - had very similar behavior. It's long, but it's not long for the wrong reasons. And yes, "copy_process()" is disgusting, and probably _could_ be split up a bit, but at the same time the bulk of the lines there really is just the "initialize all the parts of the "struct task_struct". And other times, I suspect even a 50-line function is way too dense, just because it's doing crazy things. So I have a really hard time with some arbitrary line limit. At eh very least, I think it should ignore comments and whitespace lines. And yes, some real "complexity analysis" might give a much more sane limit, but I don't even know what that would be or how it would work. LInus
[RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Mon, 2017-12-11 at 14:43 -0800, Matthew Wilcox wrote: > - There's no warning for the first paragraph of section 6: > > 6) Functions > > > Functions should be short and sweet, and do just one thing. They should > fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, > as we all know), and do one thing and do that well. > >I'm not expecting you to be able to write a perl script that checks >the first line, but we have way too many 200-plus line functions in >the kernel. I'd like a warning on anything over 200 lines (a factor >of 4 over Linus's stated goal). In response to Matthew's request: This is a possible checkpatch warning for long function definitions. Running against the last 1 git commits, there are no false positives though perhaps there are some false negatives. These are the matches in the last 1 commits: 1 227 42e0442f8a237d3de9ea3f2dd2be2739e6db7fdb:1157: WARNING: 'ir_lirc_ioctl' function definition is 206 lines, perhaps refactor 2 552 148abd3b5b146021a637d36ac5c0ee91cd4ad520:790: WARNING: 'tda18250_set_params' function definition is 206 lines, perhaps refactor 31352 123e25c4a5658be27f08ed0fb85ade34683e5dc7:366: WARNING: 'cudbg_fill_meminfo' function definition is 252 lines, perhaps refactor 42688 62d591a8e00cc349e6a9efb87efac9548f178624:462: WARNING: 'program_watermarks' function definition is 232 lines, perhaps refactor 56171 d2ddc776a4581d900fc3bdc7803b403daae64d88:3530: WARNING: 'afs_select_fileserver' function definition is 283 lines, perhaps refactor 69135 2f4b411a3d6766e6362ffbf00e0495a2dfe92507:962: WARNING: 'i40e_parse_cls_flower' function definition is 242 lines, perhaps refactor 79450 fd708b81d972a0714b02a60eb4792fdbf15868c4:1094: WARNING: 'btrfs_ref_tree_mod' function definition is 201 lines, perhaps refactor Running against files in mm lib and kernel, there are 52 functions that exceed 200 lines. $ git ls-files -- mm kernel lib | \ xargs ./scripts/checkpatch.pl -f --types=long_function --terse --quiet --no-summary | \ cat -n 1 kernel/audit.c:1447: WARNING: 'audit_receive_msg' function definition is 308 lines, perhaps refactor 2 kernel/auditsc.c:713: WARNING: 'audit_filter_rules' function definition is 273 lines, perhaps refactor 3 kernel/bpf/core.c:1285: WARNING: '___bpf_prog_run' function definition is 508 lines, perhaps refactor 4 kernel/bpf/verifier.c:2240: WARNING: 'adjust_scalar_min_max_vals' function definition is 218 lines, perhaps refactor 5 kernel/bpf/verifier.c:4064: WARNING: 'do_check' function definition is 288 lines, perhaps refactor 6 kernel/debug/debug_core.c:682: WARNING: 'kgdb_cpu_enter' function definition is 214 lines, perhaps refactor 7 kernel/debug/kdb/kdb_io.c:422: WARNING: 'kdb_read' function definition is 217 lines, perhaps refactor 8 kernel/debug/kdb/kdb_io.c:850: WARNING: 'vkdb_printf' function definition is 297 lines, perhaps refactor 9 kernel/fork.c:2033: WARNING: 'copy_process' function definition is 454 lines, perhaps refactor 10 kernel/futex.c:705: WARNING: 'get_futex_key' function definition is 204 lines, perhaps refactor 11 kernel/futex.c:2135: WARNING: 'futex_requeue' function definition is 283 lines, perhaps refactor 12 kernel/irq/manage.c:1488: WARNING: '__setup_irq' function definition is 354 lines, perhaps refactor 13 kernel/locking/locktorture.c:1050: WARNING: 'lock_torture_init' function definition is 201 lines, perhaps refactor 14 kernel/locking/qspinlock.c:505: WARNING: 'queued_spin_lock_slowpath' function definition is 210 lines, perhaps refactor 15 kernel/locking/rtmutex.c:796: WARNING: 'rt_mutex_adjust_prio_chain' function definition is 348 lines, perhaps refactor 16 kernel/power/swap.c:873: WARNING: 'save_image_lzo' function definition is 205 lines, perhaps refactor 17 kernel/power/swap.c:1469: WARNING: 'load_image_lzo' function definition is 312 lines, perhaps refactor 18 kernel/ptrace.c:1104: WARNING: 'ptrace_request' function definition is 221 lines, perhaps refactor 19 kernel/sched/core.c:4254: WARNING: '_setscheduler' function definition is 238 lines, perhaps refactor 20 kernel/sched/fair.c:8722: WARNING: 'load_balance' function definition is 261 lines, perhaps refactor 21 kernel/trace/trace_kprobe.c:839: WARNING: 'create_trace_kprobe' function definition is 207 lines, perhaps refactor 22 kernel/trace/trace_uprobe.c:564: WARNING: 'create_trace_uprobe' function definition is 202 lines, perhaps refactor 23 lib/asn1_decoder.c:518: WARNING: 'asn1_ber_decoder' function definition is 347 lines, perhaps refactor 24 lib/assoc_array.c:790: WARNING: 'assoc_array_insert_into_terminal_node' function definition is 312 lines, perhaps refactor 25 lib/assoc_array.c:1721: WARNING: 'assoc_array_gc' function definition is 266 lines, perhaps
[RFC patch] checkpatch: Add a test for long function definitions (>200 lines)
On Mon, 2017-12-11 at 14:43 -0800, Matthew Wilcox wrote: > - There's no warning for the first paragraph of section 6: > > 6) Functions > > > Functions should be short and sweet, and do just one thing. They should > fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24, > as we all know), and do one thing and do that well. > >I'm not expecting you to be able to write a perl script that checks >the first line, but we have way too many 200-plus line functions in >the kernel. I'd like a warning on anything over 200 lines (a factor >of 4 over Linus's stated goal). In response to Matthew's request: This is a possible checkpatch warning for long function definitions. Running against the last 1 git commits, there are no false positives though perhaps there are some false negatives. These are the matches in the last 1 commits: 1 227 42e0442f8a237d3de9ea3f2dd2be2739e6db7fdb:1157: WARNING: 'ir_lirc_ioctl' function definition is 206 lines, perhaps refactor 2 552 148abd3b5b146021a637d36ac5c0ee91cd4ad520:790: WARNING: 'tda18250_set_params' function definition is 206 lines, perhaps refactor 31352 123e25c4a5658be27f08ed0fb85ade34683e5dc7:366: WARNING: 'cudbg_fill_meminfo' function definition is 252 lines, perhaps refactor 42688 62d591a8e00cc349e6a9efb87efac9548f178624:462: WARNING: 'program_watermarks' function definition is 232 lines, perhaps refactor 56171 d2ddc776a4581d900fc3bdc7803b403daae64d88:3530: WARNING: 'afs_select_fileserver' function definition is 283 lines, perhaps refactor 69135 2f4b411a3d6766e6362ffbf00e0495a2dfe92507:962: WARNING: 'i40e_parse_cls_flower' function definition is 242 lines, perhaps refactor 79450 fd708b81d972a0714b02a60eb4792fdbf15868c4:1094: WARNING: 'btrfs_ref_tree_mod' function definition is 201 lines, perhaps refactor Running against files in mm lib and kernel, there are 52 functions that exceed 200 lines. $ git ls-files -- mm kernel lib | \ xargs ./scripts/checkpatch.pl -f --types=long_function --terse --quiet --no-summary | \ cat -n 1 kernel/audit.c:1447: WARNING: 'audit_receive_msg' function definition is 308 lines, perhaps refactor 2 kernel/auditsc.c:713: WARNING: 'audit_filter_rules' function definition is 273 lines, perhaps refactor 3 kernel/bpf/core.c:1285: WARNING: '___bpf_prog_run' function definition is 508 lines, perhaps refactor 4 kernel/bpf/verifier.c:2240: WARNING: 'adjust_scalar_min_max_vals' function definition is 218 lines, perhaps refactor 5 kernel/bpf/verifier.c:4064: WARNING: 'do_check' function definition is 288 lines, perhaps refactor 6 kernel/debug/debug_core.c:682: WARNING: 'kgdb_cpu_enter' function definition is 214 lines, perhaps refactor 7 kernel/debug/kdb/kdb_io.c:422: WARNING: 'kdb_read' function definition is 217 lines, perhaps refactor 8 kernel/debug/kdb/kdb_io.c:850: WARNING: 'vkdb_printf' function definition is 297 lines, perhaps refactor 9 kernel/fork.c:2033: WARNING: 'copy_process' function definition is 454 lines, perhaps refactor 10 kernel/futex.c:705: WARNING: 'get_futex_key' function definition is 204 lines, perhaps refactor 11 kernel/futex.c:2135: WARNING: 'futex_requeue' function definition is 283 lines, perhaps refactor 12 kernel/irq/manage.c:1488: WARNING: '__setup_irq' function definition is 354 lines, perhaps refactor 13 kernel/locking/locktorture.c:1050: WARNING: 'lock_torture_init' function definition is 201 lines, perhaps refactor 14 kernel/locking/qspinlock.c:505: WARNING: 'queued_spin_lock_slowpath' function definition is 210 lines, perhaps refactor 15 kernel/locking/rtmutex.c:796: WARNING: 'rt_mutex_adjust_prio_chain' function definition is 348 lines, perhaps refactor 16 kernel/power/swap.c:873: WARNING: 'save_image_lzo' function definition is 205 lines, perhaps refactor 17 kernel/power/swap.c:1469: WARNING: 'load_image_lzo' function definition is 312 lines, perhaps refactor 18 kernel/ptrace.c:1104: WARNING: 'ptrace_request' function definition is 221 lines, perhaps refactor 19 kernel/sched/core.c:4254: WARNING: '_setscheduler' function definition is 238 lines, perhaps refactor 20 kernel/sched/fair.c:8722: WARNING: 'load_balance' function definition is 261 lines, perhaps refactor 21 kernel/trace/trace_kprobe.c:839: WARNING: 'create_trace_kprobe' function definition is 207 lines, perhaps refactor 22 kernel/trace/trace_uprobe.c:564: WARNING: 'create_trace_uprobe' function definition is 202 lines, perhaps refactor 23 lib/asn1_decoder.c:518: WARNING: 'asn1_ber_decoder' function definition is 347 lines, perhaps refactor 24 lib/assoc_array.c:790: WARNING: 'assoc_array_insert_into_terminal_node' function definition is 312 lines, perhaps refactor 25 lib/assoc_array.c:1721: WARNING: 'assoc_array_gc' function definition is 266 lines, perhaps