diff options
Diffstat (limited to 'memedit.y')
-rw-r--r-- | memedit.y | 360 |
1 files changed, 360 insertions, 0 deletions
diff --git a/memedit.y b/memedit.y new file mode 100644 index 0000000..07edb13 --- /dev/null +++ b/memedit.y @@ -0,0 +1,360 @@ +/* FPGAedit */ + +%{ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <ctype.h> + +extern int errno; +extern FILE *fhan; +extern int debug; + +typedef struct variable { + struct variable *next; + char *name; + int val; +} variable; + +int in_line = 0; +#define LINELEN 16 +int write_len; +variable *vlist; + +void set_variable (char *param, int val); +int get_variable (char *param); +void hex_output (int offset, int len, int count); +void print_help (void); + +extern void yyerror (const char *s); +extern int zzlex (void); +int yylex (void); +%} + +%union { +long val; +char *tptr; +} + +%left <val> NUM +%left <val> ADD +%left <val> SUB +%left <val> MUL +%left <val> DIV +%left <val> NEG +%left <val> MOD +%left <val> RSHIFT +%left <val> LSHIFT +%left <val> OBRA +%left <val> CBRA +%left <tptr> NAME +%left <val> OPEN +%left <val> CLOSE +%left <val> MD +%left <val> MM +%left <val> EQ +%left <val> AT +%token <val> EXIT +%token <val> HELP +%right <val> CR + +%type <val> num + +%% /* FPGAedit Grammar */ + +input: /* empty */ + | input line +; + +line: CR + | open CR + | close CR + | EXIT CR { exit(EXIT_SUCCESS); } + | HELP CR { print_help(); } + | NAME CR { printf ("%s = %d\n", $1, get_variable($1)); free($1); } + | mem CR { printf ("\n"); } + | NAME EQ num CR { set_variable ($1, $3); free($1); } + | NAME EQ MD num CR { + if (fhan) + { + if (fseek (fhan, $4, SEEK_SET) == -1) + printf ("set offset %ld failed\n", $4); + else + { + unsigned int c = 0; + + fread(&c, $3, 1, fhan); + set_variable ($1, c); + free($1); + } + } + else printf ("please open file\n"); + } + | error +; + +open: OPEN { printf ("open <filename>\n"); } + | OPEN NAME { + if (fhan) fclose (fhan); + fhan = fopen($2, "r+"); + if (!fhan) + printf ("open >%s< failed\n%s\n", $2, strerror(errno)); + free ($2); + } +; + +close: CLOSE { + if (fhan) { + fclose (fhan); fhan = NULL; + } + } +; + +mem: MD { + if (fhan) hex_output (ftell (fhan), $1, 0); + else printf ("please open file\n"); + } + | MD num { hex_output ($2, $1, 0); } + | MD num num { hex_output ($2, $1, ($3 - 1)/16); } + | MD AT num { + if (fhan) + { + if (fseek (fhan, $3, SEEK_SET) == -1) + printf ("set offset %ld failed\n", $3); + else + { + unsigned int c = 0; + + fread(&c, $1, 1, fhan); + hex_output (c, $1, 0); + } + } + else printf ("please open file\n"); + } + | MD AT num num { + if (fhan) + { + if (fseek (fhan, $3, SEEK_SET) == -1) + printf ("set offset %ld failed\n", $3); + else + { + unsigned int c = 0; + + fread(&c, $1, 1, fhan); + hex_output (c, $1, $4); + } + } + else printf ("please open file\n"); + } + | MM { printf ("mm <offset> <value1> [<value2> ...]\n"); } + | mm exp +; + +mm: MM { write_len = $1; if (debug > 3) printf ("write_len = %d\n", write_len);} +; + +exp: num { + if (fhan) { + long offset; + + if (fseek (fhan, $1, SEEK_SET) == -1) + printf ("set offset %ld failed\n", $1); + else { + offset = ftell (fhan); + if (offset%write_len) { + offset -= offset%write_len; + printf ("alligned to 0x%08lx\n", + offset); + fseek (fhan, offset, SEEK_SET); + } + printf ("new values:"); + if (offset%(LINELEN*4)) + printf ("0x%08lx", offset); + } + } + else printf ("please open file\n"); + } + | exp num { + unsigned int c; + long offset; + + c = $2; + if (debug > 3) printf ("write_len = %d\nc = 0x%0x\n", + write_len, c); + + if (fhan) { + offset = ftell (fhan); + if (offset%LINELEN) printf (" "); + else printf ("\n0x%08lx ", offset); + fwrite (&c, write_len, 1, fhan); + fflush (fhan); + fseek(fhan, -write_len, SEEK_CUR); + fread(&c, write_len, 1, fhan); + switch (write_len) { + case 1: c &= 0xff; printf ("%02x", c); break; + case 2: c &= 0xffff; printf ("%04x", c); break; + case 4: printf ("%08x", c); break; + } + } + else if (debug > 3) printf ("fhan == NULL\n"); + } +; + +num: NUM + | num ADD num { $$ = $1 + $3; if (debug > 3) printf ("ADD: %ld\n", $$); } + | num SUB num { $$ = $1 - $3; if (debug > 3) printf ("SUB: %ld\n", $$); } + | num MUL num { $$ = $1 * $3; if (debug > 3) printf ("MUL: %ld\n", $$); } + | num DIV num { $$ = $1 / $3; if (debug > 3) printf ("DIV: %ld\n", $$); } + | num MOD num { $$ = $1 % $3; if (debug > 3) printf ("MOD: %ld\n", $$); } + | num RSHIFT num { $$ = $1 >> $3; if (debug > 3) printf ("RSHIFT: %ld\n", $$); } + | num LSHIFT num { $$ = $1 << $3; if (debug > 3) printf ("LSHIFT: %ld\n", $$); } + | OBRA num CBRA { $$ = $2; if (debug > 3) printf ("BRA: %ld\n", $$); } + | NAME { $$ = get_variable ($1); if (debug > 3) printf ("VAR: %ld\n", $$); free($1); } +; + +%% +void print_help (void) { + printf ("\n"); + printf ("open <file> open a file\n"); + printf ("close close currently opened file\n"); + printf ("exit, quit quit\n"); + printf ("help show this help text\n"); + printf ("\n"); + printf ("md [[@]<start> [<end>]] mem display from current position\n"); + printf (" or from <start> to <end>\n"); + printf ("mm <offset> <val1> .. <valN> modify from value <offset>\n"); + printf ("<var> = <expr> set variable <var> to <expr>\n"); + printf ("<var> print variable <var>\n"); + printf ("\n"); + printf ("<var1> add <var2> add variables\n"); + printf ("<var1> sub <var2> substract variables\n"); + printf ("<var1> mul <var2> multiplicate variables\n"); + printf ("<var1> div <var2> divide variables\n"); + printf ("<var1> rshift <var2> shift (or >>)\n"); + printf ("<var1> lshift <var2> shift (or >> or shift)\n"); + printf ("\n"); + printf ("Variables can be entered as decimals (without prefix), hex (prefixed with 0x)\n"); + printf ("oct (0o) or bin (0b). For mm and md byte, word and long word access can be \n"); + printf ("enabled with .b, .w and .l\n"); + printf ("\n"); +} + +void set_variable (char *param, int val) { + variable *l, *tmp; + + if (strncmp (param, "debug", 5) == 0) { + debug = val; + printf ("debug = %d\n", debug); + return; + } + + if (debug > 3) printf ("param = >%s<\n", param); + + for (l = vlist; l; l = l->next) { + if (debug > 3) printf ("l->name = >%s<\n", l->name); + if (strcmp (l->name, param) == 0) { + l->val = val; + return; + } + } + + tmp = calloc (1, sizeof(variable)); + if (!tmp) { + printf ("no mem for variable %s!\n", param); + return; + } + + tmp->name = calloc(1 + strlen(param), sizeof(char)); + if (!tmp->name) { + printf ("no mem for variable %s!\n", param); + free(tmp); + return; + } + strcpy(tmp->name, param); + tmp->val = val; + tmp->next = vlist; + + vlist = tmp; +} + +int get_variable (char *param) { + int v = 0; + variable *l; + + if (debug > 3) printf ("param = >%s<\n", param); + + for (l = vlist; l; l = l->next) { + if (debug > 3) printf ("l->name = >%s<\n", l->name); + if (strcmp (l->name, param) == 0) { + v = l->val; + break; + } + } + return v; +} + +void hex_output (int offset, int len, int count) { + unsigned int c; + int i=0, j, t; + unsigned char linebuf[LINELEN]; + + if (!fhan) { + printf ("please open file\n"); + return; + } + + if (fseek (fhan, offset, SEEK_SET) != 0) { + printf ("set offset %d failed\n", offset); + return; + } + + for (t = 0; t <= count; t++) { + unsigned int *lineint = (unsigned int *)linebuf; + unsigned short *lineshort = (unsigned short *)linebuf; + + printf ("%08x: ", offset + t*LINELEN); + switch (len) { + case 1: + for (i = 0; i < LINELEN; i++) { + c = 0; + if (fread (&c, 1, 1, fhan) != 1) break; + printf ("%02x ", c); + linebuf[i] = c; + } + break; + case 2: + for (i = 0; i < LINELEN; i+=2) { + c = 0; + if (fread (&c, 2, 1, fhan) != 1) break; + printf ("%04x ", c); + *lineshort++ = c; + } + break; + + case 4: + for (i = 0; i < LINELEN; i+=4) { + c = 0; + if (fread (&c, 4, 1, fhan) != 1) break; + printf ("%08x ", c); + *lineint++ = c; + } + break; + } + + for (j = 0; j < i; j++) { + if(isprint(linebuf[j])) + printf("%c",linebuf[j]); + else + printf("."); + } + printf ("\n"); + if(i < LINELEN) + return; + } +} + +int yylex (void) { + in_line++; + return zzlex (); +} |