diff options
-rw-r--r-- | src/sc_parse.c | 129 | ||||
-rw-r--r-- | src/sc_parse.h | 10 | ||||
-rw-r--r-- | tests/storycode_test.c | 32 |
3 files changed, 91 insertions, 80 deletions
diff --git a/src/sc_parse.c b/src/sc_parse.c index 3bb6daf..bb2a5f5 100644 --- a/src/sc_parse.c +++ b/src/sc_parse.c @@ -33,7 +33,7 @@ #include "sc_parse.h" -struct scblock +struct _scblock { char *name; char *options; @@ -42,8 +42,6 @@ struct scblock SCBlock *next; SCBlock *prev; SCBlock *child; - - size_t offset; }; @@ -58,14 +56,34 @@ SCBlock *sc_block_new() } -/* Insert a new block after "bl" */ -SCBlock *sc_block_insert(SCBlock *bl) +/* Insert a new block after "bl". "name", "options" and "contents" + * will not be copied. Returns the block just created, or NULL on error. + * If *blfp points to NULL, it will updated to point at the new block. */ +SCBlock *sc_block_append(SCBlock *bl, char *name, char *opt, char *contents, + SCBlock **blfp) { - SCBlock *bl = sc_block_new(); + SCBlock *bln = sc_block_new(); - /* FIXME: Implementation */ + if ( bln == NULL ) return NULL; - return bl; + bln->name = name; + bln->options = opt; + bln->contents = contents; + bln->child = NULL; + bln->next = NULL; + + if ( bl == NULL ) { + bln->prev = NULL; + } else { + bl->next = bln; + bln->prev = bl; + } + + if ( (blfp != NULL) && (*blfp == NULL) ) { + *blfp = bln; + } + + return bln; } @@ -84,6 +102,35 @@ void sc_block_free(SCBlock *bl) } +static void recursive_show_sc_blocks(const char *prefix, SCBlock *bl) +{ + while ( bl != NULL ) { + + printf("%s", prefix); + if ( bl->name != NULL ) printf("\\%s ", bl->name); + if ( bl->options != NULL ) printf("[%s] ", bl->options); + if ( bl->contents != NULL ) printf("{%s}", bl->contents); + printf("\n"); + + if ( bl->child != NULL ) { + char new_prefix[strlen(prefix)+3]; + strcpy(new_prefix, " "); + strcat(new_prefix, prefix); + recursive_show_sc_blocks(new_prefix, bl->child); + } + + bl = bl->next; + + } +} + + +void show_sc_blocks(SCBlock *bl) +{ + recursive_show_sc_blocks("", bl); +} + + static int get_subexpr(const char *sc, char *bk, char **pcontents, int *err) { size_t ml; @@ -191,13 +238,13 @@ static size_t read_block(const char *sc, char **pname, char **options, SCBlock *sc_parse(const char *sc) { SCBlock *bl; + SCBlock *blf = NULL; char *tbuf; - size_t len, i, j, start; + size_t len, i, j; if ( sc == NULL ) return NULL; - bl = sc_block_new(); - if ( bl == NULL ) return NULL; + bl = NULL; len = strlen(sc); tbuf = malloc(len+1); @@ -206,56 +253,47 @@ SCBlock *sc_parse(const char *sc) return NULL; } - i = 0; j = 0; start = 0; + i = 0; j = 0; do { if ( sc[i] == '\\' ) { int err; char *name = NULL; - char *options = NULL; + char *opt = NULL; char *contents = NULL; - if ( (blockname == NULL) && (j != 0) ) { + if ( j != 0 ) { tbuf[j] = '\0'; - if ( sc_block_list_add(bl, i, NULL, NULL, - strdup(tbuf)) ) - { - fprintf(stderr, - "Failed to add block.\n"); - sc_block_list_free(bl); + bl = sc_block_append(bl, NULL, NULL, + strdup(tbuf), &blf); + if ( bl == NULL ) { + fprintf(stderr, "Block add failed.\n"); + sc_block_free(blf); free(tbuf); return NULL; } j = 0; } - i += read_block(sc+i+1, &name, &options, &contents, - &err); + i += read_block(sc+i+1, &name, &opt, &contents, &err); if ( err ) { printf("Parse error\n"); - sc_block_list_free(bl); + sc_block_free(blf); free(tbuf); return NULL; } - if ( (blockname == NULL) - || ((blockname != NULL) && !strcmp(blockname, name)) ) - { - if ( sc_block_list_add(bl, i, name, options, - contents) ) - { - fprintf(stderr, - "Failed to add block.\n"); - sc_block_list_free(bl); - free(tbuf); - return NULL; - } + bl = sc_block_append(bl, name, opt, contents, &blf); + if ( bl == NULL ) { + fprintf(stderr, "Block add failed.\n"); + sc_block_free(blf); + free(tbuf); + return NULL; } - - /* Start of the next block */ - start = i; - + bl->child = sc_parse(contents); + free(bl->contents); + bl->contents = NULL; } else { @@ -265,22 +303,21 @@ SCBlock *sc_parse(const char *sc) } while ( i<len ); /* Add final block, if it exists */ - if ( (blockname == NULL) && (j > 0) ) { + if ( j > 0 ) { /* Leftover buffer is empty? */ if ( (j==1) && (tbuf[0]=='\0') ) return bl; tbuf[j] = '\0'; - if ( sc_block_list_add(bl, start, NULL, NULL, tbuf) ) - { - fprintf(stderr, - "Failed to add block.\n"); - sc_block_list_free(bl); + bl = sc_block_append(bl, NULL, NULL, tbuf, &blf); + if ( bl == NULL ) { + fprintf(stderr, "Block add failed.\n"); + sc_block_free(blf); free(tbuf); return NULL; } j = 0; } - return bl; + return blf; } diff --git a/src/sc_parse.h b/src/sc_parse.h index f82fca6..23bba89 100644 --- a/src/sc_parse.h +++ b/src/sc_parse.h @@ -29,13 +29,9 @@ typedef struct _scblock SCBlock; -struct scblock *sc_block_list_first(SCBlockList *bl, - SCBlockListIterator **piter); -struct scblock *sc_block_next(SCBlockList *bl, SCBlockListIterator *iter); +extern SCBlock *sc_parse(const char *sc); +extern void sc_block_free(SCBlock *bl); -extern SCBlockList *sc_find_blocks(const char *sc, const char *blockname); -extern void sc_block_list_free(SCBlockList *bl); - -extern char *remove_blocks(const char *in, const char *blockname); +extern void show_sc_blocks(SCBlock *bl); #endif /* SC_PARSE_H */ diff --git a/tests/storycode_test.c b/tests/storycode_test.c index 524fe19..7d73c41 100644 --- a/tests/storycode_test.c +++ b/tests/storycode_test.c @@ -32,41 +32,19 @@ static int test_sc(const char *tt) { - SCBlockList *bl; - SCBlockListIterator *iter; - struct scblock *b; + SCBlock *bl; printf("'%s' ->\n", tt); - bl = sc_find_blocks(tt, "bg"); + bl = sc_parse(tt); if ( bl == NULL ) { - printf("Failed to find blocks.\n"); + printf("Failed to parse SC\n"); return 1; } - for ( b = sc_block_list_first(bl, &iter); - b != NULL; - b = sc_block_list_next(bl, iter) ) - { - printf(" \\%s [%s] {%s}\n", b->name, b->options, b->contents); - } - sc_block_list_free(bl); - - printf("->\n"); - bl = sc_find_blocks(tt, NULL); + show_sc_blocks(bl); - if ( bl == NULL ) { - printf("Failed to find blocks.\n"); - return 1; - } - - for ( b = sc_block_list_first(bl, &iter); - b != NULL; - b = sc_block_list_next(bl, iter) ) - { - printf(" \\%s [%s] {%s}\n", b->name, b->options, b->contents); - } - sc_block_list_free(bl); + sc_block_free(bl); return 0; } |