correct jump management
authorLaurent Mazet <laurent.mazet@thalesgroup.com>
Wed, 20 Dec 2023 16:10:52 +0000 (17:10 +0100)
committerLaurent Mazet <laurent.mazet@thalesgroup.com>
Wed, 20 Dec 2023 16:10:52 +0000 (17:10 +0100)
bf.c

diff --git a/bf.c b/bf.c
index be9c11f2e219bb8a213c9775241533edd2671daf..c71b46785fcc047d10da40120bcf3c91b7db1917 100644 (file)
--- a/bf.c
+++ b/bf.c
@@ -14,7 +14,8 @@
 /* macros */
 
 #define BUFSIZE 256
-#define MEMSIZE 8
+#define MAXJUMP 4
+#define MEMSIZE 10
 
 /* type definition */
 
@@ -23,6 +24,8 @@
 char *progname = NULL;
 int p = 0;
 char mem[MEMSIZE] = {0};
+int j = 0;
+int jump[MAXJUMP] = {0};
 
 /* help function */
 
@@ -44,9 +47,13 @@ int usage (int ret)
 int process (char *buffer, int nb, FILE *out) {
     int i;
 
-    for (i = 0; (i < nb) && (buffer[i] != 0); i++) {
+    for (i = 0; i < nb; i++) {
+        if (buffer[i] == 0) {
+            break;
+        }
+
+        VERBOSE (DEBUG, fprintf (stderr, "%s: p=%d, buffer='%s', memory=[ ", progname, p, buffer + i); int _i; for (_i = 0; _i < MEMSIZE; _i++) fprintf (stderr," %d", mem[_i]); fprintf (stderr," ]\n"));
 
-        VERBOSE (DEBUG, fprintf (stderr, "%s: read '%c' (%u)\n", progname, buffer[i], buffer[i]));
         switch (buffer[i]) {
             case '>': /* increase pointer */
                 p++;
@@ -88,6 +95,10 @@ int process (char *buffer, int nb, FILE *out) {
                 }
                 break;
             case '[': /* jump to right bracket if pointer is set to 0 */
+                if ((p < 0) || (p >= MEMSIZE)) {
+                    VERBOSE (ERROR, fprintf (stderr, "%s: invalid address (%d)\n", progname, p));
+                    return 1;
+                }
                 if (mem[p] == 0) {
                     int bracket = 1;
                     while ((++i < nb) && (bracket > 0)) {
@@ -97,14 +108,21 @@ int process (char *buffer, int nb, FILE *out) {
                         VERBOSE (ERROR, fprintf (stderr, "%s: brace not closed\n", progname));
                         return 1;
                     }
+                    i--;
                 } else {
-                    return process (buffer + i + 1, nb - i - 1, out);
+                    if (j >= MAXJUMP) {
+                        VERBOSE (ERROR, fprintf (stderr, "%s: too many jump\n", progname));
+                        return 1;
+                    }
+                    jump[j++] = i;
                 }
                 break;
             case ']': /* jump to left bracket if pointer is different to 0 */
-                if (mem[p] != 0) {
-                    i = -1;
+                if (j <= 0) {
+                    VERBOSE (ERROR, fprintf (stderr, "%s: can't jump back\n", progname));
+                    return 1;
                 }
+                i = jump[--j] - 1;
                 break;
             case ' ':
             case '\t':
@@ -217,7 +235,9 @@ int main (int argc, char *argv[])
         }
 
         /* close input file */
-        fclose (fid);
+        if (fid != stdin) {
+            fclose (fid);
+        }
         VERBOSE (DEBUG, fprintf (stderr, "%s: read %d bytes\n", progname, size + n - BUFSIZE));
     } else {
         VERBOSE (DEBUG, fprintf (stderr, "%s: prog %d bytes\n", progname, size -1));
@@ -236,10 +256,13 @@ int main (int argc, char *argv[])
 
     /* main process */
     int rc = process (buffer, size, fid);
-    VERBOSE (INFO, fprintf (stdout, "\nmemory:"); int _i; for (_i = 0; _i < MEMSIZE; _i++) fprintf (stdout," %d", mem[_i]); fprintf (stdout,"\n"));
 
     /* close output file */
-    fclose (fid);
+    if (fid != stdout) {
+        fclose (fid);
+    }
+
+    VERBOSE (INFO, fprintf (stdout, "\nmemory:"); int _i; for (_i = 0; _i < MEMSIZE; _i++) fprintf (stdout," %d", mem[_i]); fprintf (stdout,"\n"));
 
     return rc;
 }
@@ -252,12 +275,13 @@ int main (int argc, char *argv[])
 // test: echo ">>." | bf.exe -o error/error.b 2>&1 | grep "can't open" | grep -q "writing"
 // test: echo '+++>++>>-<--' | bf.exe -v2 | grep -q "memory: 3 2 -2 -1 0"
 // test: bf.exe -e '+++>++>>-<--' -v2 | grep -q "memory: 3 2 -2 -1 0"
+// test: bf.exe -m "51 50 49" -e '.>.>.' |grep -q "321"
 // test: echo '++++++++++[>+++++++>++++++++++>+++>+<<<<-]>++.>+.+++++++..+++.>++.<<+++++++++++++++.>.+++.------.--------.>+.>.' | bf.exe -v1 | grep -q "Hello World!"
 // test: echo '++++++++++[>+>+++>+++++++>++++++++++<<<<-]>>>++++++++++++++.>+++++++++++++++++.<<++.>+++++++++++++.>--.<<.>+++.+.--.>----.++++++.+.<++.>----.++.<<.>>+.-------.<<.>>++.<.>+++++.<<.>-.+.<.>---.>---.<-.++++++++.>----.<---.>+++++++.<---.++++++++.' | bf.exe -v1 | grep -q "Tu as decouvert un peu de brainfuck"
 // test: echo -e "123\0" | bf.exe -e ',[>,]' -v2 | grep -q "memory: 49 50 51 0"
-// test: echo -e "43\0" | bf.exe -e ',>++++++[<-------->-],[<+>-]<.' -v1 | grep -q 7
-
-// test: echo -e "32\0" | bf.exe -e ',>,>>++++++++++++++++[-<+++<---<--->>>]<<[<[>>+>+<<<-]>>>[<<<+>>>-]<<-]>.' -v1 | grep -q 6
-// test: echo -e "32\0" | bf.exe -e ',>,[->>+<<]+<[->>>[>>>>>+<<<<<->+<<]<[>]>>>>>[-<<->>>>>>>]<[>]<<<<<<]>[>>>>->]<<<<<<[-]>[-]>>[-]>.' -v1 | grep -q 3
+// test: echo -e "4+3\0" | bf.exe -e ',>++++++[<-------->-],,[<+>-]<.' -v1 | grep -q 7
+// test: echo -e "1+7\0" | bf.exe -e ',>++++++[<-------->-],,[<+>-]<.' -v1 | grep -q 8
+// test: echo -e "3*2\0" | bf.exe -e ',>,,>++++++++[<------<------>>-]<<[>[>+>+<<-]>>[<<+>>-]<<<-]>>>++++++[<++++++++>-]<.' -v1 | grep -q 6
+// test: echo -e "1*7\0" | bf.exe -e ',>,,>++++++++[<------<------>>-]<<[>[>+>+<<-]>>[<<+>>-]<<<-]>>>++++++[<++++++++>-]<.' -v1 | grep -q 7
 
 /* vim: set ts=4 sw=4 et: */