diff options
Diffstat (limited to 'deps/libmscgen/mscgen_msc.c')
-rw-r--r-- | deps/libmscgen/mscgen_msc.c | 804 |
1 files changed, 804 insertions, 0 deletions
diff --git a/deps/libmscgen/mscgen_msc.c b/deps/libmscgen/mscgen_msc.c new file mode 100644 index 0000000..a18e261 --- /dev/null +++ b/deps/libmscgen/mscgen_msc.c @@ -0,0 +1,804 @@ +/*************************************************************************** + * + * $Id: msc.c 175 2011-02-06 21:07:43Z Michael.McTernan $ + * + * The message sequence parser ADT. + * Copyright (C) 2009 Michael C McTernan, Michael.McTernan.2001@cs.bris.ac.uk + * + * This program 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + ***************************************************************************/ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> +#include <string.h> +#include <stdlib.h> +#include "mscgen_config.h" +#include "mscgen_safe.h" +#include "mscgen_msc.h" + +/*************************************************************************** + * Structures + ***************************************************************************/ + +struct MscEntityTag +{ + char *label; + struct MscAttribTag *attr; + struct MscEntityTag *next; +}; + +struct MscEntityListTag +{ + unsigned int elements; + struct MscEntityTag *head, *tail; +}; + +struct MscArcTag +{ + char *src, *dst; + MscArcType type; + unsigned int inputLine; + struct MscAttribTag *attr; + struct MscArcTag *next; +}; + +struct MscArcListTag +{ + unsigned int elements; + unsigned int parElements; + struct MscArcTag *head, *tail; +}; + + +struct MscAttribTag +{ + MscAttribType type; + char *value; + struct MscAttribTag *next; +}; + +struct MscOptTag +{ + MscOptType type; + char *value; + struct MscOptTag *next; +}; + +struct MscTag +{ + struct MscOptTag *optList; + struct MscEntityListTag *entityList; + struct MscArcListTag *arcList; + + struct MscArcTag *nextArc; + struct MscEntityTag *nextEntity; +}; + +/*************************************************************************** + * Local Functions + ***************************************************************************/ + +/** Find come attribute in an attribute list. + * + * \param[in] attr Head of the linked list to search. + * \param[in] a The attribute type to find. + * \retval NULL If the attribute was not found or the passed list was NULL. + */ +static const char *findAttrib(const struct MscAttribTag *attr, MscAttribType a) +{ + while(attr != NULL && attr->type != a) + { + attr = attr->next; + } + + if(attr != NULL) + { + return attr->value; + } + else + { + return NULL; + } +} + + +/** Free the memory underlying a list of attributes. + */ +static void freeAttribList(struct MscAttribTag *attr) +{ + while(attr) + { + struct MscAttribTag *next = attr->next; + free(attr->value); + free(attr); + attr = next; + } +} + +/*************************************************************************** + * Option Functions + ***************************************************************************/ + +/* Allocate some option and set it's value. + */ +struct MscOptTag *MscAllocOpt(MscOptType type, + char *value) +{ + struct MscOptTag *a = malloc_s(sizeof(struct MscOptTag)); + + a->type = type; + a->value = value; + a->next = NULL; + + return a; +} + +/* Link one or two options together. + */ +struct MscOptTag *MscLinkOpt(struct MscOptTag *head, + struct MscOptTag *newHead) +{ + struct MscOptTag *tail = newHead; + + assert(newHead); + + /* Find the end of the list */ + while(tail->next) + { + tail = tail->next; + } + + tail->next = head; + return newHead; +} + +/* MscPrettyOptType + * Returns a string that is the human readable form of the option + * code passed to the function. + */ +const char *MscPrettyOptType(MscOptType t) +{ + switch(t) + { + case MSC_OPT_HSCALE: return "hscale"; + case MSC_OPT_WIDTH: return "width"; + case MSC_OPT_ARCGRADIENT: return "arcgradient"; + default: + return "unknown"; + } +} + +struct MscOptTag *MscFindOpt(struct MscOptTag *list, + MscOptType type) +{ + struct MscOptTag *elem = list; + + while(elem && elem->type != type) + { + elem = elem->next; + } + + if(elem && elem->type == type) + { + return elem; + } + + return NULL; +} + +void MscPrintOptList(struct MscOptTag *list) +{ + struct MscOptTag *elem = list; + + while(elem) + { + printf("%p: %s=%s\n", elem, MscPrettyOptType(elem->type), elem->value); + elem = elem->next; + } +} + +/*************************************************************************** + * Entity Functions + ***************************************************************************/ + +/* MscAllocEntity + * Allocate some entity and set it's name. + */ +struct MscEntityTag *MscAllocEntity(char *entityName) +{ + struct MscEntityTag *e = malloc_s(sizeof(struct MscEntityListTag)); + + e->label = entityName; + e->attr = NULL; + e->next = NULL; + + return e; +} + + +/* MscLinkEntity + * Link some entity onto a list, possibly producing a new head element. + */ +struct MscEntityListTag *MscLinkEntity(struct MscEntityListTag *list, + struct MscEntityTag *elem) +{ + /* Check if the list has been allocated or not */ + if(list == NULL) + { + list = zalloc_s(sizeof(struct MscEntityListTag)); + } + + /* Check for an empty list */ + if(list->head == NULL) + { + list->head = list->tail = elem; + } + else + { + /* Add to tail */ + list->tail->next = elem; + list->tail = elem; + } + + /* Increment count of elements */ + list->elements++; + + return list; +} + + +void MscPrintEntityList(struct MscEntityListTag *list) +{ + struct MscEntityTag *elem = list->head; + + while(elem) + { + printf("%p: %s\n", elem, elem->label); + MscPrintAttrib(elem->attr); + elem = elem->next; + } +} + +/*************************************************************************** + * Arc Functions + ***************************************************************************/ + +/* MscAllocArc + * Allocate an arc, filling in the src and dst entities. + */ +struct MscArcTag *MscAllocArc(char *srcEntity, + char *dstEntity, + MscArcType type, + unsigned int inputLine) +{ + struct MscArcTag *a = malloc_s(sizeof(struct MscArcTag)); + + /* A discontinuity arcs are not between entities */ + if(type == MSC_ARC_DISCO) + { + assert(srcEntity == NULL && dstEntity == NULL); + } + + a->inputLine = inputLine; + a->src = srcEntity; + a->dst = dstEntity; + a->type = type; + a->next = NULL; + a->attr = NULL; + + return a; +} + + +/* MscLinkArc + * Link some entity onto a list, possibly producing a new head element. + */ +struct MscArcListTag *MscLinkArc(struct MscArcListTag *list, + struct MscArcTag *elem) +{ + /* Check if the list has been allocated or not */ + if(list == NULL) + { + list = zalloc_s(sizeof(struct MscArcListTag)); + } + + /* Check for an empty list */ + if(list->head == NULL) + { + list->head = list->tail = elem; + } + else + { + /* Add to tail */ + list->tail->next = elem; + list->tail = elem; + } + + /* Increment count of elements */ + list->elements++; + if(elem->type == MSC_ARC_PARALLEL) + { + /* A parallel arc is a place holder, and indicates the next arc + * is on the same line. It also needs to account itself, so subtract + * two here. + */ + list->parElements += 2; + } + + return list; +} + + +/* MscPrintArcList + * Dump and arc list. + */ +void MscPrintArcList(struct MscArcListTag *list) +{ + struct MscArcTag *elem = list->head; + + while(elem) + { + printf("%p: '%s' -> '%s'\n", elem, elem->src, elem->dst); + MscPrintAttrib(elem->attr); + + elem = elem->next; + } +} + + +/*************************************************************************** + * Attribute functions + ***************************************************************************/ + +/* MscAllocAttrib + * Allocate some attribute. + */ +struct MscAttribTag *MscAllocAttrib(MscAttribType type, + char *value) +{ + struct MscAttribTag *a = malloc_s(sizeof(struct MscAttribTag)); + + a->type = type; + a->value = value; + a->next = NULL; + + return a; +} + + +/* MscLinkAttrib + * Link some attributes. The ordering of attributes is semi-important + * so the list is grown from the tail. + */ +struct MscAttribTag *MscLinkAttrib(struct MscAttribTag *head, + struct MscAttribTag *newHead) +{ + struct MscAttribTag *tail = newHead; + + assert(newHead); + + /* Find the end of the list */ + while(tail->next) + { + tail = tail->next; + } + + tail->next = head; + return newHead; +} + + +/* MscArcLinkAttrib + * Attach some attributes to some arc. + */ +void MscArcLinkAttrib(struct MscArcTag *arc, + struct MscAttribTag *att) +{ + if(arc->attr) + { + arc->attr = MscLinkAttrib(arc->attr, att); + } + else + { + arc->attr = att; + } +} + + +/* MscEntityLinkAttrib + * Attach some attributes to some entity. + */ +void MscEntityLinkAttrib(struct MscEntityTag *ent, + struct MscAttribTag *att) +{ + if(ent->attr) + { + ent->attr = MscLinkAttrib(ent->attr, att); + } + else + { + ent->attr = att; + } +} + + +/* MscPrintAttrib + * String a human readable version of the passed attribute list to stdout. + */ +void MscPrintAttrib(const struct MscAttribTag *att) +{ + while(att) + { + printf(" %s = %s\n", MscPrettyAttribType(att->type), att->value); + att = att->next; + } + +} + + +/* MscPrettyAttribType + * Returns a string that is the human readable form of the attribute + * code passed to the function. + */ +const char *MscPrettyAttribType(MscAttribType t) +{ + switch(t) + { + case MSC_ATTR_LABEL: return "label"; + case MSC_ATTR_URL: return "url"; + case MSC_ATTR_ID: return "id"; + case MSC_ATTR_IDURL: return "idurl"; + case MSC_ATTR_LINE_COLOUR: return "linecolour"; + case MSC_ATTR_TEXT_COLOUR: return "textcolour"; + case MSC_ATTR_TEXT_BGCOLOUR: return "textbgcolour"; + case MSC_ATTR_ARC_LINE_COLOUR: return "arclinecolour"; + case MSC_ATTR_ARC_TEXT_COLOUR: return "arctextcolour"; + case MSC_ATTR_ARC_TEXT_BGCOLOUR: return "arctextbgcolour"; + case MSC_ATTR_NO_ARROWS: return "noarrows"; + case MSC_ATTR_BI_ARROWS : return "biarrows"; + default: + return "<unknown>"; + } +} + + +/*************************************************************************** + * MSC Functions + ***************************************************************************/ + +struct MscTag *MscAlloc(struct MscOptTag *optList, + struct MscEntityListTag *entityList, + struct MscArcListTag *arcList) +{ + struct MscTag *m = malloc_s(sizeof(struct MscTag)); + + /* Copy the lists */ + m->optList = optList; + m->entityList = entityList; + m->arcList = arcList; + + /* Reset the iterators */ + MscResetEntityIterator(m); + MscResetArcIterator(m); + + return m; +} + +void MscFree(struct MscTag *m) +{ + struct MscOptTag *opt = m->optList; + struct MscEntityTag *entity = m->entityList->head; + struct MscArcTag *arc = m->arcList->head; + + while(opt) + { + struct MscOptTag *next = opt->next; + + free(opt->value); + free(opt); + + opt = next; + } + + while(entity) + { + struct MscEntityTag *next = entity->next; + + freeAttribList(entity->attr); + free(entity->label); + free(entity); + + entity = next; + } + + while(arc) + { + struct MscArcTag *next = arc->next; + + freeAttribList(arc->attr); + free(arc->dst); + free(arc->src); + free(arc); + + arc = next; + } + + free(m->entityList); + free(m->arcList); + free(m); +} + +void MscPrint(struct MscTag *m) +{ + printf("Option list (%d options)\n", MscGetNumOpts(m)); + MscPrintOptList(m->optList); + + printf("Entity list (%d entities, %d parallel)\n", + MscGetNumEntities(m), MscGetNumParallelArcs(m)); + MscPrintEntityList(m->entityList); + + printf("\nArc list (%d arcs)\n", MscGetNumArcs(m)); + MscPrintArcList(m->arcList); +} + +unsigned int MscGetNumEntities(struct MscTag *m) +{ + return m->entityList->elements; +} + +unsigned int MscGetNumArcs(Msc m) +{ + return m->arcList->elements; +} + +unsigned int MscGetNumParallelArcs(Msc m) +{ + return m->arcList->parElements; +} + +unsigned int MscGetNumOpts(Msc m) +{ + struct MscOptTag *elem = m->optList; + unsigned int count = 0; + + while(elem) + { + count++; + elem = elem->next; + } + + return count; +} + +int MscGetEntityIndex(struct MscTag *m, const char *label) +{ + struct MscEntityTag *entity = m->entityList->head; + int c = 0; + + assert(label); + + while(entity != NULL && strcmp(entity->label, label) != 0) + { + entity = entity->next; + c++; + } + + if(entity == NULL) + { + return -1; + } + else + { + return c; + } +} + +void MscResetEntityIterator(struct MscTag *m) +{ + m->nextEntity = m->entityList->head; +} + +Boolean MscNextEntity(struct MscTag *m) +{ + if(m->nextEntity->next != NULL) + { + m->nextEntity = m->nextEntity->next; + return TRUE; + } + else + { + return FALSE; + } +} + + +const char *MscGetCurrentEntAttrib(struct MscTag *m, MscAttribType a) +{ + const char *r; + + if(!m->nextEntity) + { + return NULL; + } + + r = findAttrib(m->nextEntity->attr, a); + + /* If the entity label was sought but not found, return entity name */ + if(r == NULL && a == MSC_ATTR_LABEL) + { + return m->nextEntity->label; + } + else + { + return r; + } +} + + +const char *MscGetEntAttrib(Msc m, unsigned int entIdx, MscAttribType a) +{ + struct MscEntityTag *entity; + const char *r; + + /* Find the entity */ + entity = m->entityList->head; + while(entIdx > 0 && entity != NULL) + { + entity = entity->next; + entIdx--; + } + + /* Search the attribute list if the entity was found */ + if(entity) + { + r = findAttrib(entity->attr, a); + + /* If the entity label was sought but not found, return entity name */ + if(r == NULL && a == MSC_ATTR_LABEL) + { + return m->nextEntity->label; + } + else + { + return r; + } + } + else + { + /* Entity was not found */ + return NULL; + } +} + + +void MscResetArcIterator(struct MscTag *m) +{ + m->nextArc = m->arcList->head; +} + +Boolean MscNextArc(struct MscTag *m) +{ + if(m->nextArc->next != NULL) + { + m->nextArc = m->nextArc->next; + return TRUE; + } + else + { + return FALSE; + } +} + +const char *MscGetCurrentArcSource(struct MscTag *m) +{ + return m->nextArc ? m->nextArc->src : NULL; +} + +const char *MscGetCurrentArcDest(struct MscTag *m) +{ + return m->nextArc ? m->nextArc->dst : NULL; +} + +MscArcType MscGetCurrentArcType(struct MscTag *m) +{ + return m->nextArc ? m->nextArc->type : MSC_INVALID_ARC_TYPE; +} + +const char *MscGetCurrentArcAttrib(struct MscTag *m, MscAttribType a) +{ + struct MscAttribTag *attr; + + if(!m->nextArc) + { + return NULL; + } + + attr = m->nextArc->attr; + + while(attr != NULL && attr->type != a) + { + attr = attr->next; + } + + if(attr != NULL) + { + return attr->value; + } + else + { + return NULL; + } + +} + +Boolean MscGetOptAsFloat(struct MscTag *m, MscOptType type, float *const f) +{ + struct MscOptTag *opt = MscFindOpt(m->optList, type); + + if(opt != NULL) + { + *f = (float)atof(opt->value); + return *f != 0.0f; + } + + return FALSE; +} + +unsigned int MscGetCurrentArcInputLine(struct MscTag *m) +{ + if(m->nextArc) + { + return m->nextArc->inputLine; + } + else + { + return 0; + } +} + +Boolean MscGetOptAsBoolean(struct MscTag *m, MscOptType type, Boolean *const b) +{ + struct MscOptTag *opt = MscFindOpt(m->optList, type); + + if(opt != NULL) + { + const char *v = opt->value; + + if(strcasecmp(v, "true") == 0 || strcasecmp(v, "yes") == 0 || + strcasecmp(v, "on") == 0 || strcasecmp(v, "1") == 0) + { + *b = TRUE; + return TRUE; + } + else if(strcasecmp(v, "false") == 0 || strcasecmp(v, "no") == 0 || + strcasecmp(v, "off") == 0 || strcasecmp(v, "0") == 0) + { + *b = FALSE; + return TRUE; + } + else + { + fprintf(stderr, "Warning: Unrecognised boolean option value '%s'. Valid values are 'true',\n" + " 'false', 'yes', 'no', 'on', 'off', '1' and '0'.\n", + v); + return FALSE; + } + } + + return FALSE; +} +/* END OF FILE */ + |