From: Ben Pfaff Date: Sat, 11 Jan 2020 07:13:11 +0000 (+0000) Subject: vizml work X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=d91901f17ae623d757d9c935df153ce1917d5e12;p=pspp vizml work --- diff --git a/src/output/spv/automake.mk b/src/output/spv/automake.mk index 198e8df7e5..6a2b3e1ad2 100644 --- a/src/output/spv/automake.mk +++ b/src/output/spv/automake.mk @@ -102,3 +102,20 @@ nodist_src_output_liboutput_la_SOURCES += $(structure_xml_out) BUILT_SOURCES += $(structure_xml_out) CLEANFILES += $(structure_xml_out) EXTRA_DIST += $(structure_xml_in) + +vizml_in = \ + src/output/spv/xml-parser-generator \ + src/output/spv/vizml.grammar +vizml_out = \ + src/output/spv/vizml-parser.c \ + src/output/spv/vizml-parser.h +src/output/spv/vizml-parser.c: $(vizml_in) + $(AM_V_GEN)$(PYTHON) $^ code vizml '"output/spv/vizml-parser.h"' > $@.tmp + $(AM_V_at)mv $@.tmp $@ +src/output/spv/vizml-parser.h: $(vizml_in) + $(AM_V_GEN)$(PYTHON) $^ header vizml > $@.tmp && mv $@.tmp $@ +nodist_src_output_liboutput_la_SOURCES += $(vizml_out) +BUILT_SOURCES += $(vizml_out) +CLEANFILES += $(vizml_out) +EXTRA_DIST += $(vizmlb_in) + diff --git a/src/output/spv/spv.c b/src/output/spv/spv.c index f186e638e7..ecb008c991 100644 --- a/src/output/spv/spv.c +++ b/src/output/spv/spv.c @@ -40,6 +40,7 @@ #include "output/spv/spv-legacy-decoder.h" #include "output/spv/spv-light-decoder.h" #include "output/spv/structure-xml-parser.h" +#include "output/spv/vizml-parser.h" #include "gl/c-ctype.h" #include "gl/intprops.h" @@ -181,6 +182,12 @@ spv_item_is_table (const struct spv_item *item) return item->type == SPV_ITEM_TABLE; } +bool +spv_item_is_graph (const struct spv_item *item) +{ + return item->type == SPV_ITEM_GRAPH; +} + bool spv_item_is_text (const struct spv_item *item) { @@ -572,6 +579,8 @@ spv_item_load (const struct spv_item *item) { if (spv_item_is_table (item)) spv_item_get_table (item); + else if (spv_item_is_graph (item)) + spv_item_get_graph (item); } bool @@ -652,8 +661,11 @@ char * WARN_UNUSED_RESULT spv_item_get_raw_legacy_data (const struct spv_item *item, void **data, size_t *size) { - if (!spv_item_is_legacy_table (item)) - return xstrdup ("not a legacy table object"); + if (!spv_item_is_legacy_table (item) && !spv_item_is_graph (item)) + return xstrdup ("not a graph or legacy table object"); + + if (!item->bin_member) + return xstrdup ("graph or legacy table lacks legacy data"); return zip_member_read_all (item->spv->zip, item->bin_member, data, size); } @@ -873,6 +885,74 @@ spv_item_get_table (const struct spv_item *item_) return item->table; } +static char * WARN_UNUSED_RESULT +spv_open_graph (struct spv_item *item) +{ + assert (spv_item_is_graph (item)); + + struct spv_data data; + char *error = spv_item_get_legacy_data (item, &data); + if (error) + { + struct string s = DS_EMPTY_INITIALIZER; + spv_item_format_path (item, &s); + ds_put_format (&s, " (%s): %s", item->bin_member, error); + + free (error); + return ds_steal_cstr (&s); + } + + xmlDoc *doc; + error = spv_read_xml_member (item->spv, item->xml_member, false, + "visualization", &doc); + if (error) + { + spv_data_uninit (&data); + return error; + } + + struct spvxml_context ctx = SPVXML_CONTEXT_INIT (ctx); + struct vizml_visualization *v; + vizml_parse_visualization (&ctx, xmlDocGetRootElement (doc), &v); + error = spvxml_context_finish (&ctx, &v->node_); + + if (error) + { + struct string s = DS_EMPTY_INITIALIZER; + spv_item_format_path (item, &s); + ds_put_format (&s, " (%s): %s", item->xml_member, error); + + free (error); + error = ds_steal_cstr (&s); + } + + spv_data_uninit (&data); + vizml_free_visualization (v); + if (doc) + xmlFreeDoc (doc); + + return error; +} + +void +spv_item_get_graph (const struct spv_item *item_) +{ + struct spv_item *item = CONST_CAST (struct spv_item *, item_); + + assert (spv_item_is_graph (item)); + if (!item->graph) + { + item->graph = true; + char *error = spv_open_graph (item); + if (error) + { + item->error = true; + msg (ME, "%s", error); + free (error); + } + } +} + /* Constructs a new spv_item from XML and stores it in *ITEMP. Returns NULL if successful, otherwise an error message for the caller to use and free (with free()). @@ -904,7 +984,7 @@ spv_decode_container (const struct spvsx_container *c, item->subtype = xstrdup_if_nonempty (table->sub_type); if (ts->path) { - item->xml_member = ts->path ? xstrdup (ts->path->text) : NULL; + item->xml_member = xstrdup_if_nonempty (ts->path->text); char *error = decode_spvsx_legacy_properties ( table->table_properties, &item->legacy_properties); if (error) @@ -916,10 +996,12 @@ spv_decode_container (const struct spvsx_container *c, } else if (spvsx_is_graph (content)) { - struct spvsx_graph *graph = spvsx_cast_graph (content); item->type = SPV_ITEM_GRAPH; + + struct spvsx_graph *graph = spvsx_cast_graph (content); + item->bin_member = xstrdup_if_nonempty (graph->data_path->text); item->command_id = xstrdup_if_nonempty (graph->command_name); - /* XXX */ + item->xml_member = xstrdup_if_nonempty (graph->path->text); } else if (spvsx_is_model (content)) { diff --git a/src/output/spv/spv.h b/src/output/spv/spv.h index 0bf2ff7014..f04cb95fe5 100644 --- a/src/output/spv/spv.h +++ b/src/output/spv/spv.h @@ -131,9 +131,14 @@ struct spv_item /* SPV_ITEM_TABLE only. */ struct pivot_table *table; /* NULL if not yet loaded. */ struct spv_legacy_properties *legacy_properties; + char *subtype; + + /* SPV_ITEM_GRAPH only. */ + bool graph; + + /* SPV_ITEM_TABLE and SPV_ITEM_GRAPH only. */ char *bin_member; char *xml_member; - char *subtype; /* SPV_ITEM_TEXT only. */ struct pivot_value *text; @@ -159,6 +164,9 @@ struct spv_item *spv_item_get_child (const struct spv_item *, size_t idx); bool spv_item_is_table (const struct spv_item *); struct pivot_table *spv_item_get_table (const struct spv_item *); +bool spv_item_is_graph (const struct spv_item *); +void spv_item_get_graph (const struct spv_item *); + bool spv_item_is_text (const struct spv_item *); const struct pivot_value *spv_item_get_text (const struct spv_item *); diff --git a/src/output/spv/vizml.grammar b/src/output/spv/vizml.grammar new file mode 100644 index 0000000000..31b9d95835 --- /dev/null +++ b/src/output/spv/vizml.grammar @@ -0,0 +1,592 @@ +# PSPP - a program for statistical analysis. +# Copyright (C) 2017, 2018, 2019 Free Software Foundation, Inc. +# +# 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 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 . + +visualization + :creator? + :date + :description + :lang + :name + :style[style_ref]=ref style + :type + :version + :schemaLocation? + :clip? +=> location* + visualization_extension? + userSource + (sourceVariable | derivedVariable | expressionVariable)+ + categoricalDomain? + intervalDomain* + graph + labelFrame[lf1]* + container? + labelFrame[lf2]* + style+ + layerController? + styleCycle* + style[s2]* + +extension[visualization_extension] + :numRows=int? + :showGridline=bool? + :minWidthSet=(true)? + :maxWidthSet=(true)? + :legend1? + :legend2? + :styleCycleRepository? + :title1? + :title2? + :subtitle? + :footnote1? + :footnote2? + :footnote3? + :textbox1? + :textbox2? + :statisticsSummary? + :statisticsSummary1? + :dataSetHandle_0? + :dataSetName_0? + :dataSetHandle_1? + :dataSetName_1? + :dataSetHandle_2? + :dataSetName_2? + :percentDomain=(percentDomain)? + :regionStatistic_2270? + :regionStatistic_2737? + :smoothStatistic_2717? + :originLineY? + :boxplotLinkWidth=bool? +=> EMPTY + +userSource :missing=(listwise | pairwise)? => EMPTY # Related to omit_empty? + +categoricalDomain => variableReference categories? simpleSort? + +intervalDomain + :date=bool? +=> ETC + +categories + :remove=bool? +=> ETC + +simpleSort + :method[sort_method]=(custom | natural) +=> categoryOrder + +sourceVariable + :id + :categorical=bool + :source + :domain=ref categoricalDomain? + :sourceName + :dependsOn=ref sourceVariable? + :label? + :labelVariable=ref sourceVariable? + :creator? + :key=bool? + :weight=bool? + :shortLabel? + :description? +=> variable_extension* (format | stringFormat)? + +derivedVariable + :id + :categorical=(true) + :value + :dependsOn=ref sourceVariable? + :creator? + :key=bool? + :label? + :source? + :weight=bool? +=> variable_extension* (format | stringFormat)? valueMapEntry* + +extension[variable_extension] + :from? + :helpId? + :statistic? + :valuesAreGroupedMidpoints=bool? + :max? + :min? +=> EMPTY + +expressionVariable + :categorical=bool? + :creator? + :expression? + :shortLabel? + :label? +=> ETC + +valueMapEntry :from :to => EMPTY + +categoryOrder => TEXT + +graph + :cellStyle=ref style + :style=ref style + :axesOutside=bool? +=> location+ coordinates faceting? point[p1]? facetLayout? + line[line1]? point[p2]? schema? interval* lineGuide? line[line2]? + functionGuide* + +location + :part=(height | width | top | bottom | left | right) + :method=(sizeToContent | attach | fixed | same) + :min? + :max? + :target=ref (labelFrame | graph | container)? + :value? + :specifiedByUser=bool? +=> EMPTY + +coordinates +=> (dimension | transposeTransform | reflectionTransform | polarTransform)* + +dimension + :domain? + :lowerMargin? + :upperMargin? + :niceLowerMapping=bool? + :niceUpperMapping=bool? + :unionDomain=bool? + :clusterGap? + :clusterVariable? +=> ETC + +transposeTransform => ETC + +reflectionTransform + :alternating=bool? + :dimension? +=> ETC + +polarTransform + :counterClockwise=bool? + :cycles=int? + :startAngle=real? +=> ETC + +faceting + :method[faceting_method]=(nest | cross | dot)? +=> layer[layers1]* cross layer[layers2]* + +cross => (unity | nest | cross | variableReference)+ + +nest => variableReference[vars]+ + +unity => EMPTY + +variableReference :ref=ref (sourceVariable | derivedVariable) => EMPTY + +layer + :variable=ref (sourceVariable | derivedVariable) + :value + :visible=bool? + :method[layer_method]=(nest)? + :titleVisible=bool? +=> EMPTY + +facetLayout + :topDown=bool? + :method[facetLayout_method]=(structured)? + :cellAspect=int? +=> tableLayout? setCellProperties[scp1]* + facetLevel* setCellProperties[scp2]* + +tableLayout + :verticalTitlesInCorner=bool + :style=ref style? + :fitCells=(ticks both)? +=> EMPTY + +facetLevel + :level=int + :gap? +=> axis? + +point + :dot=bool? + :name? + :showCollidingLabels=bool? + :labelCollisionHandling=(none | normal)? + :style=ref style? + :positionModifier=(none | stack)? + :zOrder=int? +=> ETC + +line + :breakRepresentation? + :labelCollisionHandling=(none | normal)? + :showCollidingLabels=bool? + :name? + :style=ref style? + :dot=bool? + :positionModifier=(none | stack)? + :showDiscontinuity=bool? + :zOrder=int? + :coordinates? +=> ETC + +lineGuide + :style=ref style? + :x=int? + :y=int? +=> ETC + +functionGuide + :name + :segments=int? + :style=ref style? + :value? +=> ETC + +schema + :dot=bool? + :extremeStyle? + :fenceStyle=ref style? + :hingeStyle=ref style? + :medianStyle=ref style? + :name? + :outlierStyle=ref style? + :showCollidingLabels=bool? + :labelCollisionHandling=(none | normal)? + :style=ref style? + :positionModifier=(none | stack)? + :zOrder=int? +=> ETC + +axis + :style=ref style + :opposite=bool? + :repeat=(never)? +=> label? majorTicks + +label + :style=ref style + :textFrameStyle=ref style? + :purpose=(title | subTitle | subSubTitle | layer | footnote)? +=> text+ | descriptionGroup + +descriptionGroup + :target=ref (faceting | interval) + :separator? +=> (description | text)+ + +description + :name? +=> format* + +majorTicks + :labelAngle=int + :length=dimension + :style=ref style + :tickFrameStyle=ref style + :labelFrequency=int? + :stagger=bool? + :markStyle=ref style? + :base=int? +=> gridline? + +gridline + :style=ref style + :zOrder=int +=> EMPTY + +setCellProperties + :applyToConverse=bool? +=> (setStyle | setFrameStyle | setFormat | setMetaData)* union[union_]? + +setStyle + :target=ref (labeling | graph | interval | majorTicks) + :style=ref style +=> EMPTY + +setMetaData + :target=ref graph + :key + :value +=> EMPTY + +setFormat + :target=ref (majorTicks | labeling) + :reset=bool? +=> format | numberFormat | stringFormat+ | dateTimeFormat | elapsedTimeFormat + +setFrameStyle + :style=ref style + :target=ref majorTicks +=> EMPTY + +format + :baseFormat[f_base_format]=(date | time | dateTime | elapsedTime)? + :errorCharacter? + :separatorChars? + :mdyOrder=(dayMonthYear | monthDayYear | yearMonthDay)? + :showYear=bool? + :showQuarter=bool? + :quarterPrefix? + :quarterSuffix? + :yearAbbreviation=bool? + :showMonth=bool? + :monthFormat=(long | short | number | paddedNumber)? + :dayPadding=bool? + :dayOfMonthPadding=bool? + :showWeek=bool? + :weekPadding=bool? + :weekSuffix? + :showDayOfWeek=bool? + :dayOfWeekAbbreviation=bool? + :hourPadding=bool? + :minutePadding=bool? + :secondPadding=bool? + :showDay=bool? + :showHour=bool? + :showMinute=bool? + :showSecond=bool? + :showMillis=bool? + :dayType=(month | year)? + :hourFormat=(AMPM | AS_24 | AS_12)? + :minimumIntegerDigits=int? + :maximumFractionDigits=int? + :minimumFractionDigits? + :useGrouping=bool? + :scientific=(onlyForSmall | whenNeeded | true | false)? + :small=real? + :prefix? + :suffix? + :tryStringsAsNumbers=bool? + :negativesOutside=bool? + :hiddenseparator=bool? +=> relabel* affix* + +numberFormat + :minimumIntegerDigits? + :maximumFractionDigits=int? + :minimumFractionDigits=int? + :useGrouping=bool? + :scientific=(onlyForSmall | whenNeeded | true | false)? + :small=real? + :prefix? + :suffix? +=> affix* + +stringFormat => relabel* affix* + +dateTimeFormat + :baseFormat[dt_base_format]=(date | time | dateTime) + :separatorChars? + :mdyOrder=(dayMonthYear | monthDayYear | yearMonthDay)? + :showYear=bool? + :yearAbbreviation=bool? + :showQuarter=bool? + :quarterPrefix? + :quarterSuffix? + :showMonth=bool? + :monthFormat=(long | short | number | paddedNumber)? + :showWeek=bool? + :weekPadding=bool? + :weekSuffix? + :showDayOfWeek=bool? + :dayOfWeekAbbreviation=bool? + :dayPadding=bool? + :dayOfMonthPadding=bool? + :hourPadding=bool? + :minutePadding=bool? + :secondPadding=bool? + :showDay=bool? + :showHour=bool? + :showMinute=bool? + :showSecond=bool? + :showMillis=bool? + :dayType=(month | year)? + :hourFormat=(AMPM | AS_24 | AS_12)? +=> affix* + +elapsedTimeFormat + :baseFormat[dt_base_format]=(date | time | dateTime) + :dayPadding=bool? + :hourPadding=bool? + :minutePadding=bool? + :secondPadding=bool? + :showYear=bool? + :showDay=bool? + :showHour=bool? + :showMinute=bool? + :showSecond=bool? + :showMillis=bool? +=> affix* + +affix + :definesReference=int + :position=(subscript | superscript) + :suffix=bool + :value +=> EMPTY + +relabel + :from + :to +=> EMPTY + +union => intersect+ + +intersect => where+ | intersectWhere | alternating | EMPTY + +where + :variable=ref (sourceVariable | derivedVariable) + :include +=> EMPTY + +intersectWhere + :variable=ref (sourceVariable | derivedVariable) + :variable2=ref (sourceVariable | derivedVariable) +=> EMPTY + +alternating => EMPTY + +text + :usesReference=int? + :definesReference=int? + :position=(subscript | superscript)? + :style=ref style +=> TEXT + +interval + :style=ref style + :dot=bool? + :labelCollisionHandling=(none | normal)? + :showCollidingLabels=bool? + :name? + :positionModifier=(none | stack)? + :zOrder=int? +=> binStatistic? summaryStatistic? styleBy? color? x? y? labeling? footnotes? + +labeling + :style=ref style? + :variable=ref (sourceVariable | derivedVariable) +=> (formatting | format | footnotes)* + +formatting :variable=ref (sourceVariable | derivedVariable) => formatMapping* + +formatMapping :from=int => format? + +color + :affect=(both)? + :cycle=ref styleCycle? + :variable? + :clamp=bool? +=> ETC + +x + :variable? +=> ETC + +y + :variable? +=> ETC + +styleBy + :styleCycle? + :variable? + :dimension=int? +=> ETC + +binStatistic + :gridType=(square)? + :binWidth=real? + :binCount=int? +=> ETC + +summaryStatistic + :method[summaryStatistic_method]=(count | range)? + :symbol[summaryStatistic_symbol]=(circle | square)? + :summaryBase=(coordinate)? + :convertIntervalToSingleValue=bool? +=> ETC + +footnotes + :superscript=bool? + :variable=ref (sourceVariable | derivedVariable) +=> footnoteMapping* + +footnoteMapping :definesReference=int :from=int :to => EMPTY + +style + :color=color? + :color2=color? + :labelAngle=real? + :border-bottom=(solid | thick | thin | double | none)? + :border-top=(solid | thick | thin | double | none)? + :border-left=(solid | thick | thin | double | none)? + :border-right=(solid | thick | thin | double | none)? + :border-bottom-color? + :border-top-color? + :border-left-color? + :border-right-color? + :font-family? + :font-size? + :font-weight=(regular | bold)? + :font-style=(regular | italic)? + :font-underline=(none | underline)? + :margin-bottom=dimension? + :margin-left=dimension? + :margin-right=dimension? + :margin-top=dimension? + :textAlignment=(left | right | center | decimal | mixed)? + :labelLocationHorizontal=(positive | negative | center)? + :labelLocationVertical=(positive | negative | center)? + :decimal-offset=dimension? + :size? + :width? + :visible=bool? + :pattern=int? + :stroke-linecap=(butt | round)? + :stroke-width=dimension? + :stroke-dasharray? + :text-fit=bool? + :depth? + :symbol=(circle | ibeam | flower)? + :margin=dimension? + :padding=dimension? +=> style* + +layerController + :source=(tableData) + :target=ref label? +=> EMPTY + +container + :style=ref style + :clip=bool? +=> container_extension? location+ labelFrame* legend? + +extension[container_extension] :combinedFootnotes=(true) => EMPTY + +labelFrame :style=ref style => location+ label? paragraph? + +legend + :style=ref style? + :tickFrameStyle=ref style? + :tickTextStyle=ref style? +=> ETC + +paragraph :hangingIndent=dimension? => EMPTY + +styleCycle +=> ETC diff --git a/utilities/pspp-output.c b/utilities/pspp-output.c index c57dda8e6d..7e22a37076 100644 --- a/utilities/pspp-output.c +++ b/utilities/pspp-output.c @@ -108,6 +108,7 @@ dump_item (const struct spv_item *item) break; case SPV_ITEM_GRAPH: + spv_item_get_graph (item); break; case SPV_ITEM_MODEL: