Giter Site home page Giter Site logo

cs50 / help50-deprecated Goto Github PK

View Code? Open in Web Editor NEW
62.0 19.0 65.0 4.55 MB

This is help50, a command-line tool that helps students understand error messages.

Home Page: https://cs50.harvard.edu/

License: GNU General Public License v3.0

Python 100.00%

help50-deprecated's Introduction

help50

Build Status

help50 is a command line tool that makes an effort to translate some of the more arcane error messages that other tools, such as clang or valgrind, sometimes spit out. In this way, it serves as a "virtual TF" of sorts, hopefully helping nudge students in the right direction, so that they needn’t wait for a staff member at office hours when a little bit of translation of the error message is really all that’s needed to move on.

Installation

pip install help50

Usage

  • help50 ./foo
  • CC=clang help50 make foo
  • help50 clang -o foo foo.c
  • ./foo |& help50
  • CC=clang make foo |& help50
  • clang -o foo foo.c |& help50

help50-deprecated's People

Contributors

annieechen avatar brianyu28 avatar cmlsharp avatar coltonoscopy avatar dlloyd09 avatar dmalan avatar glennholloway avatar jelleas avatar rongxin-liu avatar tlively avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

help50-deprecated's Issues

variable is uninitialized whenever…

whenever 'if' condition is false

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    greedy.c  -lcs50 -lm -o greedy
greedy.c:16:16: error: variable 'i' is used uninitialized whenever 'if' condition is false [-Werror,-Wsometimes-uninitialized]
            if(c>0){
               ^~~

whenever function 'main' is called

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:9:9: error: variable 'h' is used uninitialized whenever function 'main' is called [-Werror,-Wsometimes-uninitialized]
    int h;
    ~~~~^

whenever 'do' loop exits because its condition is false

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    greedy.c  -lcs50 -lm -o greedy
greedy.c:14:16: error: variable 'coincount' is used uninitialized whenever 'do' loop exits because its condition is false [-Werror,-Wsometimes-uninitialized]
        while (change < 0);
               ^~~~~~~~~~

whenever function is called

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:28:9: error: variable 'height' is used uninitialized whenever function 'get_height' is called [-Werror,-Wsometimes-uninitialized]
    int height;
    ~~~~^~~~~~

allow helpers to return subsets of lines?

Sooo, after thinking about valgrind, I wonder if we should revert to (before, after) but in this way:

  • application.py iterates over lines, passing in lines[i:] iteratively until a helper returns (before, after).
  • At that point, application.py should print lines[0:i] as well as before.
  • If helper uses lines i through j but there's still one or more lines after j that it doesn't care about, helper should append ... to before.

This would allow something like the valgrind helper to output:

==26== Memcheck, a memory error detector
==26== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==26== Command: ./a.out
...
==26== Use of uninitialised value of size 8
==26==    at 0x4E8099B: _itoa_word (_itoa.c:179)
==26==    by 0x4E84636: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
...

so that the student receives help but also is able to see more clearly what help50 is seeing.

Alternatively, we could forego the ellipses idea and instead use ANSI codes to invert lines that we've matched on (i.e., highlight them). But something tells me that would be less friendly than just omitting distracting lines, replacing them with just ....

Invalid conversion specifier

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    credit.c  -lcs50 -lm -o credit
credit.c:11:24: error: invalid conversion specifier ' ' [-Werror,-Wformat-invalid-specifier]
    printf("(%lli % 100 - %lli % 10)/10", n);
                  ~~~~~^
1 error generated.
make: *** [credit] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    imreallytryingmario.c  -lcs50 -lm -o imreallytryingmario
imreallytryingmario.c:38:19: error: invalid conversion specifier '
' [-Werror,-Wformat-invalid-specifier]
        printf("c%\n", hash); 
                 ~^
1 error generated.
make: *** [imreallytryingmario] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    tests.c  -lcs50 -lm -o tests
tests.c:8:20: error: invalid conversion specifier 'k' [-Werror,-Wformat-invalid-specifier]
    printf("%f %f %k", n, m, k);
                  ~^
1 error generated.
make: *** [tests] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:9:20: error: invalid conversion specifier 'b' [-Werror,-Wformat-invalid-specifier]
    printf("Used % bottle \n",bottles);
                 ~~^
1 error generated.
make: *** [water] Error 1

Use of uninitialised value of size 8

$ cat foo.c
#include <stdio.h>

int main(void)
{
    int array[50];
    printf("%i\n", array[50]);
}
$ clang -ggdb3 foo.c
$ valgrind ./a.out
==26== Memcheck, a memory error detector
==26== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==26== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==26== Command: ./a.out
==26== 
==26== Conditional jump or move depends on uninitialised value(s)
==26==    at 0x4E814CE: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
==26== Use of uninitialised value of size 8
==26==    at 0x4E8099B: _itoa_word (_itoa.c:179)
==26==    by 0x4E84636: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
==26== Conditional jump or move depends on uninitialised value(s)
==26==    at 0x4E809A5: _itoa_word (_itoa.c:179)
==26==    by 0x4E84636: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
==26== Conditional jump or move depends on uninitialised value(s)
==26==    at 0x4E84682: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
==26== Conditional jump or move depends on uninitialised value(s)
==26==    at 0x4E81599: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
==26== Conditional jump or move depends on uninitialised value(s)
==26==    at 0x4E8161C: vfprintf (vfprintf.c:1660)
==26==    by 0x4E8B3D8: printf (printf.c:33)
==26==    by 0x40054C: main (foo.c:6)
==26== 
0
==26== 
==26== HEAP SUMMARY:
==26==     in use at exit: 0 bytes in 0 blocks
==26==   total heap usage: 0 allocs, 0 frees, 0 bytes allocated
==26== 
==26== All heap blocks were freed -- no leaks are possible
==26== 
==26== For counts of detected and suppressed errors, rerun with: -v
==26== Use --track-origins=yes to see where uninitialised values come from
==26== ERROR SUMMARY: 6 errors from 6 contexts (suppressed: 0 from 0)

Ultimately, we should try to identify main (foo.c:6) as the source of the issue, with the issue itself Use of uninitialised value of size 8, which is perhaps the most precise.

array initializer must be an initializer list or string literal

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:14:15: error: array initializer must be an initializer list or string literal
         char string[] = fullBase;
              ^
1 error generated.
make: *** [mario] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    initials.c  -lcs50 -lm -lcrypt -o initials
initials.c:9:10: error: array initializer must be an initializer list or string literal
    char LetterArray[] = (name);
         ^
1 error generated.
make: *** [initials] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    initials.c  -lcs50 -lm -o initials
initials.c:7:10: error: array initializer must be an initializer list or string literal
    char name[] = get_string;
         ^
1 error generated.
make: *** [initials] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    caesar.c  -lcs50 -lm -o caesar
caesar.c:22:14: error: array initializer must be an initializer list or string literal
        char alph[25] = (c-65);
             ^
1 error generated.
make: *** [caesar] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    vigenere.c  -lcs50 -lm -lcrypt -o vigenere
vigenere.c:13:10: error: array initializer must be an initializer list or string literal
    char k[]= (argv[1]);
         ^
1 error generated.
make: *** [vigenere] Error 1

| has lower precedence than ==

clang -ggdb3 -O0 -Qunused-arguments -std=c11 -Wall -Werror   -c -o dictionary.o dictionary.c
dictionary.c:48:29: error: | has lower precedence than ==; == will be evaluated first [-Werror,-Wparentheses]
        }else if(isalpha(c) | c == '\''){
                            ^~~~~~~~~~~
dictionary.c:48:29: note: place parentheses around the '==' expression to silence this warning
        }else if(isalpha(c) | c == '\''){
                            ^
                              (        )
dictionary.c:48:29: note: place parentheses around the | expression to evaluate it first
        }else if(isalpha(c) | c == '\''){
                 ~~~~~~~~~~~^~~
dictionary.c:58:28: error: comparison between pointer and integer ('int' and 'void *') [-Werror]
                if(word[i] != NULL){
                   ~~~~~~~ ^  ~~~~
2 errors generated.
make: *** [dictionary.o] Error 1

Code Setup issue

After installing docker and cloning the repository.
docker-compose build giving errors
ERROR: In file './docker-compose.yml' service 'version' doesn't have any configuration options. All top level keys in your docker-compose.yml must map to a dictionary of configuration options.
I tried fixing it, and found that, Ubuntu does not support docker version 2.
I use ubuntu 16.04.
docker-compose version 1.5.2 and it says its already the latest when i run update command.

Do everyone here have docker version 2 or am i doing something wrong?

Best way to handle "expected expression"?

@dmalan, can I get your thoughts on this? error: expected expression has come up multiple times on /review (11, 76, 157, 228). The error message is so general, though, that each of the four cases that have triggered it so far have been very different, making it difficult to write a good matcher for. Have any ideas on how to best handle this error?

use of undeclared identifier 'string'; did you mean 'stdin'?

input:

#include <stdio.h>

int main(void)
{
    string s = get_string();
    printf("hello, %s\n", s);
}

output:

$ clang buggy1.c
buggy1.c:5:5: error: use of undeclared identifier 'string'; did you mean 'stdin'?
    string s = get_string();
    ^~~~~~
    stdin
/usr/include/stdio.h:168:25: note: 'stdin' declared here
extern struct _IO_FILE *stdin;          /* Standard input stream.  */
                        ^
buggy1.c:5:11: error: expected ';' after expression
    string s = get_string();
          ^
          ;
buggy1.c:5:12: error: use of undeclared identifier 's'
    string s = get_string();
           ^
buggy1.c:5:16: warning: implicit declaration of function 'get_string' is invalid in C99 [-Wimplicit-function-declaration]
    string s = get_string();
               ^
buggy1.c:6:27: error: use of undeclared identifier 's'
    printf("hello, %s\n", s);
                          ^
buggy1.c:5:5: warning: expression result unused [-Wunused-value]
    string s = get_string();
    ^~~~~~
2 warnings and 4 errors generated.

current help but should recognize string as needing c50.h:

By "undeclared identifier," `clang` means you've used a name `string` which hasn't been defined.
If you mean to use `string` as a variable, make sure to declare it by specifying its type, and check that the variable name is spelled correctly.

shadow declaration clang error

Might want a "shadow declaration" help? If, for example, the student uses a comma rather than a semicolon in their for loop: for (int i = 0, i < d; i++), clang will spit out: error: declaration shadows a local variable [-Werror,-Wshadow]

unexpected type name, expected expressions

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    test.c  -lcs50 -lm -o test
test.c:10:25: error: unexpected type name 'string': expected expression
    int length = strlen(string s);
                        ^
1 error generated.
make: *** [test] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:29:44: error: unexpected type name 'string': expected expression
             space_string = space_string + string(" ");
                                           ^
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:23:22: error: unexpected type name 'string': expected expression
        printf("%c", string[j]);
                     ^
1 error generated.
make: *** [mario] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    caesar.c  -lcs50 -lm -lcrypt -o caesar
caesar.c:19:18: error: unexpected type name 'string': expected expression
        p = atoi(string s);
                 ^
1 error generated.
make: *** [caesar] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    recovertest.c  -lcs50 -lm -o recovertest
recovertest.c:89:28: error: unexpected type name 'FILE': expected expression
            else if (feof( FILE *inptr ) != 0)
                           ^
1 error generated.
make: *** [recovertest] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    initials.c  -lcs50 -lm -lcrypt -o initials
initials.c:12:24: error: unexpected type name 'string': expected expression
    if (s != NULL, s = string)
                       ^
1 error generated.
make: *** [initials] Error 1

error: expression is not an integer constant expression

greedy.c:13:11: error: expression is not an integer constant expression
    case (n<0):
         ~^~~~
mario.c:10:12: error: expression is not an integer constant expression
    case  (a<0 || a>23):
          ~^~~~~~~~~~~~
mario.c:15:13: error: expression is not an integer constant expression
    case (0<a && a<=23):
         ~~~^~~~~~~~~~~
2 errors generated.

expected parameter declarator

input:

#include <stdio.h>

int main(void);

printf("hello, world\n");

output:

$ clang bug1.c
bug1.c:5:8: error: expected parameter declarator
printf("hello, world\n");
       ^
bug1.c:5:8: error: expected ')'
bug1.c:5:7: note: to match this '('
printf("hello, world\n");
      ^
bug1.c:5:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
printf("hello, world\n");
^~~~~~
bug1.c:5:1: error: conflicting types for 'printf'
/usr/include/stdio.h:362:12: note: previous declaration is here
extern int printf (const char *__restrict __format, ...);
           ^
1 warning and 3 errors generated.

current help but not right:

Make sure that all opening parentheses `(` are matched with a closing parenthesis `)` in bug1.c.
In particular, check to see if you are missing a closing parenthesis on line 5 of bug1.c.

Too many arguments to function call

/tmp/foo-1ce1b9.o: In function `main':
foo.c:28:17: error: too many arguments to function call, expected 0, have 1
        say_hi(x);
        ~~~~~~ ^

/review inputs 137, 2703, 2756, 2757, 2902, 3704, 4949, 4970, 5503, 5595, 6550.

detect when user has hit ctrl-c or ctrl-d

For help with interactive commands, a student might run, e.g.,

help50 rm foo

at which point they're prompted by rm to confirm (because of our alias). But at that point, help50 still hasn't helped them, since rm is blocking for stdin. If student hits ctrl-c or ctrl-d at that point to break out of rm, help50 will take over, but its output will be on the same line, because the user didn't hit Enter.

screen shot 2016-08-29 at 10 12 20 am

error: conflicting types for 'round'

math.c:9:9: error: conflicting types for 'round'
    int round(int n);
        ^
/usr/include/x86_64-linux-gnu/bits/mathcalls.h:309:14: note: previous declaration is here

expected ';' after top level declarator

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mariopractice6.c  -lcs50 -lm -o mariopractice6
mariopractice6.c:7:15: error: expected ';' after top level declarator
int main(void)
              ^
              ;
1 error generated.
make: *** [mariopractice6] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:4:6: error: expected ';' after top level declarator
int n
     ^
     ;
1 error generated.
make: *** [water] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:4:19: error: expected ';' after top level declarator
int bottles(int n)
                  ^
                  ;
1 error generated.
make: *** [water] Error 1

definitely lost: 4 bytes in 1 blocks

$ cat foo.c
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int *p = malloc(sizeof(int));
    *p = 50;
}
$ clang -ggdb3 foo.c
$ valgrind ./a.out
==49== Memcheck, a memory error detector
==49== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==49== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==49== Command: ./a.out
==49== 
==49== 
==49== HEAP SUMMARY:
==49==     in use at exit: 4 bytes in 1 blocks
==49==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==49== 
==49== LEAK SUMMARY:
==49==    definitely lost: 4 bytes in 1 blocks
==49==    indirectly lost: 0 bytes in 0 blocks
==49==      possibly lost: 0 bytes in 0 blocks
==49==    still reachable: 0 bytes in 0 blocks
==49==         suppressed: 0 bytes in 0 blocks
==49== Rerun with --leak-check=full to see details of leaked memory
==49== 
==49== For counts of detected and suppressed errors, rerun with: -v
==49== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

For this simple output, should focus on:

  • definitely lost: 4 bytes in 1 blocks
  • Rerun with --leak-check=full to see details of leaked memory, so as to recommend as much
valgrind --leak-check=full ./a.out
==53== Memcheck, a memory error detector
==53== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==53== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==53== Command: ./a.out
==53== 
==53== 
==53== HEAP SUMMARY:
==53==     in use at exit: 4 bytes in 1 blocks
==53==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==53== 
==53== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1
==53==    at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==53==    by 0x400546: main (foo.c:6)
==53== 
==53== LEAK SUMMARY:
==53==    definitely lost: 4 bytes in 1 blocks
==53==    indirectly lost: 0 bytes in 0 blocks
==53==      possibly lost: 0 bytes in 0 blocks
==53==    still reachable: 0 bytes in 0 blocks
==53==         suppressed: 0 bytes in 0 blocks
==53== 
==53== For counts of detected and suppressed errors, rerun with: -v
==53== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

With --leak-check=full, above now offers:

  • by 0x400546: main (foo.c:6), but we should probably focus on line below at 0x4C2AB80: malloc..., lest main have called something that called malloc.

CC @glennholloway, @rbowden91

incompatible pointer types passing...

initials.c:20:18: error: incompatible pointer types passing 'string' (aka 'char *') to parameter of type 'string *' (aka 'char **'); take
the address with & [-Werror,-Wincompatible-pointer-types]
get_initials(s,strlen(s));

start including comments atop matchers?

Brian, rather than include sample files and such, which feels like it'll become unwieldy to maintain longer term, especially since some commands will require creating files, etc. in order to simulate... shall we simply start prefixing matchers with multi-line examples of output that they match? E.g., rather than just do

# undefined reference
if ...

we can instead do

# /tmp/ccOsNy8L.o: In function `main':
#3.c:(.text+0xe): undefined reference to `get_string'
# collect2: error: ld returned 1 exit status
# make: *** [3] Error 1
if ...

? Afraid I'm already starting to forget the context for some of the matchers!

Up for tweaking our comments accordingly if this feels compelling?

comparison of constant with boolean expression is always true

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    mario.c  -lcs50 -lm -o mario
mario.c:8:15: error: comparison of constant 23 with boolean expression is always true [-Werror,-Wtautological-constant-out-of-range-compare]
    if (0 < n < 23)
        ~~~~~ ^ ~~
1 error generated.
make: *** [mario] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    caesar.c  -lcs50 -lm -lcrypt -o caesar
caesar.c:31:24: error: comparison of constant 90 with boolean expression is always true [-Werror,-Wtautological-constant-out-of-range-compare]
        if (64<plain[i]<=90)
            ~~~~~~~~~~~^ ~~
1 error generated.
make: *** [caesar] Error 1

Expression is not assignable

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:9:14: error: expression is not assignable
    GetInt() = i;
    ~~~~~~~~ ^
1 error generated.
make: *** [water] Error 1

/review inputs 71, 492, 493, 1106, 1354, 1367, 1724, 2842, 2964, 3016, 3325, 3734, 4811, 4832, 4833, 4843, 5063.

preserve color in clang's output

I wonder if we can easily capture clang's ANSI color so that, when the server spits it back out, a student sees clang's colorized output still, even while our server-side matchers throw away any ANSI codes before doing regex-matching?

Our own helpful output, meanwhile, could then be displayed in some standard color of our own, or in inverse or perhaps as just gray text?

http://pueblo.sourceforge.net/doc/manual/ansi_color_codes.html

detect missing stdlib.h for malloc specifically

foo.c:5:14: warning: implicitly declaring library function 'malloc' with type 'void *(unsigned long)'
    int *p = malloc(sizeof(int));
             ^
foo.c:5:14: note: please include the header <stdlib.h> or explicitly provide a declaration for 'malloc'
1 warning generated.

expected function body after function declarator

clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:4:16: error: expected function body after function declarator
int main (void)
               ^
1 error generated.
make: *** [water] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:5:1: error: expected function body after function declarator
while (n>0)
^
1 error generated.
make: *** [water] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    water.c  -lcs50 -lm -o water
water.c:6:1: error: expected function body after function declarator
do
^
1 error generated.
make: *** [water] Error 1
clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow    caesar.c  -lcs50 -lm -lcrypt -o caesar
caesar.c:7:1: error: expected function body after function declarator
if (argc == 2)
^
1 error generated.
make: *** [caesar] Error 1

ensure entire Reviewed TD is clickable

For efficiency, mind making entire td clickable in the Reviewed column? Odds are you can use a <label for=""> within the td and ensure that it's a block element.

HTTP 500 occasionally

This error starts to recur:

App 116 stderr: ERROR [application] Exception on / [POST]
App 116 stderr: Traceback (most recent call last):
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1988, in wsgi_app
App 116 stderr:     response = self.full_dispatch_request()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1641, in full_dispatch_request
App 116 stderr:     rv = self.handle_user_exception(e)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1544, in handle_user_exception
App 116 stderr:     reraise(exc_type, exc_value, tb)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/_compat.py", line 33, in reraise
App 116 stderr:     raise value
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1639, in full_dispatch_request
App 116 stderr:     rv = self.dispatch_request()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1625, in dispatch_request
App 116 stderr:     return self.view_functions[rule.endpoint](**req.view_args)
App 116 stderr:   File "/srv/www/application.py", line 56, in index
App 116 stderr:     model.log(request.form.get("cmd"), request.form.get("username"), request.form.get("script"), after)
App 116 stderr:   File "/srv/www/model.py", line 20, in log
App 116 stderr:     session.commit()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 801, in commit
App 116 stderr:     self.transaction.commit()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 390, in commit
App 116 stderr:     self._assert_active(prepared_ok=True)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 214, in _assert_active
App 116 stderr:     % self._rollback_exception
App 116 stderr: sqlalchemy.exc.InvalidRequestError: This Session's transaction has been rolled back due to a previous exception during flush. To begin a new transaction
with this Session, first issue Session.rollback(). Original exception was: 'latin-1' codec can't encode character '\u2018' in position 44: ordinal not in range(256)
App 116 stderr:

After this initial error:

App 116 stderr: [2016-09-09 20:45:52,134] ERROR in app: Exception on / [POST]
App 116 stderr: Traceback (most recent call last):
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1988, in wsgi_app
App 116 stderr:     response = self.full_dispatch_request()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1641, in full_dispatch_request
App 116 stderr:     rv = self.handle_user_exception(e)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1544, in handle_user_exception
App 116 stderr:     reraise(exc_type, exc_value, tb)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/_compat.py", line 33, in reraise
App 116 stderr:     raise value
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1639, in full_dispatch_request
App 116 stderr:     rv = self.dispatch_request()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/flask/app.py", line 1625, in dispatch_request
App 116 stderr:     return self.view_functions[rule.endpoint](**req.view_args)
App 116 stderr:   File "/srv/www/application.py", line 60, in index
App 116 stderr:     model.log(request.form.get("cmd"), request.form.get("username"), request.form.get("script"), None)
App 116 stderr:   File "/srv/www/model.py", line 24, in log
App 116 stderr:     session.commit()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 801, in commit
App 116 stderr:     self.transaction.commit()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 392, in commit
App 116 stderr:     self._prepare_impl()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 372, in _prepare_impl
App 116 stderr:     self.session.flush()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2019, in flush
App 116 stderr:     self._flush(objects)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2137, in _flush
App 116 stderr:     transaction.rollback(_capture_exception=True)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/langhelpers.py", line 60, in __exit__
App 116 stderr:     compat.reraise(exc_type, exc_value, exc_tb)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/compat.py", line 186, in reraise
App 116 stderr:     raise value
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/session.py", line 2101, in _flush
App 116 stderr:     flush_context.execute()
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/unitofwork.py", line 373, in execute
App 116 stderr:     rec.execute(self)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/unitofwork.py", line 532, in execute
App 116 stderr:     uow
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/persistence.py", line 174, in save_obj
App 116 stderr:     mapper, table, insert)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/orm/persistence.py", line 800, in _emit_insert_statements
App 116 stderr:     execute(statement, params)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 914, in execute
App 116 stderr:     return meth(self, multiparams, params)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/sql/elements.py", line 323, in _execute_on_connection
App 116 stderr:     return connection._execute_clauseelement(self, multiparams, params)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1010, in _execute_clauseelement
App 116 stderr:     compiled_sql, distilled_params
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1146, in _execute_context
App 116 stderr:     context)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1344, in _handle_dbapi_exception
App 116 stderr:     util.reraise(*exc_info)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/util/compat.py", line 186, in reraise
App 116 stderr:     raise value
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/base.py", line 1139, in _execute_context
App 116 stderr:     context)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/sqlalchemy/engine/default.py", line 450, in do_execute
App 116 stderr:     cursor.execute(statement, parameters)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/MySQLdb/cursors.py", line 207, in execute
App 116 stderr:     args = tuple(map(db.literal, args))
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/MySQLdb/connections.py", line 304, in literal
App 116 stderr:     s = self.escape(o, self.encoders)
App 116 stderr:   File "/usr/local/lib/python3.4/dist-packages/MySQLdb/connections.py", line 226, in unicode_literal
App 116 stderr:     return db.literal(str(u).encode(unicode_literal.charset))
App 116 stderr: UnicodeEncodeError: 'latin-1' codec can't encode character '\u2018' in position 44: ordinal not in range(256)

