/* * sc_parse.c * * Copyright © 2013-2014 Thomas White * * This file is part of Colloquium. * * Colloquium is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "sc_parse.h" struct _scblock { char *name; char *options; char *contents; SCBlock *next; SCBlock *prev; SCBlock *child; struct frame *fr; }; SCBlock *sc_block_new() { SCBlock *bl; bl = calloc(1, sizeof(SCBlock)); if ( bl == NULL ) return NULL; return bl; } SCBlock *sc_block_next(const SCBlock *bl) { return bl->next; } SCBlock *sc_block_child(const SCBlock *bl) { return bl->child; } const char *sc_block_name(const SCBlock *bl) { return bl->name; } const char *sc_block_options(const SCBlock *bl) { return bl->options; } const char *sc_block_contents(const SCBlock *bl) { return bl->contents; } struct frame *sc_block_frame(const SCBlock *bl) { return bl->fr; } void sc_block_set_frame(SCBlock *bl, struct frame *fr) { bl->fr = fr; } /* 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 *bln = sc_block_new(); if ( bln == NULL ) return NULL; 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; } /* Frees "bl" and all its children, and links it out of its chain */ void sc_block_free(SCBlock *bl) { if ( bl->child != NULL ) { SCBlock *ch = bl->child; while ( ch != NULL ) { sc_block_free(ch); ch = ch->next; } } free(bl); } static void recursive_show_sc_blocks(const char *prefix, const SCBlock *bl) { while ( bl != NULL ) { show_sc_block(bl, prefix); bl = bl->next; } } void show_sc_block(const SCBlock *bl, const char *prefix) { 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); } } void show_sc_blocks(const SCBlock *bl) { recursive_show_sc_blocks("", bl); } static int get_subexpr(const char *sc, char *bk, char **pcontents, int *err) { size_t ml; int i; int bct = 1; int found = 0; char *contents; *err = 0; ml = strlen(sc); contents = malloc(ml+1); if ( contents == NULL ) { *err = -1; return 0; } *pcontents = contents; for ( i=0; ichild = sc_parse(contents); free(bl->contents); bl->contents = NULL; } else { tbuf[j++] = sc[i++]; } } while ( i 0 ) { /* Leftover buffer is empty? */ if ( (j==1) && (tbuf[0]=='\0') ) return bl; tbuf[j] = '\0'; 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 blf; } void sc_delete_text(SCBlock *b1, int p1, SCBlock *b2, int p2) { printf("Deleting from %p/%i to %p/%i\n", b1, p1, b2, p2); }