/* File: nicedump.c * Author: Danielle et Jean Thierry-Mieg (mieg@mrc-lmb.cam.ac.uk) * Copyright (C) J Thierry-Mieg and R Durbin, 1993 * ------------------------------------------------------------------- * Acedb 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt * ------------------------------------------------------------------- * This file is part of the ACEDB genome database package, written by * Richard Durbin (MRC LMB, UK) rd@mrc-lmb.cam.ac.uk, and * Jean Thierry-Mieg (CRBM du CNRS, France) mieg@kaa.cnrs-mop.fr * * Description: * Exported functions: * HISTORY: * Last edited: Mar 8 14:32 2001 (edgrif) * * Lincoln Stein added java dump * * Doug Bigwood and John Barnett changes to handle html format * * Jul 16 00:11 1998 (rd): lots of cleaning up * new timestamps for Java (never used in human or perl) * down looping not recursion * perl layout simplified (no freeOutxy) and IL \n "fix" undone * (it's bug was because of bad interaction with freeOutxy) * removed dumpQueries static because it was always set TRUE - * Java always dumps ATTACHes to recursion level one, * human and perl never do * isModel set correctly for NEW_MODELS * * Dec 8 13:53 1994 (mieg): * Created: Thu Jan 28 13:50:53 1993 (mieg) * CVS info: $Id: nicedump.c,v 1.46 2003/05/15 22:18:34 sienkiew Exp $ *------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include #include #include #include /* for isModel() */ /*************/ /* Defines the output style of xml. */ typedef struct _XmlProcessing { BOOL content ; BOOL class_att ; BOOL value_att ; BOOL all_atts ; } XmlProcessing ; /*************/ static int niceBShuman (ACEOUT dump_out, BS bs, int x, int y) ; static char *niceTextUsual(BS bs) ; static char *niceExpandText(KEY key) ; static void niceBSPerl (ACEOUT dump_out, BS bs, BS bsm, int position, int level) ; static char *niceTextPerl (BS bs) ; static void niceBSXML (ACEOUT dump_out, BS bs, BS bsm, XmlProcessing *style, int position, int level, char *enclosing_class, int enclosing_level) ; static char* niceTextXML(BS bs, XmlProcessing *style, char **end_tag, char **enclosing_class, int *enclosing_level) ; static char *niceTextXMLSchema(BS *bs, BS *bsm, XmlProcessing *style, char **end_tag_out) ; static int niceBSJava (ACEOUT dump_out, BS bs, BS bsm, int position, int level, int style, BOOL isK) ; static char* niceTextJava (BS bs, int style, BOOL isK) ; /*************/ /* YUCH, there is really no need for these to be here like this.... */ extern BOOL dumpComments ; extern BOOL dumpTimeStamps ; /*************/ #define LINE_LENGTH 120 static BOOL isModele ; static char *qm = 0 ; /* character or sequence of chars to use as a quote mark */ static BOOL debug = FALSE ; /* * AceC object dumper */ static int niceBSC (ACEOUT dump_out, BS bs, BS bsm, int position) { int i, level ; char direction ; char *cp, buf[8] ; level = position + 1; while (bs) { bsModelMatch (bs, &bsm) ; i = level - position ; switch (i) { case 0: direction = '.' ; break ; case 1: direction = '>' ; break ; case -1: direction = '<' ; break ; default: buf[0] = 'l' ; while (i < -255) { buf[1] = 255 ; aceOutBinary (dump_out, buf,2) ; i += 255 ; } if (i < 0) { buf[1] = -i ; aceOutBinary (dump_out, buf,2) ; } direction = '.' ; break ; } buf[0] = direction ; position = level ; /* dump cell itself */ if (bs->key <= _LastC) { buf[1] = 't' ; aceOutBinary ( dump_out, buf,2) ; cp = bsText(bs) ; aceOutBinary ( dump_out, cp, strlen(cp) + 1) ; } else if (bs->key == _Int) { int ii = bs->n.i ; buf[1] = 'i' ; aceOutBinary ( dump_out, buf,2) ; aceOutBinary ( dump_out, (char*)&ii, 4) ; } else if (bs->key == _Float) { float f = bs->n.f ; buf[1] = 'f' ; aceOutBinary ( dump_out, buf,2) ; aceOutBinary ( dump_out, (char*) &f, 4) ; } else if (bs->key == _DateType) { int ii = bs->n.time ; buf[1] = 'd' ; aceOutBinary ( dump_out, buf,2) ; aceOutBinary ( dump_out, (char*) &ii, 4) ; } else if (iskey(bs->key) == 2) { char *title = 0 ; if ((title = niceExpandText(bs->key))) { buf[1] = 't' ; aceOutBinary ( dump_out, buf,2) ; cp = title ; aceOutBinary ( dump_out, cp, strlen(cp) + 1) ; } else { buf[1] = 'K' ; buf[2] = class(bs->key) ; aceOutBinary ( dump_out, buf,3) ; cp = name(bs->key) ; aceOutBinary ( dump_out, cp, strlen(cp) + 1) ; } } else if (class(bs->key)) /* an emtpty object */ { buf[1] = 'k' ; buf[2] = class(bs->key) ; aceOutBinary (dump_out, buf,3) ; cp = name(bs->key) ; aceOutBinary (dump_out, cp, strlen(cp) + 1) ; } else if (!class(bs->key)) /* a tag */ { int ii = bs->key ; buf[1] = 'g' ; aceOutBinary ( dump_out, buf,2) ; aceOutBinary ( dump_out, (char*) &ii, 4) ; } /* dump right */ if (bs->right) { if (bsIsType(bsm->right)) aceOutBinary( dump_out, "!", 1); /* entering subtype */ position = niceBSC (dump_out, bs->right, bsModelRight(bsm), position) ; if (bsIsType(bsm->right)) aceOutBinary( dump_out, "@", 1); /* leaving subtype */ } /* move down, dump in the cuurent while loop */ bs = bs->down ; if (!bs) break ; /* exit from loop */ aceOutBinary( dump_out, "\n", 1); } return position ; } /*****************************************************************************/ /************************* External routines *********************************/ void niceDump(ACEOUT dump_out, OBJ obj, char style) { static BOOL isFirst = TRUE ; BS oldDown = 0 ; if (isFirst) { qm = getenv("ACEQM"); /* quote mark for perl output */ if (!qm) { qm = messalloc (2); qm[0] = 1; qm[1] = 0; /* default character is ^A */ } isFirst = FALSE ; } isModele = (class(obj->root->key) == _VModel) || isModel(obj->root->key) ; if (obj->curr) switch (style) { case 'h': case 'H': aceOutPrint (dump_out, "%s %s", className (obj->key), niceTextUsual (obj->root)) ; if (obj->curr != obj->root) { oldDown = obj->curr->down ; obj->curr->down = 0 ; niceBShuman (dump_out, obj->curr,2,1) ; obj->curr->down = oldDown ; } else niceBShuman (dump_out, obj->curr->right,2,1) ; aceOutxy (dump_out, "",0,1) ; /* space line */ break ; case 'j': case 'J': case 'k' : case 'K': /* revised 'j' types for AcePerl with # and good times */ if (obj->curr != obj->root) { aceOutPrint (dump_out, "%s", niceTextJava (obj->root, (style == 'J' || style == 'K') ? 1 : 0, (style == 'k' || style == 'K'))) ; oldDown = obj->curr->down ; obj->curr->down = 0 ; niceBSJava (dump_out, obj->curr, obj->modCurr, 0, 1, (style == 'J' || style == 'K') ? 2 : 0, (style == 'k' || style == 'K')) ; obj->curr->down = oldDown ; } else { oldDown = obj->curr->down ; obj->curr->down = 0 ; niceBSJava (dump_out, obj->curr, obj->modCurr, 0, 0, (style == 'J' || style == 'K') ? 1 : 0, (style == 'k' || style == 'K')) ; obj->curr->down = oldDown ; } aceOutPrint (dump_out, "\n") ; break; case 'p': aceOutPrint (dump_out, "{"); aceOutPrint (dump_out, "%s", niceTextPerl (obj->root)) ; if (obj->curr->right) { aceOutPrint (dump_out, ",Pn=>[\n"); niceBSPerl (dump_out, obj->curr->right, bsModelRight(obj->modCurr), 0, 1) ; aceOutPrint (dump_out, "]"); } aceOutPrint (dump_out, "}\n"); break ; case 'C': { char buf[2] ; char *cp = name(obj->key) ; buf[0] = 'N' ; buf[1] = class(obj->key) ; aceOutBinary ( dump_out, buf, 2) ; aceOutBinary ( dump_out, cp, strlen (cp) + 1) ; if (obj->curr->right) niceBSC ( dump_out, obj->curr->right, bsModelRight(obj->modCurr), 0) ; buf[0] = '#' ; aceOutBinary ( dump_out, buf,1) ; } break ; case 'x': case 'X': case 'y': case 'Y': { XmlProcessing xml_style ; char *start_tag ; char *end_tag ; char *enclosing_tag = className(obj->root->key) ; int enclosing_level = 0 ; /* Map the style on to the possible elements we can write out. */ /* With current meanings of flags this if/else is slightly more */ /* compact than a switch, this may change. */ if (style == 'x') xml_style.class_att = FALSE ; else xml_style.class_att = TRUE ; if (style == 'x' || style == 'X') xml_style.value_att = FALSE ; else xml_style.value_att = TRUE ; if (style == 'y') xml_style.all_atts = TRUE ; else xml_style.all_atts = FALSE ; if (style == 'Y') xml_style.content = FALSE ; else xml_style.content = TRUE ; if (isModele) start_tag = niceTextXMLSchema(&(obj->root), &(obj->modCurr), &xml_style, &end_tag) ; else start_tag = niceTextXML(obj->root, &xml_style, &end_tag, &enclosing_tag, &enclosing_level) ; aceOutPrint(dump_out, "%s", start_tag) ; if (obj->curr->right) { aceOutPrint (dump_out, "\n") ; niceBSXML(dump_out, obj->curr->right, bsModelRight(obj->modCurr), &xml_style, 0, 1, enclosing_tag, enclosing_level) ; } aceOutPrint (dump_out, "%s", end_tag) ; messfree(end_tag) ; aceOutPrint (dump_out, "\n"); break ; } #ifdef JUNK /* not yet done */ > case 'b': /* Boulder */ > -name=AC4 > -class=Sequence > FEATURES=.... > HOMOL=... > > > niceText = niceTextBoulder; > aceOutPrint (dump_out, "%s", niceText(obj->root)); > niceBSBoulder (dump_out, obj->root->key, obj->curr->right, obj->modCurr->right, 0,1); > aceOutPrint (dump_out, "\n"); > break; > #endif default: messcrash ("Logic error: unknown style %c in niceDump", style) ; } return; } /* niceDump */ /*****************************************************************************/ /*********************** Internal routines ***********************************/ /* Output ace data in human readable form, indentation provides a visual key */ /* to the class/tags etc. */ /* recursive routine */ static int niceBShuman (ACEOUT dump_out, BS bs, int x, int y) { int length, xPlus, yMax ; char *text, *cp ; for ( ; bs ; bs = bs->down) { if (!dumpComments && class(bs->key) == _VComment) continue ; if (!(text = niceExpandText (bs->key))) text = niceTextUsual (bs) ; if (x < LINE_LENGTH - 18) length = LINE_LENGTH - x ; else length = 18 ; xPlus = 0 ; yMax = y ; uLinesText (text, length) ; if ((cp = uNextLine(text))) { if (strlen(cp) > xPlus) xPlus = strlen(cp) ; if ( x + xPlus > LINE_LENGTH ) { yMax++ ; x = LINE_LENGTH - length ; } aceOutxy (dump_out, cp,x,yMax++) ; /* write out this node */ } while ((cp = uNextLine(text))) /* indent following lines */ { aceOutxy (dump_out, cp,x+2,yMax++) ; if (strlen(cp)+2 > xPlus) xPlus = strlen(cp)+2 ; } xPlus += x ; xPlus = xPlus + 6 - xPlus%4 ; if (bs->right) /* to the right at same y */ y = niceBShuman (dump_out, bs->right, xPlus, y) ; if (yMax > y) y = yMax ; } return y ; } /* niceBShuman */ static char* niceTextUsual(BS bs) { if (isModele) return name (bs->key) ; if (bs->key <= _LastC) return bsText(bs) ; else if (bs->key == _Int) return messprintf ("%d", bs->n.i) ; else if (bs->key == _Float) return messprintf ("%g", bs->n.f) ; else if (bs->key == _DateType) return timeShow (bs->n.time) ; else return name (bs->key) ; } /* niceTextUsual */ /*************/ static char *niceExpandText (KEY key) { KEY tag = pickExpandTag(key) ; OBJ obj ; char *text = 0 ; if (tag && (obj = bsCreate(key))) { if (bsGetKeyTags (obj,tag,0)) text = niceTextUsual (obj->curr) ; bsDestroy (obj) ; } return text ; } /* niceExpandText */ /************************************************************/ /* *** Java DUMPING *** */ /* recursive routine */ static int niceBSJava (ACEOUT dump_out, BS bs, BS bsm, int position, int level, int style, BOOL isK) { static int attachRecursionLevel = 0 ; int i; while (bs) { bsModelMatch (bs, &bsm) ; /* tab over to the correct level */ for (i=position;iright) level=niceBSJava (dump_out, bs->right, bsModelRight(bsm), level,level+1, style, isK); else if (!attachRecursionLevel && bsm && bsm->right && class(bsm->right->key) == _VQuery) { char *cq, *question = name(bsm->right->key) ; OBJ obj2 = 0 ; BS bs1 = bs ; KEYSET ks1 ; KEY key1 ; int ii ; BOOL wholeObj = !strcmp("WHOLE",question) ; cq = question + strlen(question) - 1 ; while (cq > question && *cq != ';') cq-- ; if (*cq == ';') cq++ ; wholeObj = !strcmp("WHOLE",cq) ; /* position k1 upward on first true non-tag key */ while (bs1->up && ( pickType(bs1->key) != 'B' || !class(bs1->key) || bsIsComment(bs1))) bs1 = bs1->up ; ks1 = queryKey (bs1->key, !wholeObj ? question : "IS *") ; if (wholeObj || queryFind (0, 0, cq)) for (ii = 0 ; ii < keySetMax (ks1) ; ii++) { key1 = keySet (ks1, ii) ; obj2 = bsCreate(key1) ; if (!obj2) continue ; attachRecursionLevel++ ; if (wholeObj || queryFind (obj2, key1, 0)) level=niceBSJava (dump_out, obj2->curr->right, bsModelRight(obj2->modCurr), level, level + 1, style, isK) ; bsDestroy (obj2) ; attachRecursionLevel-- ; } keySetDestroy (ks1) ; } bs = bs->down ; if (!bs) break ; /* exit from loop */ aceOutPrint (dump_out, "\n"); position = 0; } level--; return level; } /* niceBSJava */ /**************/ static char* niceTextJava (BS bs, int style, BOOL isK) { static KEY old = 0, oldTime = 0 ; static Stack s = 0 ; if (style < 2) old = oldTime = 0 ; if (!bs) return 0 ; /* allow to simply reset old to zero */ if (!s) s = stackCreate(128) ; stackClear (s) ; if (style == 0) /* old style, always start with a ? */ pushText (s, "?") ; if (isModele) { catText (s, class(bs->key) == _VModel ? "Model" : "tag") ; catText (s, messprintf ("?%s?", freejavaprotect(name(bs->key)))) ; } else if (bs->key <= _LastC) { if (!old || bs->key != old) catText (s, isK ? "#Text" : "txt") ; catText (s, messprintf ("?%s?", freejavaprotect(bsText(bs)))) ; } else if (bs->key == _Int) { if (!old || bs->key != old) catText (s, isK ? "#Int" : "int") ; catText (s, messprintf ("?%d?", bs->n.i)) ; } else if (bs->key == _Float) { if (!old || bs->key != old) catText (s, isK ? "#Float" : "float") ; catText (s, messprintf ("?%g?", bs->n.f)) ; } else if (bs->key == _DateType) { if (!old || bs->key != old) catText (s, isK ? "#Date" : "date") ; catText (s, messprintf ("?%s?", isK ? timeShow (bs->n.time) : timeShowJava (bs->n.time))) ; } else if (!class(bs->key)) /* a tag */ { if (!old || class(old)) catText (s, "tag") ; catText (s, messprintf ("?%s?", freejavaprotect(name(bs->key)))) ; } else { if (!old || class(bs->key) != class(old)) catText (s, messprintf ("%s", freejavaprotect(className(bs->key)))) ; catText (s, messprintf ("?%s?", freejavaprotect(name(bs->key)))) ; } if (dumpTimeStamps && bs->timeStamp && (!oldTime || bs->timeStamp != oldTime )) catText (s, name(bs->timeStamp)) ; old = bs->key ; oldTime = bs->timeStamp ; return stackText (s,0) ; } /* niceTextJava */ /************************************************************/ /* *** XML DUMPING *** */ /* recursive routine */ static void niceBSXML(ACEOUT dump_out, BS bs, BS bsm, XmlProcessing *style, int position, int level, char *enclosing_class, int enclosing_level) { static int attachRecursionLevel = 0 ; int i ; char *start_tag ; char *end_tag ; char *new_enclosing_class = enclosing_class ; int new_enclosing_level = enclosing_level ; BS bs_down ; bs_down = bs ; while (bs) { BOOL model_query ; bsModelMatch (bs, &bsm) ; /* Indent */ for (i = position; i < level; i++) /* indent */ aceOutPrint (dump_out, " "); #ifdef ED_G_NEVER_INCLUDE_THIS_CODE aceOutPrint (dump_out, "\t"); #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ /* I'm really not sure if this is going to work too well because of */ /* all the model stuff...is it really needed to print out a model */ /* anyway ??? I just don't know....it seems to do better things but */ /* are they correct ????? */ /* print the current tag */ end_tag = NULL ; if (isModele) start_tag = niceTextXMLSchema(&bs, &bsm, style, &end_tag) ; else start_tag = niceTextXML(bs, style, &end_tag, &new_enclosing_class, &new_enclosing_level) ; aceOutPrint(dump_out, "%s", start_tag) ; /* Check for embedded query in the objects model. */ if (!attachRecursionLevel && bsm && bsm->right && class(bsm->right->key) == _VQuery) model_query = TRUE ; else model_query = FALSE ; /* Anything to right ? then do it on the next line. */ if (bs->right || model_query) { aceOutPrint (dump_out, "\n"); } /* Recurse and get the next item to the right */ if (bs->right) { niceBSXML(dump_out, bs->right, bsModelRight(bsm), style, 0 /*level */, level+1, new_enclosing_class, new_enclosing_level) ; } /* else if (!attachRecursionLevel && bsm && bsm->right && class(bsm->right->key) == _VQuery) */ else if (model_query) { char *cq, *question = name(bsm->right->key) ; OBJ obj2 = 0 ; BS bs1 = bs ; KEYSET ks1 ; KEY key1 ; int ii ; BOOL wholeObj = !strcmp("WHOLE",question) ; cq = question + strlen(question) - 1 ; while (cq > question && *cq != ';') cq-- ; if (*cq == ';') cq++ ; wholeObj = !strcmp("WHOLE",cq) ; /* position k1 upward on first true non-tag key */ while (bs1->up && (pickType(bs1->key) != 'B' || !class(bs1->key) || bsIsComment(bs1))) bs1 = bs1->up ; ks1 = queryKey (bs1->key, !wholeObj ? question : "IS *") ; if (wholeObj || queryFind (0, 0, cq)) { for (ii = 0 ; ii < keySetMax (ks1) ; ii++) { key1 = keySet (ks1, ii) ; obj2 = bsCreate(key1) ; if (!obj2) continue ; attachRecursionLevel++ ; if (wholeObj || queryFind (obj2, key1, 0)) { niceBSXML (dump_out, obj2->curr->right, bsModelRight(obj2->modCurr), style, 0 /*level */, level + 1, new_enclosing_class, new_enclosing_level) ; } bsDestroy (obj2) ; attachRecursionLevel-- ; } } keySetDestroy (ks1) ; } /* Print the closing tag (indent it if its on different line from */ /* opening tag. Always newline after closing tag. */ if (bs->right || model_query) { for (i = position; i < level; i++) aceOutPrint (dump_out, " "); #ifdef ED_G_NEVER_INCLUDE_THIS_CODE aceOutPrint (dump_out, "\t"); #endif /* ED_G_NEVER_INCLUDE_THIS_CODE */ } aceOutPrint (dump_out, "%s", end_tag) ; aceOutPrint (dump_out, "\n"); messfree(end_tag) ; /* Compare addresses, _not_ contents, free if new address. */ if (enclosing_class != new_enclosing_class) { messfree(new_enclosing_class) ; new_enclosing_class = enclosing_class ; } /* reset enclosing level. */ new_enclosing_level = enclosing_level ; /* See if there is another item at same level, otherwise exit from loop*/ bs = bs->down ; if (!bs) break ; } /* while loop */ return ; } static char *niceTextXML(BS bs, XmlProcessing *style, char **end_tag_out, char **enclosing_class, int *enclosing_level) { char *start_tag = NULL, *end_tag = NULL ; char *element ; char *value ; char *type ; char *num_str ; char *level_str ; /* These must be NULL because of the messprintf() below. */ element = NULL ; value = NULL ; type = NULL ; /* These must be NULL to ensure freeing of resources correctly. */ *end_tag_out = NULL ; num_str = NULL ; level_str = NULL ; if (bs->key <= _LastC) { element = "Txt" ; value = bsText(bs) ; type = "txt" ; end_tag = element ; (*enclosing_level)++ ; level_str = hprintf(0, "%s-%d", *enclosing_class, *enclosing_level) ; } else if (bs->key == _Int) { element = "Int" ; num_str = hprintf(0, "%d", bs->n.i) ; value = num_str ; type = "int" ; end_tag = element ; (*enclosing_level)++ ; level_str = hprintf(0, "%s-%d", *enclosing_class, *enclosing_level) ; } else if (bs->key == _Float) { element = "Float" ; num_str = hprintf(0, "%g", bs->n.f) ; value = num_str ; type = "float" ; end_tag = element ; (*enclosing_level)++ ; level_str = hprintf(0, "%s-%d", *enclosing_class, *enclosing_level) ; } else if (bs->key == _DateType) { element = "Date" ; value = timeShow(bs->n.time) ; type = "date" ; end_tag = element ; (*enclosing_level)++ ; level_str = hprintf(0, "%s-%d", *enclosing_class, *enclosing_level) ; } else if (class(bs->key)) { /* we've found an object. */ element = className(bs->key) ; value = name(bs->key) ; type = "object_ref" ; end_tag = element ; *enclosing_class = hprintf(0, "%s", element) ; } else if (!class(bs->key)) { /* we've found a tag. */ element = name(bs->key) ; type = "tag" ; end_tag = element ; *enclosing_class = hprintf(0, "%s", element) ; } else { messcrash("logic error, unexpected type of tag/class, class was: %s.", className(bs->key)) ; } /* Make: "content" and print it. */ start_tag = messprintf ("<%s%s%s%s%s%s%s%s%s%s>%s", /* aaaagggghhhhh, the percentage game... */ element, style->class_att ? " type=\"" : "", style->class_att ? type : "", style->class_att ? "\"" : "", (style->all_atts && level_str) ? " level=\"" : "", (style->all_atts && level_str) ? level_str : "", (style->all_atts && level_str) ? "\"" : "", (style->value_att && value) ? " value=\"" : "", (style->value_att && value) ? value : "", (style->value_att && value) ? "\"" : "", (style->content && value) ? value : "") ; /* Make: "" and return it (note, caller must free this). */ *end_tag_out = hprintf(0, "", end_tag) ; if (num_str != NULL) messfree(num_str) ; if (level_str != NULL) messfree(level_str) ; return start_tag ; } /***************************/ /* Like the above routine but deals with special requirements of a model. */ static char *niceTextXMLSchema(BS *bs_out, BS *bsm_out, XmlProcessing *style, char **end_tag_out) { char *start_tag = NULL ; char *elem_name ; char *elem_type ; char *elem_occurs ; char *elem_basetype ; char *elem_xref = NULL ; char *debug ; BS bs = *bs_out ; BS bsm = *bsm_out ; BOOL unique = FALSE ; /* These must _not_ be NULL because of the messprintf() below. */ elem_basetype = "" ; /* These must be NULL to ensure freeing of resources correctly. */ *end_tag_out = NULL ; /* if you do a class(key) you get either model or system, that's it. */ debug = nameWithClass(bs->key) ; if (bs->key == _UNIQUE) { unique = TRUE ; bs = bs->right ; bsModelRight(bsm) ; bsModelMatch(bs, &bsm) ; *bs_out = bs ; *bsm_out = bsm ; } /* we could just use the keys rather than all this name lark which just */ /* wastes time.... */ elem_name = name(bs->key) ; if (strcasecmp(elem_name, "int") == 0) { elem_type = "INT" ; elem_basetype = "" ; } else if (strcasecmp(elem_name, "float") == 0) { elem_type = "FLOAT" ; elem_basetype = "" ; } else if (strcasecmp(elem_name, "datetype") == 0) { elem_type = "DATE" ; elem_basetype = "" ; } else if (strcasecmp(elem_name, "text") == 0) { elem_type = "TEXT" ; elem_basetype = "" ; } else if (class(bs->key) == _VModel) { elem_type = "Model" ; if (bs->right) { if ((bs->right)->key == _XREF) { char *my_name = name((bs->right)->key) ; /* go right to xref... */ bs = bs->right ; bsModelRight(bsm) ; bsModelMatch(bs, &bsm) ; /* go right to tag following xref... */ bs = bs->right ; bsModelRight(bsm) ; bsModelMatch(bs, &bsm) ; elem_xref = name(bs->key) ; *bs_out = bs ; *bsm_out = bsm ; } } elem_basetype = "" ; } /* WARNING: NOT SURE IF THIS CATCH ALL IS SAFE...????? */ else { elem_type = "Tag" ; } if (unique) elem_occurs = " maxOccurs=\"1\"" ; else elem_occurs = " maxOccurs=\"unbounded\"" ; /* Make: "content" and return it. */ start_tag = messprintf("%s", elem_name, elem_type, elem_occurs, elem_xref ? " xref=\"" : "", elem_xref ? elem_xref : "", elem_xref ? "\"" : "", elem_basetype) ; /* Make: "" and return it (note, caller must free this). */ *end_tag_out = hprintf(0, "%s%s", *elem_basetype ? "" : "", "") ; return start_tag ; } /************************************************************/ /* *** Perl DUMPING *** */ static char* niceTextPerl(BS bs) { char *title; if (isModele) return name (bs->key); if (bs->key <= _LastC) return messprintf ("ty=>tx,va=>%s%s%s", qm, bsText(bs), qm); else if (bs->key == _Int) return messprintf ("ty=>in,va=>%d", bs->n.i); else if (bs->key == _Float) return messprintf ("ty=>fl,va=>%g", bs->n.f); else if (bs->key == _DateType) return messprintf ("ty=>dt,va=>%s%s%s", qm, timeShow (bs->n.time), qm); else if (iskey(bs->key) == 2) { if ((title = niceExpandText(bs->key))) return messprintf ("ty=>ob,cl=>%s%s%s,va=>%s%s%s,ti=>%s%s%s", qm, className(bs->key), qm, qm, name(bs->key), qm, qm, title, qm); else return messprintf ("ty=>ob,cl=>%s%s%s,va=>%s%s%s", qm, className(bs->key), qm, qm, name(bs->key), qm); } else if (!class(bs->key)) /* a tag */ return messprintf ("ty=>tg,va=>%s%s%s", qm, name(bs->key), qm); else return messprintf ("ty=>ob,cl=>%s%s%s,va=>%s%s%s,mt=>1", qm, className(bs->key), qm, qm, name(bs->key), qm); } /* niceTextPerl */ /************************************************************/ /* recursive routine */ /* RD 980716 simpler layout */ static void niceBSPerl (ACEOUT dump_out, BS bs, BS bsm, int position, int level) { static int attachRecursionLevel = 0 ; int i ; while (bs) { bsModelMatch (bs, &bsm) ; for (i = position; i < level; i++) /* indent */ aceOutPrint (dump_out, "\t"); aceOutPrint (dump_out, "{") ; aceOutPrint (dump_out, "%s", niceTextPerl(bs)) ; if (bs->right) { aceOutPrint (dump_out, ",Pn=>[\n") ; niceBSPerl (dump_out, bs->right, bsModelRight(bsm), 0 /*level */ , level+1) ; aceOutPrint (dump_out, "]") ; } else if (!attachRecursionLevel && bsm && bsm->right && class(bsm->right->key) == _VQuery) { char *cq, *question = name(bsm->right->key) ; OBJ obj2 = 0 ; BS bs1 = bs ; KEYSET ks1 ; KEY key1 ; int ii ; BOOL wholeObj = !strcmp("WHOLE",question) ; cq = question + strlen(question) - 1 ; while (cq > question && *cq != ';') cq-- ; if (*cq == ';') cq++ ; wholeObj = !strcmp("WHOLE",cq) ; /* position k1 upward on first true non-tag key */ while (bs1->up && ( pickType(bs1->key) != 'B' || !class(bs1->key) || bsIsComment(bs1))) bs1 = bs1->up ; ks1 = queryKey (bs1->key, !wholeObj ? question : "IS *") ; if (wholeObj || queryFind (0, 0, cq)) for (ii = 0 ; ii < keySetMax (ks1) ; ii++) { key1 = keySet (ks1, ii) ; obj2 = bsCreate(key1) ; if (!obj2) continue ; attachRecursionLevel++ ; if (wholeObj || queryFind (obj2, key1, 0)) { aceOutPrint (dump_out, ",Pn=>[\n") ; niceBSPerl (dump_out, obj2->curr->right, bsModelRight(obj2->modCurr), 0 /*level */, level + 1) ; aceOutPrint (dump_out, "]") ; } bsDestroy (obj2) ; attachRecursionLevel-- ; } keySetDestroy (ks1) ; } aceOutPrint (dump_out, "}") ; bs = bs->down ; if (!bs) break ; /* exit from loop */ aceOutPrint (dump_out, ",\n") ; } } /**************/ /************************* eof ******************************/