]> cloudbase.mooo.com Git - z180-stamp.git/commitdiff
process_macros: reduce heap usage and fragmentation
authorLeo C <erbl259-lmu@yahoo.de>
Mon, 1 Sep 2014 15:06:58 +0000 (17:06 +0200)
committerLeo C <erbl259-lmu@yahoo.de>
Tue, 2 Sep 2014 12:01:01 +0000 (14:01 +0200)
avr/cli.c
avr/debug.c

index 08e70387df9f7e5518c7e6efc08904f284658a03..b310f793d97eb54d85db24129eecc4bb6996687b 100644 (file)
--- a/avr/cli.c
+++ b/avr/cli.c
@@ -43,114 +43,107 @@ static int cli_parse_line(char *line, char *argv[])
        return nargs;
 }
 
-static void process_macros(const char *input, char *output)
+static
+void append_char(uint_fast8_t pass, char **p, char c)
 {
-       char c, prev;
-       const char *varname_start = NULL;
-#if 0 && (CONFIG_SYS_CBSIZE < __UINT_FAST8_MAX__)
-       uint_fast8_t inputcnt = strlen(input);
-       uint_fast8_t outputcnt = CONFIG_SYS_CBSIZE;
-#else
-       int inputcnt = strlen(input);
-       int outputcnt = CONFIG_SYS_CBSIZE;
-#endif
-       uint_fast8_t state = 0;         /* 0 = waiting for '$'  */
-
-       /* 1 = waiting for '{' */
-       /* 2 = waiting for '}' */
-       /* 3 = waiting for '''  */
-       char *output_start = output;
-
-       debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(input),
-                    input);
-
-       prev = '\0';            /* previous character   */
-
-       while (inputcnt && outputcnt) {
-               c = *input++;
-               inputcnt--;
-
-               if (state != 3) {
-                       /* remove one level of escape characters */
-                       if ((c == '\\') && (prev != '\\')) {
-                               if (inputcnt-- == 0)
-                                       break;
-                               prev = c;
-                               c = *input++;
-                       }
+
+       if (pass) {
+               **p = c;
+       }
+       ++(*p);
+}
+
+static
+char *process_macros(char *input, char *output)
+{
+       char c, prev, *inp, *outp;
+       const char *varname = NULL;
+
+       for(uint_fast8_t pass = 0; pass < 2; pass++)
+       {
+               uint_fast8_t state = 0;         /* 0 = waiting for '$'  */
+               /* 1 = waiting for '{' */
+               /* 2 = waiting for '}' */
+               /* 3 = waiting for ''' */
+
+               if (pass == 0) {
+                       outp = output;
+               } else {
+                       int outputlen = outp - output;
+                       outp = xrealloc(output, outputlen);
+                       output = outp;
                }
 
-               switch (state) {
-               case 0: /* Waiting for (unescaped) $    */
-                       if ((c == '\'') && (prev != '\\')) {
-                               state = 3;
-                               break;
-                       }
-                       if ((c == '$') && (prev != '\\')) {
-                               state++;
-                       } else {
-                               *(output++) = c;
-                               outputcnt--;
-                       }
-                       break;
-               case 1: /* Waiting for (        */
-                       if (c == '{') {
-                               state++;
-                               varname_start = input;
-                       } else {
-                               state = 0;
-                               *(output++) = '$';
-                               outputcnt--;
-
-                               if (outputcnt) {
-                                       *(output++) = c;
-                                       outputcnt--;
+               inp = input;
+               prev = '\0';            /* previous character   */
+
+               debug_parser("[PROCESS_MACROS] INPUT len %d: \"%s\"\n", strlen(inp),
+                            inp);
+
+               while ((c = *inp++) != '\0') {
+
+                       if (state != 3) {
+                               /* remove one level of escape characters */
+                               if ((c == '\\') && (prev != '\\')) {
+                                       if (*inp == '\0')
+                                               break;
+                                       prev = c;
+                                       c = *inp++;
                                }
                        }
-                       break;
-               case 2: /* Waiting for )        */
-                       if (c == '}') {
-                               char envname[CONFIG_SYS_ENV_NAMELEN+1], *envval;
-                               /* Varname # of chars */
-                               uint_fast8_t envcnt = input - varname_start - 1;
-                               if (envcnt > CONFIG_SYS_ENV_NAMELEN)
-                                       envcnt = CONFIG_SYS_ENV_NAMELEN;
-
-                               memcpy(envname, varname_start, envcnt);
-                               envname[envcnt] = '\0';
-
-                               /* Get its value */
-                               envval = getenv(envname);
-
-                               /* Copy into the line if it exists */
-                               if (envval != NULL)
-                                       while ((*envval) && outputcnt) {
-                                               *(output++) = *(envval++);
-                                               outputcnt--;
-                                       }
-                               /* Look for another '$' */
-                               state = 0;
-                       }
-                       break;
-               case 3: /* Waiting for '        */
-                       if ((c == '\'') && (prev != '\\')) {
-                               state = 0;
-                       } else {
-                               *(output++) = c;
-                               outputcnt--;
+
+                       switch (state) {
+                       case 0: /* Waiting for (unescaped) $    */
+                               if ((c == '\'') && (prev != '\\')) {
+                                       state = 3;
+                                       break;
+                               }
+                               if ((c == '$') && (prev != '\\'))
+                                       state++;
+                               else
+                                       append_char(pass, &outp, c);
+                               break;
+                       case 1: /* Waiting for {        */
+                               if (c == '{') {
+                                       state++;
+                                       varname = inp;
+                               } else {
+                                       state = 0;
+                                       append_char(pass, &outp, '$');
+                                       append_char(pass, &outp, c);
+                               }
+                               break;
+                       case 2: /* Waiting for }        */
+                               if (c == '}') {
+                                       /* Terminate variable name */
+                                       *(inp-1) = '\0';
+                                       const char *envval = getenv(varname);
+                                       *(inp-1) = '}';
+                                       /* Copy into the line if it exists */
+                                       if (envval != NULL)
+                                               while (*envval)
+                                                       append_char(pass, &outp, *(envval++));
+                                       /* Look for another '$' */
+                                       state = 0;
+                               }
+                               break;
+                       case 3: /* Waiting for '        */
+                               if ((c == '\'') && (prev != '\\'))
+                                       state = 0;
+                               else
+                                       append_char(pass, &outp, c);
+                               break;
                        }
-                       break;
+                       prev = c;
                }
-               prev = c;
-       }
 
-       if (outputcnt)
-               *output = 0;
-       else
-               *(output - 1) = 0;
+               append_char(pass, &outp, 0);
+       }
 
        debug_parser("[PROCESS_MACROS] OUTPUT len %d: \"%s\"\n",
-                    strlen(output_start), output_start);
+                    strlen(output), output);
+
+       return output;
 }
 
 /**
@@ -174,7 +167,7 @@ static int cli_run_command(const char *cmd, int flag)
        char *cmdbuf;                   /* working copy of cmd          */
        char *token;                    /* start of token in cmdbuf     */
        char *sep;                      /* end of token (separator) in cmdbuf */
-       char *finaltoken;
+       char *finaltoken = NULL;        /* token after macro expansion  */
        char *str;
        char *argv[CONFIG_SYS_MAXARGS + 1];     /* NULL terminated      */
        int argc;
@@ -190,8 +183,7 @@ static int cli_run_command(const char *cmd, int flag)
                return -1;      /* empty command */
 
        cmdbuf = strdup(cmd);
-       finaltoken = xmalloc(CONFIG_SYS_CBSIZE);
-       if (!finaltoken)
+       if (!cmdbuf)
                return -1;      /* not enough memory */
 
        str = cmdbuf;
@@ -231,7 +223,7 @@ static int cli_run_command(const char *cmd, int flag)
                debug_parser("token: \"%s\"\n", token);
 
                /* find macros in this token and replace them */
-               process_macros(token, finaltoken);
+               finaltoken = process_macros(token, finaltoken);
 
                /* Extract arguments */
                argc = cli_parse_line(finaltoken, argv);
index 16df702d0a0949a47bd6c058ca4e844374fa3f0f..47b11b097cc5b51130f460eb760e5d4fd6564231 100644 (file)
@@ -23,7 +23,7 @@ static uint8_t ram_read_byte(const uint8_t *p)
        return *p;
 }
 
-void dump_mem(const uint8_t *startaddr, int len, 
+void dump_mem(const uint8_t *startaddr, int len,
                uint8_t (*readfkt)(const uint8_t *), char *title)
 {
        uint8_t buf[16];
@@ -33,12 +33,12 @@ void dump_mem(const uint8_t *startaddr, int len,
        const uint8_t *addr = (uint8_t *) ((size_t) startaddr & ~0x0f);
        len += pre;
        uint8_t i;
-       
+
        if (title && *title) {
                printf_P(PSTR("%s\n"),title);
                indent = "    ";
        }
-               
+
        while (len) {
                if (len < 16)
                        llen = len;
@@ -100,7 +100,7 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
 //     static const uint8_t *addr;
 //     static uint16_t length = 128;
        uint8_t (*readhow)(const uint8_t *);
-               
+
        (void) cmdtp; (void) flag;
 
        if (argc < 2)
@@ -108,7 +108,7 @@ command_ret_t do_dump_mem(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg
 
        const uint8_t *addr;
        uint16_t length = 128;
-       
+
        if (strchr(argv[0],'r') != NULL)
                readhow = ram_read_byte;
        else if (strchr(argv[0],'e') != NULL)
@@ -182,7 +182,7 @@ command_ret_t do_eep_cp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[
 /*------------------------------------------------------------------------------*/
 
 
-#if 0
+#if 1
 
 struct __freelist {
        size_t sz;
@@ -201,6 +201,8 @@ printfreelist(const char * title)
        int i;
        unsigned int freesum = 0;
 
+/* TODO: printf_P */
+
        if (!__flp) {
                printf("%s no free list\n", title ? title : "");
        } else {
@@ -215,7 +217,7 @@ printfreelist(const char * title)
                        freesum += fp1->sz;
                }
        }
-       
+
        freesum +=  (size_t) STACK_POINTER() - __malloc_margin - (size_t) __brkval;
 
        printf("SP: %04x, __brkval: %04x, Total free: %04u\n",