tabindex on Reviewed column

Let's make each td in the Reviewed column have a tabindex of i, so that we can easily table down the table and check boxes with the space bar?

show only a subset of input along with output?

So I've been thinking about whether there's a better way to display help50's output. At the moment, we display the entirety of its input, below which, in yellow, is its output.

But I wonder if we should start showing only the first n lines of input, where n - 1 is the (last) line we matched. That'd shorten total output in many cases. And we could also start to highlight substrings in the input (e.g., filenames, line numbers, portions of error messages).

Separately, we currently output lines of output, adding \ns irrespective of screen width. Am thinking we should start outputting "paragraphs" instead and let them wrap naturally.

Thoughts? Can we produce better output?

help50 mv (and similar)

$ touch foo
$ touch bar
$ mv foo bar
mv: overwrite ‘bar’?

If someone wanted help understanding the above message, presumably we would want them to be able to execute help50 mv foo bar in order to produce the output from the matcher in mv.py.

However, when I actually execute that, I get a Sorry, not sure how to help!, and the mv command overwrites bar without prompting.

My guess is that since we have mv aliased to mv -i: when help50 is called, it's running mv without the -i flag, triggering the overwrite without prompting the user, and then not POSTing any output to help50's server. Can/should we do anything about that?

(I'm getting analogous results with cp and rm)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.