pyxplot-0.9.2/0000775000175000017500000000000012026340554011624 5ustar dcf21dcf21pyxplot-0.9.2/AUTHORS0000664000175000017500000000004512026340554012673 0ustar dcf21dcf21Dominic Ford pyxplot-0.9.2/NEWS0000664000175000017500000000003712026340554012323 0ustar dcf21dcf21There is no news at this time. pyxplot-0.9.2/buildScripts/0000775000175000017500000000000012026340554014273 5ustar dcf21dcf21pyxplot-0.9.2/buildScripts/parser_data.dat0000664000175000017500000011316212026340554017256 0ustar dcf21dcf21# parser_data.dat # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: parser_data.dat 1302 2012-09-05 17:30:27Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # The language used in this file is generally refered to as RE++ version 3. # The atoms of the syntax are summarised below. # # = If a match fails after this point generate an error rather than continuing # text@3:var Match "text", abbreviated to >= 3 letters, and place in variable var # text@n No space after "text", which must be quoted in full # { ... } Optionally match ... # < ...a... | ...b... > Match exactly one of ...a... or ...b... # ( ...a... ~ ...b... ) Match ...a..., ...b..., etc., in any order, either 1 or 0 times each # [ ...a... ]:foo Match ...a... multiple times. If foo begins zero, ...a... can be matched zero times. # %a:variable Match the name of an axis, e.g. x, y3, z5 # %A:variable Match an angle # %b:variable Match an expression that evaluates to a Boolean # %c:variable Match the name of a color, or an expression evaluating to a color # %d:variable Match an integer expression # %D:variable Match a distance # %e:variable Match an algebraic expression (dollars not allowed) # %E:variable Match an algebraic expression (dollars allowed) # %f:variable Match an expression that evaluates to a real, dimensionless number # %g:variable Match an algebraic expression (no equals signs or dollars) # %o:variable Match an expression that evaluates to any object # %p:variable Match a position -- (x,y) or a vector/list # %P:variable Match a position with a possible third component # %q:variable Match an expression that evaluates to a string # %r:variable Return the whole of the rest of the line as a string # %s:variable Match a word made of alphabetic characters # %S:variable Match a word made of any non-whitespace characters, except quotes # %u:variable Match an expression that evaluates to a number # CODEBLOCK Match a { }-enclosed block of code # DATABLOCK Match one datablock for every filename of '--' # List of commands recognised by Pyxplot { < let@3 > = } [ %v:varname ]:varnames. < =~@n:directive:var_set = s@n %r:regex | =@n:directive:var_set = { %o:value } > [ %v:function_name ]:function_names. (@n [ %v:argument_name ]:0argument_list, )@n [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list =@n:directive:func_set = { %E:definition } arc@3:directive = { item@1 %d:editno } { at@1 } %p:p radius@1 %D:r from@1 %A:angle1 to@1 %A:angle2 { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < fillcolour@1 | fillcolor@1 | fc@2 > %c:fillcolor ) } < line@2:directive | arrow@2:directive > = { item@1 %d:editno } { from@1 } %p:p1 to@1 %p:p2 { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < nohead@2:arrow_style | head@2:arrow_style | twohead@2:arrow_style:twoway | twoway@2:arrow_style > ) } assert@6:directive = < version@4 < >=@n:gtreq | <@n:lt > < %S:version | %q:version > | %b:expr > { %q:message } < box@2:directive | rectangle@2:directive:box > = { item@1 %d:editno } < from@1 %p:p1 to@1 %p:p2 { rotate@1 %A:rotation } | at@1 %p:p3 ( width@1 %D:width ~ height@1 %D:height ~ rotate@1 %A:rotation ) > { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < fillcolour@1 | fillcolor@1 | fc@2 > %c:fillcolor ) } break@5:directive = { %v:loopname } call@3:directive = %o:object cd@2:directive = [ < %S:directory | %q:directory > ]:path circle@4:directive = { item@1 %d:editno } { at@1 } %p:p radius@1 %D:r { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < fillcolour@1 | fillcolor@1 | fc@2 > %c:fillcolor ) } clear@3:directive = continue@4:directive = { %v:loopname } delete@3:directive = { item@1 } [ %d:number ]:deleteno, do@2:directive = { loopname@1 %v:loopname } CODEBLOCK:code while@1 %E:condition ellipse@5:directive = { item@1 %d:editno } < from@2 %p:p1 { to@1 } %p:p2 ( rotate@1 %A:rotation ~ arc { from@1 } %A:arcfrom { to@1 } %A:arcto ) | ( < centre@1 | center@1 > %p:center ~ focus@1 %p:focus ~ < majoraxis@2 %D:majoraxis | semimajoraxis@6 %D:semimajoraxis > ~ < minoraxis@2 %D:minoraxis | semiminoraxis@6 %D:semiminoraxis > ~ eccentricity@1 %f:eccentricity ~ < < semilatusrectum@5 | slr@2 > %D:slr | < latusrectum@2 | lr@2 > %D:lr > ~ rotate@1 %A:rotation ~ arc { from@1 } %A:arcfrom { to@1 } %A:arcto ) > { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < fillcolour@1 | fillcolor@1 | fc@2 > %c:fillcolor ) } eps@3:directive = { item@1 %d:editno } < %S:filename | %q:filename > ( at@2 %p:p ~ rotate@1 %A:rotation ~ width@1 %D:width ~ height@1 %D:height ~ clip@2:clip ~ calcbbox@2:calcbbox ) exec@3:directive = %q:command exit@3:directive:quit = fit@3:directive = [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list %v:fit_function (@n [ %v:inputvar ]:0operands, )@n { withouterrors@1:withouterrors } < %S:filename | %q:filename > ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ) via@1 [ %v:fit_variable ]:fit_variables, < fft@3:directive | ifft@4:directive > = [ [@n %u:min < :@n | to@n > %u:max < :@n | step@n > %u:step ]@n ]:range_list [ %v:varname ]:varnames. (@n [ %v:inputvar ]:0in_operands, )@n { of@1 } < [ %v:fnname ]:fnnames. (@n [ %v:outvar ]:0out_operands, )@n ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ~ window@1 < rectangular@1:window | hamming@3:window | hann@3:window | cosine@1:window | lanczos@1:window | bartlett@2:window | triangular@1:window | gauss@1:window | bartletthann@9:window | blackman@2:window > ) | %q:filename { window@1 < rectangular@1:window | hamming@3:window | hann@3:window | cosine@1:window | lanczos@1:window | bartlett@2:window | triangular@1:window | gauss@1:window | bartletthann@9:window | blackman@2:window > } > DATABLOCK:data for@3:directive = < %v:var_name =@n %u:start_value to@n %u:final_value ( step@2:step %u:step_size ) | (@n { %F:begin } ;@n { %F:criterion } ;@n { %F:iterate } )@n > { loopname@1 %v:loopname } CODEBLOCK:code foreach@4:directive:foreachdatum datum@5:df = [ %v:variable ]:variables, in@n:in [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list { parametric@1:parametric { [@n %u:tmin < :@n | to@n > %u:tmax ]@n { [@n %u:vmin < :@n | to@n > %u:vmax ]@n } } } [ %e:expression ]:expression_list: ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ) { loopname@1 %v:loopname } CODEBLOCK:code DATABLOCK:data foreach@4:directive = %v:var_name in@n:in %o:item_list { loopname@1 %s:loopname } CODEBLOCK:code global@6:directive = [ %v:var_name ]:var_names, help@4:directive = %r:topic history@4:directive = { %d:number_lines } histogram@5:directive = [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list [ %v:varname ]:varnames. ()@2 { parametric@1:parametric { [@n %u:tmin < :@n | to@n > %u:tmax ]@n { [@n %u:vmin < :@n | to@n > %u:vmax ]@n } } } [ %e:expression ]:expression_list: ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ~ binwidth@4 %u:binwidth ~ binorigin@4 %u:binorigin ~ bins@n (@n [ %u:x ]:bin_list, )@n ) DATABLOCK:data < image@4:directive | jpeg@4:directive:image > = { item@1 %d:editno } = < %S:filename | %q:filename > ( at@2 %p:p ~ smooth@1:smooth ~ < notransparent@3:notrans | notransparency@3:notrans | transparent@1 rgb@n %f:colorR :@n %f:colorG :@n %f:colorB > ~ rotate@1 %A:rotation ~ < width@1 %D:width | height@1 %D:height > ) if@2:directive = %E:criterion CODEBLOCK:code [ else@4 if@1 %E:criterion CODEBLOCK:code_elif ]:0elifs { else CODEBLOCK:code_else } < list@3:directive | ls@2:directive:list > = load@4:directive = < %S:filename | %q:filename > local@5:directive = [ %v:var_name ]:var_names, < maximise@3:directive | maximize@3:directive:maximise > = %e:expression via@1 [ %v:fit_variable ]:fit_variables, < minimise@3:directive | minimize@3:directive:minimise > = %e:expression via@1 [ %v:fit_variable ]:fit_variables, move@3:directive = { item@1 } %d:moveno to@1 %p:p { rotate@1 %A:rotation } ?@n:directive:help = %r:topic !@n:directive:pling = %r:cmd piechart@3:directive = { item@1 %d:editno } < [ %e:expression ]:expression_list: > ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ label@1 { < auto@1:piekeypos | inside@1:piekeypos | key@1:piekeypos | outside@1:piekeypos > } { %E:label } ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ~ with@1 ( < linetype@5 | lt@2 > %dE:linetype ~ < linewidth@5 | lw@2 > %fE:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %cE:color ) ~ format@1 < auto@3:auto_format | %E:format_string > ) DATABLOCK:data < plot@1:directive = { item@1 %d:editno } { 3d@2:threedim } | replot@3:directive = { item@1 %d:editno } > [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list [ { parametric@1:parametric { [@n %u:tmin < :@n | to@n > %u:tmax ]@n { [@n %u:vmin < :@n | to@n > %u:vmax ]@n } } } [ %e:expression ]:expression_list: ( axes@1 %a:axis_1 %a:axis_2 { %a:axis_3 } ~ every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ label@1 %E:label ~ select@1 %E:select_criterion { < continuous@1:continuous | discontinuous@1:discontinuous > } ~ < title@1 %q:title | notitle@3:notitle > ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ~ with@1 ( < linetype@5 | lt@2 > %dE:linetype ~ < linewidth@5 | lw@2 > %fE:linewidth ~ < pointsize@7 | ps@2 > %fE:pointsize ~ < pointtype@6 | pt@2 > %dE:pointtype ~ style@2 %d:style_number ~ < pointlinewidth@6 | plw@3 > %fE:pointlinewidth ~ < colour@1 | color@1 > %cE:color ~ < fillcolour@2 | fillcolor@2 | fc@2 > %cE:fillcolor ~ < lines@1:style | points@1:style | lp@2:style:linespoints | linespoints@5:style | pl@2:style:linespoints | pointslines@5:style:linespoints | errorbars@6:style:yerrorbars | xerrorbars@1:style | yerrorbars@1:style | zerrorbars@1:style | xyerrorbars@3:style | xzerrorbars@3:style | yzerrorbars@3:style | xyzerrorbars@3:style | errorrange@6:style:yerrorrange | xerrorrange@1:style | yerrorrange@1:style | zerrorrange@1:style | xyerrorrange@3:style | xzerrorrange@3:style | yzerrorrange@3:style | xyzerrorrange@3:style | filledregion@3:style | yerrorshaded@8:style | upperlimits@1:style | lowerlimits@2:style | dots@1:style | impulses@1:style | boxes@1:style | wboxes@1:style | steps@1:style | fsteps@1:style | histeps@1:style | stars@3:style | arrows@3:style:arrows_head | arrows_head@3:style | arrows_nohead@3:style | arrows_twoway@3:style:arrows_twohead | arrows_twohead@3:style | surface@2:style | colormap@3:style | colourmap@4:style:colormap | colmap@4:style:colormap | contourmap@3:style | contours@3:style:contourmap > ) ) ]:0plot_list, DATABLOCK:data point@5:directive = { item@1 %d:editno } { at@2 } %p:p { label@1 %q:label } { with@1 ( < pointsize@7 | ps@2 > %fE:pointsize ~ < pointtype@6 | pt@2 > %dE:pointtype ~ style@2 %d:style_number ~ < pointlinewidth@6 | plw@3 > %fE:pointlinewidth ~ < colour@1 | color@1 > %c:color ) } polygon@5:directive = { item@1 %d:editno } %o:pointlist { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < fillcolour@1 | fillcolor@1 | fc@2 > %c:fillcolor ) } print@2:directive = [ %o:expression ]:0print_list, pwd@3:directive = quit@4:directive = refresh@3:directive = reset@5:directive = return@3:directive = { %o:return_value } save@3:directive = < %S:filename | %q:filename > set@2:directive { item@1 %d:editno } %a:axis format@1:set_option:xformat = < auto@3:auto_format | %E:format_string > { < horizontal@1:orient | vertical@1:orient | rotate@1:orient %A:rotation > } set@2:directive { item@1 %d:editno } %a:axis label@1:set_option:xlabel = ( rotate@3 %A:rotation ~ %q:label_text ) set@2:directive { item@1 %d:editno } %a:axis range@1:set_option = < reversed@1:reverse | noreversed@3:noreverse | [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n { < reversed@1:reverse | noreversed@3:noreverse > } > set@2:directive { item@1 %d:editno } { m@n:minor } { %a:axis } < tics@1:set_option | ticks@1:set_option:tics > = { < axis@2:dir:inwards | border@3:dir:outwards | inwards@2:dir | outwards@3:dir | both@3:dir > } { < autofreq@3:autofreq | (@n:got_list [ %o:x { %o:label } ]:0tick_list, )@n | %u:start { ,@n %u:increment { ,@n %u:end } } > } set@2:directive { item@1 %d:editno } arrow@1:set_option = %d:arrow_id { from@1 } { < first@1:x0_system | second@1:x0_system | page@2:x0_system | graph@1:x0_system | axis@n:x0_system %d:x0_axis > } %u:x0 ,@n { < first@1:y0_system | second@1:y0_system | page@2:y0_system | graph@1:y0_system | axis@n:y0_system %d:y0_axis > } %u:y0 { ,@n { < first@1:z0_system | second@1:z0_system | page@2:z0_system | graph@1:z0_system | axis@n:z0_system %d:z0_axis > } %u:z0 } to@1 { < first@1:x1_system | second@1:x1_system | page@2:x1_system | graph@1:x1_system | axis@n:x1_system %d:x1_axis > } %u:x1 ,@n { < first@1:y1_system | second@1:y1_system | page@2:y1_system | graph@1:y1_system | axis@n:y1_system %d:y1_axis > } %u:y1 { ,@n { < first@1:z1_system | second@1:z1_system | page@2:z1_system | graph@1:z1_system | axis@n:z1_system %d:z1_axis > } %u:z1 } { with@1 ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ style@2 %d:style_number ~ < colour@1 | color@1 > %c:color ~ < nohead@2:arrow_style | head@2:arrow_style | twohead@2:arrow_style:twoway | twoway@2:arrow_style > ) } set@2:directive { item@1 %d:editno } autoscale@2:set_option = { [ %a:axis ]:0axes } set@2:directive { item@1 %d:editno } < axescolor@5:set_option | axescolour@5:set_option:axescolor > = %c:color set@2:directive { item@1 %d:editno } axis@1:set_option = [ %a:axis ]:axes ( < invisible@1:invisible | visible@1:visible > ~ < top@2:xorient:on | bottom@2:xorient:off | left@2:yorient:off | right@2:yorient:on | front@2:zorient:off | back@2:zorient:on > ~ < automirrored@2:mirror | mirrored@1:mirror | nomirrored@2:mirror:nomirror | fullmirrored@2:mirror > ~ < atzero@2:atzero | notatzero@4:notatzero > ~ < arrow@2:axisdisp | noarrow@3:axisdisp | twowayarrow@2:axisdisp | reversearrow@2:axisdisp > ~ < notlinked@4:notlinked | linked@1:linked { item@1 %d:linktoid } %a:linkaxis { using@1 %e:usingexp } > ) set@2:directive { item@1 %d:editno } axisunitstyle@5:set_option = < bracketed@1:unitstyle | ratio@1:unitstyle | squarebracketed@1:unitstyle > set@2:directive backup@1:set_option = set@2:directive { item@1 %d:editno } bar@2:set_option = { < large@1:bar_size_large | small@1:bar_size_small | %f:bar_size > } set@2:directive { item@1 %d:editno } binorigin@4:set_option = < auto@4:auto | %u:bin_origin > set@2:directive { item@1 %d:editno } binwidth@4:set_option = < auto@4:auto | %u:bin_width > set@2:directive { item@1 %d:editno } boxfrom@4:set_option = < auto@4:auto | %u:box_from > set@2:directive { item@1 %d:editno } boxwidth@1:set_option = < auto@4:auto | %u:box_width > set@2:directive { item@1 %d:editno } c1format@1:set_option = < auto@1:auto_format | %E:format_string > { < horizontal@1:orient | vertical@1:orient | rotate@1:orient %A:rotation > } set@2:directive { item@1 %d:editno } c1label@3:set_option = ( rotate@3 %A:rotation ~ %q:label_text ) set@2:directive { item@1 %d:editno } { m@n:minor } < c1tics@1:set_option | c1ticks@1:set_option:c1tics > = { < axis@2:dir:inwards | border@3:dir:outwards | inwards@2:dir | outwards@3:dir | both@3:dir > } { < autofreq@3:autofreq | (@n:got_list [ %o:x { %o:label } ]:0tick_list, )@n | %u:start { ,@n %u:increment { ,@n %u:end } } > } set@2:directive calendar@1:set_option = < < gregorian@1:calendar:Gregorian | julian@1:calendar:Julian | british@1:calendar:British | french@1:calendar:French | papal@1:calendar:Papal | russian@1:calendar:Russian | greek@5:calendar:Greek | muslim@1:calendar:Islamic | islamic@1:calendar:Islamic | jewish@2:calendar:Hebrew | hebrew@1:calendar:Hebrew > | ( input@2 < gregorian@1:calendarin:Gregorian | julian@1:calendarin:Julian | british@1:calendarin:British | french@1:calendarin:French | papal@1:calendarin:Papal | russian@1:calendarin:Russian | greek@5:calendarin:Greek | muslim@1:calendar:Islamic | islamic@1:calendar:Islamic | jewish@2:calendar:Hebrew | hebrew@1:calendar:Hebrew > ~ output@2 < gregorian@1:calendarout:Gregorian | julian@1:calendarout:Julian | british@1:calendarout:British | french@1:calendarout:French | papal@1:calendarout:Papal | russian@1:calendarout:Russian | greek@5:calendarout:Greek | muslim@1:calendar:Islamic | islamic@1:calendar:Islamic | jewish@2:calendar:Hebrew | hebrew@1:calendar:Hebrew > ) > set@2:directive { item@1 %d:editno } clip@2:set_option = set@2:directive { item@1 %d:editno } < colkey@4:set_option | colourkey@7:set_option:colkey | colorkey@6:set_option:colkey > = { < left@1:pos | right@1:pos | outside@1:pos:right | top@1:pos | above@1:pos:top | bottom@1:pos | below@1:pos:bottom > } set@2:directive { item@1 %d:editno } < colmap@4:set_option | colourmap@7:set_option:colmap | colormap@6:set_option:colmap > = %E:color { < mask@1 %E:mask | nomask@1:nomask > } set@2:directive { item@1 %d:editno } contours@3:set_option = ( < label@3:label | nolabel@5:nolabel > ~ < (@n [ %u:contour ]:contour_list, )@n | %d:contours > ) set@2:directive { item@1 %d:editno } c@n < 1@n:c_number | 2@n:c_number | 3@n:c_number | 4@n:c_number > range@2:set_option:crange = ( < reversed@1:reverse | noreversed@3:noreverse > ~ [@n { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } ]@n ~ < renormalise@3:renormalise | renormalize@3:renormalise | norenormalise@3:norenormalise | norenormalize@3:norenormalise > ) set@2:directive < { item@1 %d:editno } < data@1:dataset_type style@1:set_option | style@2:set_option data@1:dataset_type | function@1:dataset_type style@1:set_option | style@2:set_option function@1:dataset_type > | style@2:set_option:style_numbered %d:style_set_number > = ( < linetype@5 | lt@2 > %d:linetype ~ < linewidth@5 | lw@2 > %f:linewidth ~ < pointsize@7 | ps@2 > %f:pointsize ~ < pointtype@6 | pt@2 > %d:pointtype ~ style@2 %d:style_number ~ < pointlinewidth@6 | plw@3 > %f:pointlinewidth ~ < colour@1 | color@1 > %c:color ~ < fillcolour@2 | fillcolor@2 | fc@2 > %c:fillcolor ~ < lines@1:style | points@1:style | lp@2:style:linespoints | linespoints@5:style | pl@2:style:linespoints | pointslines@5:style:linespoints | errorbars@6:style:yerrorbars | xerrorbars@1:style | yerrorbars@1:style | zerrorbars@1:style | xyerrorbars@3:style | xzerrorbars@3:style | yzerrorbars@3:style | xyzerrorbars@3:style | errorrange@6:style:yerrorrange | xerrorrange@1:style | yerrorrange@1:style | zerrorrange@1:style | xyerrorrange@3:style | xzerrorrange@3:style | yzerrorrange@3:style | xyzerrorrange@3:style | filledregion@3:style | yerrorshaded@8:style | upperlimits@1:style | lowerlimits@2:style | dots@1:style | impulses@1:style | boxes@1:style | wboxes@1:style | steps@1:style | fsteps@1:style | histeps@1:style | arrows@3:style:arrows_head | arrows_head@3:style | arrows_nohead@3:style | arrows_twoway@3:style:arrows_twohead | arrows_twohead@3:style | surface@2:style | colormap@3:style | colourmap@4:style:colormap | colmap@4:style:colormap | contourmap@3:style > ) set@2:directive display@1:set_option = set@2:directive filter@2:set_option = < %S:filename | %q:filename > < %S:filter | %q:filter > set@2:directive { item@1 %d:editno } < fountsize@2set_option:fontsize | fontsize@2:set_option > = %f:fontsize set@2:directive { item@1 %d:editno } grid@1:set_option = [ %a:axis ]:0axes set@2:directive { item@1 %d:editno } < gridmajcolor@6:set_option | gridmajcolour@6:set_option:gridmajcolor > = %c:color set@2:directive { item@1 %d:editno } < gridmincolor@6:set_option | gridmincolour@6:set_option:gridmincolor > = %c:color set@2:directive { item@1 %d:editno } key@1:set_option = < below@2:pos | above@2:pos | outside@1:pos | ( < left@1:xpos | right@1:xpos | xcenter@1:xpos | xcentre@1:xpos:xcenter > ~ < top@1:ypos | bottom@2:ypos | ycenter@1:ypos | ycentre@1:ypos:ycenter > ) > { %p:offset } set@2:directive { item@1 %d:editno } < keycolumns@4:set_option | keycols@4:set_option:keycolumns > = < auto@4:auto_columns | %d:key_columns > set@2:directive { item@1 %d:editno } label@2:set_option = %d:label_id < %q:label_text > { at@1 } { < first@1:x_system | second@1:x_system | page@2:x_system | graph@1:x_system | axis@n:x_system %d:x_axis > } %u:x ,@n { < first@1:y_system | second@1:y_system | page@2:y_system | graph@1:y_system | axis@n:y_system %d:y_axis > } %u:y { ,@n { < first@1:z_system | second@1:z_system | page@2:z_system | graph@1:z_system | axis@n:z_system %d:z_axis > } %u:z } ( rotate@1 %A:rotation ~ gap@1 %D:gap ~ halign@2 < left@1:halign | center@1:halign | centre@1:halign:center | right@1:halign > ~ valign@2 < top@1:valign | center@1:valign | centre@1:valign:center | bottom@1:valign > ~ with@1 ( < colour@1 | color@1 > %c:color ~ < fontsize@2 | fs@2 | fountsize@3 > %f:fontsize ) ) set@2:directive { item@1 %d:editno } < linewidth@5:set_option | lw@2:set_option:linewidth > = %f:linewidth set@2:directive { item@1 %d:editno } logscale@1:set_option = { [ < %a:axis | t@n:tlog | u@n:ulog | v@n:vlog | c1@n:c1log | c2@n:c2log | c3@n:c3log | c4@n:c4log > ]:0axes } { %d:base } set@2:directive multiplot@1:set_option = set@2:directive { item@1 %d:editno } noarrow@3:set_option = [ %d:arrow_id ]:0arrow_list, set@2:directive:unset { item@1 %d:editno } noaxis@3:set_option:axis = [ %a:axis ]:axes set@2:directive nobackup@3:set_option = set@2:directive { item@1 %d:editno } noclip@4:set_option = set@2:directive { item@1 %d:editno } < nocolkey@4:set_option | nocolourkey@4:set_option:nocolkey | nocolorkey@4:set_option:nocolkey > = set@2:directive nodisplay@3:set_option = set@2:directive { item@1 %d:editno } nogrid@3:set_option = [ %a:axis ]:0axes set@2:directive { item@1 %d:editno } nokey@3:set_option = set@2:directive { item@1 %d:editno } nolabel@4:set_option = [ %d:label_id ]:0label_list, set@3:directive { item@1 %d:editno } no@n %a:axis label@1:set_option:noxlabel = set@3:directive { item@1 %d:editno } no@n c1label@3:set_option:noc1label = set@2:directive { item@1 %d:editno } nostyle@3:set_option < data@3:dataset_type | function@4:dataset_type | [ %d:id ]:0style_ids, > = set@2:directive { item@1 %d:editno } < nologscale@3:set_option | linearscale@3:set_option:nologscale > = { [ < %a:axis | t@n:tlog | u@n:ulog | v@n:vlog | c1@n:c1log | c2@n:c2log | c3@n:c3log | c4@n:c4log > ]:0axes } set@2:directive nomultiplot@3:set_option = set@2:directive { item@1 %d:editno } no@n { m@n:minor } { %a:axis } < tics@1:set_option:notics | ticks@1:set_option:notics > = set@2:directive { item@1 %d:editno } no@n { m@n:minor } < c1tics@1:set_option:noc1tics | c1ticks@1:set_option:noc1tics > = set@2:directive { item@1 %d:editno } noc1format@1:set_option = set@2:directive { item@1 %d:editno } notitle@3:set_option = set@2:directive { item@1 %d:editno } no@n %a:axis format@1:set_option:noxformat = set@2:directive numerics@2:set_option = ( < sigfig@3 | sf@2 > %d:number_significant_figures ~ errors@2 < explicit@1:errortype:on | nan@1:errortype:off | quiet@1:errortype:off | nonan@3:errortype:on | noquiet@3:errortype:on | noexplicit@3:errortype:off > ~ < complex@1:complex:on | real@1:complex:off | nocomplex@3:complex:off | noreal@3:complex:on > ~ display@1 < typeable@1:display | natural@2:display | latex@1:display | tex@1:display:latex > ) set@2:directive { item@1 %d:editno } origin@2:set_option = %p:origin set@2:directive { item@1 %d:editno } output@1:set_option = < %S:filename | %q:filename > set@2:directive { item@1 %d:editno } palette@3:set_option = < from@4 %o:list | [ %c:color ]:palette, > set@2:directive papersize@3:set_option = < dimensions@3 %p:size | %S:paper_name | %q:paper_name > set@2:directive { item@1 %d:editno } < pointlinewidth@6:set_option | plw@3:set_option:pointlinewidth > = %f:pointlinewidth set@2:directive { item@1 %d:editno } < pointsize@1:set_option | ps@2:set_option:pointsize > = %f:pointsize set@2:directive { item@1 %d:editno } preamble@2:set_option = < %q:preamble | %r:preamble > set@2:directive { item@1 %d:editno } samples@2:set_option = ( grid@2 < %d:samplesX | *@n:samplesXauto > { x@n } < %d:samplesY | *@n:samplesYauto > ~ interpolate@3 < inversesquare@1:method | monaghanlattanzio@1:method | nearestneighbour@1:method:nearestneighbor | nearestneighbor@1:method > ~ %d:samples ) set@2:directive seed@2:set_option = %f:seed set@2:directive { item@1 %d:editno } size@1:set_option = ( < height@1 %D:height | ratio@1 < auto@3:noratio | %f:ratio > | noratio@1:noratio | square@1:square > ~ < zsize@2 %d:depth | zratio@1 < auto@3:nozratio | %f:zratio > | nozratio@1:nozratio > ~ %D:width ) set@2:directive terminal@1:set_option = ( < x11_singlewindow@1:term:X11_SingleWindow | x11_multiwindow@5:term:X11_MultiWindow | x11_persist@5:term:X11_Persist | postscript@1:term:ps | ps@2:term:ps | eps@1:term:eps | pdf@2:term:pdf | png@2:term:png | gif@1:term:gif | jpg@1:term:jpg | jpeg@1:term:jpg | bmp@1:term:bmp | tiff@1:term:tif | svg@1:term:svg > ~ < colour@1:col:on | color@1:col:on | monochrome@1:col:off | nocolour@1:col:off | nocolor@1:col:off > ~ < enlarge@1:enlarge:on | noenlarge@3:enlarge:off > ~ < landscape@1:land:on | portrait@2:land:off > ~ < notransparency@3:trans:off | notransparent@3:trans:off | nosolid@3:trans:on | transparent@1:trans:on | solid@1:trans:off > ~ < invert@1:invert:on | noinvert@1:invert:off > ~ < antialias@1:antiali:on | noantialias@3:antiali:off > ~ < dpi@3 | resolution@3 > %f:dpi ) set@2:directive { item@1 %d:editno } < textcolor@5:set_option | textcolour@5:set_option:textcolor > = %c:color set@2:directive { item@1 %d:editno } texthalign@5:set_option = < left@1:left | centre@1:center | center@1:center | middle@1:center | right@1:right > set@2:directive { item@1 %d:editno } textvalign@5:set_option = < top@1:top | centre@1:center | center@1:center | middle@1:center | bottom@1:bottom > set@2:directive timezone@3:set_option = %q:timezone set@2:directive { item@1 %d:editno } title@2:set_option = < %q:title > { %p:offset } set@2:directive { item@1 %d:editno } trange@2:set_option = { [@n:range { %u:min } < :@n | to@n > { %u:max } ]@n } { reverse@1:reverse } set@2:directive unit@1:set_option = ( angle@1 < dimensionless@1:angle:on | nodimensionless@1:angle:off > ~ display@1 ( < abbreviated@1:abbrev:on | noabbreviated@3:abbrev:off | full@1:abbrev:off | nofull@3:abbrev:on > ~ < prefix@1:prefix:on | noprefix@3:prefix:off > ) ~ scheme@1 < si@2:scheme:SI | cgs@1:scheme:CGS | ancient@1:scheme:ANCIENT | imperial@1:scheme:IMPERIAL | uscustomary@1:scheme:USCustomary | planck@1:scheme:PLANCK | natural@1:scheme:PLANCK > ~ [ of@1 %s:quantity %v:unit ]:preferred_units, ~ preferred@2 %e:preferred_unit ~ nopreferred@3 %e:unpreferred_unit ) set@2:directive { item@1 %d:editno } urange@2:set_option = { [@n:range { %u:min } < :@n | to@n > { %u:max } ]@n } { reverse@1:reverse } set@2:directive { item@1 %d:editno } view@1:set_option = %A:xy_angle { ,@n } %A:yz_angle set@2:directive viewer@5:set_option = < auto@4:auto_viewer | %r:viewer > set@2:directive { item@1 %d:editno } vrange@2:set_option = { [@n:range { %u:min } < :@n | to@n > { %u:max } ]@n } { reverse@1:reverse } set@2:directive { item@1 %d:editno } width@1:set_option = %D:width set@2:directive:set_error = { item@1 %d:editno } { %s:set_option } %r:restofline show@2:directive = { item@1 %d:editno } [ %S:setting ]:0setting_list solve@4:directive = [ %g:left_expression =@n %g:right_expression ]:expressions, via@1 [ %v:fit_variable ]:fit_variables, < spline@3:directive = | interpolate@4 = < akima@1:directive | linear@2:directive | loglinear@2:directive | polynomial@1:directive | spline@2:directive | stepwise@2:directive | 2d@2:directive:interpolate2d { < bmp_r:bmp | bmp_g:bmp | bmp_b:bmp > } > > [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list [ %v:varname ]:varnames. ()@2 { parametric@1:parametric { [@n %u:tmin < :@n | to@n > %u:tmax ]@n { [@n %u:vmin < :@n | to@n > %u:vmax ]@n } } } [ %e:expression ]:expression_list: ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ) DATABLOCK:data subroutine@4:directive = [ %v:subroutine_name ]:subroutine_names. (@n [ %v:argument_name ]:0argument_list, )@n CODEBLOCK:code swap@4:directive = %d:item1 %d:item2 tabulate@5:directive = [ [@n { { < %u:min | *@n:minauto > } < :@n | to@n > { < %u:max | *@n:maxauto > } } ]@n ]:0range_list [ { parametric@1:parametric { [@n %u:tmin < :@n | to@n > %u:tmax ]@n { [@n %u:vmin < :@n | to@n > %u:vmax ]@n } } } [ %e:expression ]:expression_list: ( every@1 [ { %d:every_item } ]:every_list: ~ index@1 %d:index ~ select@1 %E:select_criterion ~ sortby %E:sort_expression ~ using@1 { < rows@1:use_rows | columns@1:use_columns > } [ { %E:using_item } ]:using_list: ) { with@1 ( format@1 %q:format ~ spacing@1 %u:spacing ) } ]:0tabulate_list, DATABLOCK:data text@4:directive = { item@1 %d:editno } < %q:string > ( at@1 %p:p ~ rotate@1 %A:rotation ~ gap@1 %D:gap ~ halign@2 < left@1:halign | center@1:halign | centre@1:halign:center | right@1:halign > ~ valign@2 < top@1:valign | center@1:valign | centre@1:valign:center | bottom@1:valign > ~ with@1 < colour@1 | color@1 > %c:color ) undelete@5:directive = { item@1 } [ %d:number ]:undeleteno, unset@3:directive { item@1 %d:editno } { no@n } %a:axis format@1:set_option:xformat = unset@3:directive { item@1 %d:editno } %a:axis label@1:set_option:xlabel = unset@3:directive { item@1 %d:editno } %a:axis range@1:set_option = unset@3:directive { item@1 %d:editno } { no@n } { m@n:minor } { %a:axis } < tics@1:set_option | ticks@1:set_option:tics > = unset@3:directive { item@1 %d:editno } { no@n } { m@n:minor } < c1tics@1:set_option | c1ticks@1:set_option:c1tics > = unset@3:directive { item@1 %d:editno } arrow@2:set_option = [ %d:arrow_id ]:0arrow_list, unset@3:directive { item@1 %d:editno } autoscale@2:set_option = { [ %a:axis ]:axes } unset@3:directive { item@1 %d:editno } < axescolor@5:set_option | axescolour@5:set_option:axescolor > = unset@3:directive { item@1 %d:editno } axis@2:set_option = [ %a:axis ]:0axes unset@3:directive { item@1 %d:editno } axisunitstyle@5:set_option = unset@3:directive backup@1:set_option = unset@3:directive { item@1 %d:editno } bar@2:set_option = unset@3:directive binorigin@4:set_option = unset@3:directive binwidth@4:set_option = unset@3:directive { item@1 %d:editno } boxfrom@4:set_option = unset@3:directive { item@1 %d:editno } boxwidth@1:set_option = unset@3:directive { item@1 %d:editno } { no@n } c1format@1:set_option = unset@3:directive { item@1 %d:editno } c1label@3:set_option = unset@3:directive calendar@1:set_option = unset@3:directive { item@1 %d:editno } clip@2:set_option = unset@3:directive { item@1 %d:editno } < colkey@4:set_option | colourkey@7:set_option:colkey | colorkey@6:set_option:colkey > = unset@3:directive { item@1 %d:editno } < colmap@4:set_option | colourmap@7:set_option:colmap | colormap@6:set_option:colmap > = unset@3:directive { item@1 %d:editno } contours@3:set_option = unset@3:directive { item@1 %d:editno } c@n < 1@n:c_number | 2@n:c_number | 3@n:c_number | 4@n:c_number > range@2:set_option:crange = unset@3:directive display@1:set_option = unset@3:directive filter@2:set_option = < %S:filename | %q:filename > unset@3:directive { item@1 %d:editno } < fountsize@2:set_option:fontsize | fontsize@2:set_option > = unset@3:directive { item@1 %d:editno } grid@1:set_option = unset@3:directive { item@1 %d:editno } < gridmajcolor@6:set_option | gridmajcolour@6:set_option:gridmajcolor > = unset@3:directive { item@1 %d:editno } < gridmincolor@6:set_option | gridmincolour@6:set_option:gridmincolor > = unset@3:directive { item@1 %d:editno } key@1:set_option = unset@3:directive { item@1 %d:editno } < keycolumns@4:set_option | keycols@4:set_option:keycolumns > = unset@3:directive { item@1 %d:editno } label@2:set_option = [ %d:label_id ]:0label_list, unset@3:directive { item@1 %d:editno } < data@3:dataset_type style@3:set_option = | function@4:dataset_type style@3:set_option = | < nostyle@4:set_option:style | style@2:set_option:style > = < data@1:dataset_type | function@1:dataset_type | [ %d:id ]:0style_ids, > > unset@3:directive { item@1 %d:editno } < linewidth@5:set_option | lw@2:set_option:linewidth > = unset@3:directive { item@1 %d:editno } < logscale@2:set_option | linearscale@5:set_option:logscale > = { [ < %a:axis | t@n:tlog | u@n:ulog | v@n:vlog | c1@n:c1log | c2@n:c2log | c3@n:c3log | c4@n:c4log > ]:0axes } unset@3:directive multiplot@1:set_option = unset@3:directive { item@1 %d:editno } noarrow@3:set_option:arrow = [ %d:arrow_id ]:0arrow_list, unset@3:directive { item@1 %d:editno } noaxis@4:set_option:axis = [ %a:axis ]:axes unset@3:directive { item@1 %d:editno } nobackup@3:set_option:backup = unset@3:directive { item@1 %d:editno } noclip@4:set_option:clip = unset@3:directive { item@1 %d:editno } < nocolkey@4:set_option:colkey | nocolourkey@4:set_option:colkey | nocolorkey@4:set_option:colkey > = unset@3:directive { item@1 %d:editno } nodisplay@3:set_option:display = unset@3:directive { item@1 %d:editno } nogrid@3:set_option:grid = unset@3:directive { item@1 %d:editno } nokey@3:set_option:key = unset@3:directive { item@1 %d:editno } nolabel@4:set_option:label = [ %d:label_id ]:0label_list, unset@3:directive { item@1 %d:editno } < nolinewidth@7:set_option:linewidth | nolw@4:set_option:linewidth > unset@3:directive { item@1 %d:editno } nologscale@3:set_option:logscale = { [ < %a:axis | t@n:tlog | u@n:ulog | v@n:vlog | c1@n:c1log | c2@n:c2log | c3@n:c3log | c4@n:c4log > ]:axes } unset@3:directive { item@1 %d:editno } nomultiplot@3:set_option:multiplot = unset@3:directive { item@1 %d:editno } notitle@3:set_option:title = unset@3:directive numerics@2:set_option = { < sigfig@3:set_option:numerics_sigfig | sf@2:set_option:numerics_sigfig | errors@2:set_option:numerics_errors | complex@1:set_option:numerics_complex | real@1:set_option:numerics_complex | nocomplex@3:set_option:numerics_complex | noreal@3:set_option:numerics_complex | display@1:set_option:numerics_display > } unset@3:directive { item@1 %d:editno } origin@2:set_option = unset@3:directive { item@1 %d:editno } output@1:set_option = unset@3:directive { item@1 %d:editno } palette@1:set_option = unset@3:directive papersize@3:set_option = unset@3:directive { item@1 %d:editno } < pointlinewidth@6:set_option | plw@3:set_option:pointlinewidth > = unset@3:directive { item@1 %d:editno } < pointsize@1:set_option | ps@2:set_option:pointsize > = unset@3:directive { item@1 %d:editno } preamble@2:set_option = unset@3:directive { item@1 %d:editno } samples@2:set_option = unset@3:directive seed@2:set_option = unset@3:directive:set { item@1 %d:editno } < axis@1:set_option:noaxis | noaxis@3:set_option > = [ %a:axis ]:axes unset@3:directive { item@1 %d:editno } size@1:set_option = unset@3:directive terminal@1:set_option = unset@3:directive { item@1 %d:editno } < textcolor@5:set_option | textcolour@5:set_option:textcolor > = unset@3:directive { item@1 %d:editno } texthalign@5:set_option = unset@3:directive { item@1 %d:editno } textvalign@5:set_option = unset@3:directive { item@1 %d:editno } title@2:set_option = unset@3:directive { item@1 %d:editno } trange@2:set_option = unset@3:directive unit@1:set_option = { < display@1:set_option:unit_display | scheme@1:set_option:unit_scheme | of@1:set_option:unit_of %s:quantity | preferred@1:set_option:unit_preferred > } unset@3:directive { item@1 %d:editno } urange@2:set_option = unset@3:directive { item@1 %d:editno } view@1:set_option = unset@3:directive viewer@1:set_option = unset@3:directive { item@1 %d:editno } vrange@2:set_option = unset@3:directive { item@1 %d:editno } width@1:set_option = unset@3:directive:unset_error = { item@1 %d:editno } { %s:set_option } %r:restofline while@5:directive = %e:criterion { loopname@1 %v:loopname } CODEBLOCK:code with@4:directive = %o:namespace CODEBLOCK:code %e:directive = pyxplot-0.9.2/buildScripts/manpage_pyxplot.py0000664000175000017500000000607412026340554020063 0ustar dcf21dcf21# manpage_pyxplot.py # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: manpage_pyxplot.py 1273 2012-07-20 00:18:37Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # Generate manpage for Pyxplot import sys docpath = sys.argv[1] author = open("AUTHORS","r").read() description = "" f = open("README","r") state = 0 for line in f.readlines(): if (line[0:2] == "1."): state = 1 elif (line[0:2] == "2."): state = 2 elif (state == 1) : description += line sys.stdout.write(r""" .\" pyxplot.1 .\" .\" The manpage in this file is part of Pyxplot .\" .\" .\" Copyright (C) 2006-2012 Dominic Ford .\" 2008-2012 Ross Church .\" .\" $Id: manpage_pyxplot.py 1273 2012-07-20 00:18:37Z dcf21 $ .\" .\" Pyxplot 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. .\" .\" You should have received a copy of the GNU General Public License along with .\" Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin .\" Street, Fifth Floor, Boston, MA 02110-1301, USA .\" .\" ---------------------------------------------------------------------------- .\" Man page for pyxplot .TH PYXPLOT 1 .SH NAME pyxplot \- a multi-purpose command-line data processing, vector graphics and graph-plotting tool. .SH SYNOPSIS .B pyxplot [file ...] .SH DESCRIPTION %s Full documentation can be found in: %s .SH COMMAND LINE OPTIONS \-h, \-\-help: Display this help. \-v, \-\-version: Display version number. \-q, \-\-quiet: Turn off initial welcome message. \-V, \-\-verbose: Turn on initial welcome message. \-c, \-\-color: Use colored highlighting of output. \-m, \-\-monochrome: Turn off coloured highlighting. .SH AUTHORS %s. .SH BUGS AND USER FORUMS To report bugs in Pyxplot, or to meet other Pyxplot users in our forums, please visit us on sourceforge: . .SH CREDITS Matthew Smith, Michael Rutter, Zoltan Voros and John Walker have all contributed code to Pyxplot. We welcome bug reports, which can be submitted to our project page on Sourceforge, and thank the many testers who have already made significant contributions to the project by helping us to track down bugs. .SH "SEE ALSO" .BR pyxplot_watch (1), gnuplot (1) """%(description,docpath,author)) pyxplot-0.9.2/buildScripts/parser_data.py0000664000175000017500000001447212026340554017142 0ustar dcf21dcf21# parser_data.py # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: parser_data.py 1261 2012-07-11 21:38:05Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # Generate table of positions of variables by name globalVarNames = [] globalVarTable = {} def processVarTable(vt, directive, setOption): global globalVarNames,globalVarTable if '%' in directive: return key = "%s_%s"%(directive,setOption) globalVarTable[key] = vt for name,pos in vt.iteritems(): if name not in globalVarNames: globalVarNames.append(name) def printVarTable(): global globalVarNames,globalVarTable,f_h,f_c globalVarNames.sort() for i in range(len(globalVarNames)): f_h.write("#define PARSE_INDEX_%s %d\n"%(sanitize(globalVarNames[i]),i)) keys = globalVarTable.keys() keys.sort() for k in keys: d = globalVarTable[k] f_h.write("extern const int PARSE_TABLE_%s[];\n"%k) f_c.write("const int PARSE_TABLE_%s[] = {"%k) for i in range(len(globalVarNames)): item = globalVarNames[i] if (i!=0) : f_c.write(",") if item in d: f_c.write("%d"%d[item]) else : f_c.write("-1"); f_c.write("};\n") # Generate specification of commands that Pyxplot recognises def sanitize(instr): outstr = "" for i in range(len(instr)): if (instr[i].isalnum() or instr[i]=='_'): outstr+=instr[i] return outstr f_in = open("buildScripts/parser_data.dat","r") # Output C files containing command definitions f_h = open("src/parser/cmdList.h","w") f_c = open("src/parser/cmdList.c","w") includeKeys = {} f_h.write("""// This file autogenerated by parser_data.py #ifndef _CMDLIST_H #define _CMDLIST_H 1 extern const char ppl_cmdList[]; """) f_c.write("""// This file autogenerated by parser_data.py const char ppl_cmdList[] = "\\ """) # Loop through command definitions linecount = 0 for line in f_in: linecount+=1 line = line.strip(); if len(line)<1: continue if line.startswith("#"): continue outline = "" directive = "undefined" setoption = "" stack = [] stack_varnames = [] listsizes = [] varnames = {"directive":0 , "editno":1, "set_option":2, "X":3} vartable = varnames.copy() varcount = len(varnames) words = line.split() for word in words: if word in ["=","(","~",")","{","}","<","|",">","["]: # Grammar characters are passed straight through outline += "%s "%word if word=="[": # Lists are placed on the stack, and the number of variables in each list counted stack.append(varcount) stack_varnames.append(varnames) varcount=1 # Start counting from variable 1 inside a list, as first value is pointer to next list item varnames={} continue parts = word[1:].split(":") parts[0] = word[0]+parts[0] # If first character is a colon, it should match a literal :, not act as a separator subparts = parts[0].split("@") # Match string has form plot@1, meaning 'p' is short for 'plot' if len(parts)<2: parts.append("X") # If output variable name is not specified, stick it in 'X'. if len(subparts)>1: if subparts[1]=="n": subparts[1]=-1 # An auto-complete length of 'n' is stored as -1 parts.append("%s"%subparts[1]) parts[0] = subparts[0] else: parts.append("%s"%len(parts[0])) # If no auto-complete length is specified, whole string must be matched if len(parts)==3: parts.insert(2,"") # At this point, parts is [ match string , output variable , string to store (blank if equals match string) , auto-complete len ] assert len(parts)==4, "Syntax error in word '%s'."%word varname = parts[1] if word.startswith("]:"): parts = [ "]" , word[2:] , "" , "1" ] listsizes.append(varcount) varcount=stack.pop() for key,item in varnames.iteritems(): stack_varnames[-1]["%s_%s"%(key,varname)] = item varnames=stack_varnames.pop() if varname=='directive': # Directive names are stored for use in #defines to convert variable names into output slot numbers if parts[2]=="": directive = parts[0] else : directive = parts[2] if varname=='set_option': # Set options are also used in #defines if parts[2]=="": setoption = parts[0]+"_" else : setoption = parts[2]+"_" if (setoption[0]=="%"): setoption="" if varname not in varnames: varnames[varname] = varcount vartable[varname] = varcount if (parts[0]=="%p"): varcount += 2 # Position vectors require 2 or 3 slots elif (parts[0]=="%P"): varcount += 3 else : varcount += 1 # Varcount keeps track of the slot number to place the next variable in elif (parts[0] in ["%p","%P"]): print "Danger in command %s: sharing position variable name with other variables of different lengths"%directive outnum = varnames[varname] parts.append("%s"%outnum) # parts[4] = slot number if word.startswith("]:"): initial = "" parts.append("%s"%listsizes[-1]) # parts[5] = list length for ] (number of slots needed for this list's variables) else: initial = "@" parts.append("0") # ... or zero otherwise outline += initial + "@".join(parts) + " " f_c.write("%d "%(varcount)) # First word on each statement definition line is the number of variables in the root slotspace f_c.write("%s\\n\\\n"%outline) processVarTable(vartable,directive,setoption) for i,j in varnames.iteritems(): if '%' not in directive: key = "PARSE_%s_%s%s"%(directive,setoption,sanitize(i)) if (key in includeKeys) and (includeKeys[key]!=j): print "Repetition of key %s"%key includeKeys[key] = j f_h.write("#define %s %d\n"%(key,j)) # Write #defines to convert variable names into slot numbers # Finish up f_c.write("""";\n"""); printVarTable() f_h.write("""\n\n#endif"""); f_h.close() f_c.close() pyxplot-0.9.2/buildScripts/manpage_pyxplot_watch.py0000664000175000017500000000616312026340554021250 0ustar dcf21dcf21# manpage_pyxplot_watch.py # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: manpage_pyxplot_watch.py 1273 2012-07-20 00:18:37Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # Generate manpage for Pyxplot watcher import sys docpath = sys.argv[1] author = open("AUTHORS","r").read() description = "" sys.stdout.write(r""" .\" pyxplot_watch.1 .\" .\" The manpage in this file is part of Pyxplot .\" .\" .\" Copyright (C) 2006-2012 Dominic Ford .\" 2008-2012 Ross Church .\" .\" $Id: manpage_pyxplot_watch.py 1273 2012-07-20 00:18:37Z dcf21 $ .\" .\" Pyxplot 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. .\" .\" You should have received a copy of the GNU General Public License along with .\" Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin .\" Street, Fifth Floor, Boston, MA 02110-1301, USA .\" .\" ---------------------------------------------------------------------------- .\" Man page for pyxplot_watch .TH PYXPLOT_WATCH 1 .SH NAME pyxplot_watch \- a tool which monitors a collection of Pyxplot command scripts and executes them whenever they are modified. .SH SYNOPSIS .B pyxplot_watch [file ...] .SH DESCRIPTION pyxplot_watch is a part of the Pyxplot plotting package; it is a simple tool for watching Pyxplot command script files, and executing them whenever they are modified. It is should be followed on the commandline by a list of command scripts which are to be watched. Full documentation can be found in: %s .SH COMMAND LINE OPTIONS \-v, \-\-verbose: Verbose mode; output full activity log to terminal \-q, \-\-quiet : Quiet mode; only output Pyxplot error messages to terminal \-h, \-\-help : Display this help \-V, \-\-version: Display version number .SH AUTHORS %s. .SH BUGS AND USER FORUMS To report bugs in Pyxplot, or to meet other Pyxplot users in our forums, please visit us on sourceforge: . .SH CREDITS Matthew Smith, Michael Rutter, Zoltan Voros and John Walker have all contributed code to Pyxplot. We welcome bug reports, which can be submitted to our project page on Sourceforge, and thank the many testers who have already made significant contributions to the project by helping us to track down bugs. .SH "SEE ALSO" .BR pyxplot (1), gnuplot (1) """%(docpath,author)) pyxplot-0.9.2/buildScripts/colorlistGenerate.py0000664000175000017500000001211212026340554020327 0ustar dcf21dcf21# colorlistGenerate.py # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: colorlistGenerate.py 1261 2012-07-11 21:38:05Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- color_list={ "greenYellow": [0.15, 0, 0.69, 0], "yellow": [0, 0, 1, 0], "goldenRod": [0, 0.10, 0.84, 0], "dandelion": [0, 0.29, 0.84, 0], "apricot": [0, 0.32, 0.52, 0], "peach": [0, 0.50, 0.70, 0], "melon": [0, 0.46, 0.50, 0], "yellowOrange": [0, 0.42, 1, 0], "orange": [0, 0.61, 0.87, 0], "burntOrange": [0, 0.51, 1, 0], "bitterSweet": [0, 0.75, 1, 0.24], "redOrange": [0, 0.77, 0.87, 0], "mahogany": [0, 0.85, 0.87, 0.35], "maroon": [0, 0.87, 0.68, 0.32], "brickRed": [0, 0.89, 0.94, 0.28], "red": [0, 1, 1, 0], "orangeRed": [0, 1, 0.50, 0], "rubineRed": [0, 1, 0.13, 0], "wildStrawberry": [0, 0.96, 0.39, 0], "salmon": [0, 0.53, 0.38, 0], "carnationPink": [0, 0.63, 0, 0], "magenta": [0, 1, 0, 0], "violetRed": [0, 0.81, 0, 0], "rhodamine": [0, 0.82, 0, 0], "mulberry": [0.34, 0.90, 0, 0.02], "redViolet": [0.07, 0.90, 0, 0.34], "fuchsia": [0.47, 0.91, 0, 0.08], "lavender": [0, 0.48, 0, 0], "thistle": [0.12, 0.59, 0, 0], "orchid": [0.32, 0.64, 0, 0], "darkOrchid": [0.40, 0.80, 0.20, 0], "purple": [0.45, 0.86, 0, 0], "plum": [0.50, 1, 0, 0], "violet": [0.79, 0.88, 0, 0], "royalPurple": [0.75, 0.90, 0, 0], "blueViolet": [0.86, 0.91, 0, 0.04], "periwinkle": [0.57, 0.55, 0, 0], "cadetBlue": [0.62, 0.57, 0.23, 0], "cornflowerBlue": [0.65, 0.13, 0, 0], "midnightBlue": [0.98, 0.13, 0, 0.43], "navyBlue": [0.94, 0.54, 0, 0], "royalBlue": [1, 0.50, 0, 0], "blue": [1, 1, 0, 0], "cerulean": [0.94, 0.11, 0, 0], "cyan": [1, 0, 0, 0], "processBlue": [0.96, 0, 0, 0], "skyBlue": [0.62, 0, 0.12, 0], "turquoise": [0.85, 0, 0.20, 0], "tealBlue": [0.86, 0, 0.34, 0.02], "aquamarine": [0.82, 0, 0.30, 0], "blueGreen": [0.85, 0, 0.33, 0], "emerald": [1, 0, 0.50, 0], "jungleGreen": [0.99, 0, 0.52, 0], "seaGreen": [0.69, 0, 0.50, 0], "green": [1, 0, 1, 0], "forestGreen": [0.91, 0, 0.88, 0.12], "pineGreen": [0.92, 0, 0.59, 0.25], "limeGreen": [0.50, 0, 1, 0], "yellowGreen": [0.44, 0, 0.74, 0], "springGreen": [0.26, 0, 0.76, 0], "oliveGreen": [0.64, 0, 0.95, 0.40], "rawSienna": [0, 0.72, 1, 0.45], "sepia": [0, 0.83, 1, 0.70], "brown": [0, 0.81, 1, 0.60], "tan": [0.14, 0.42, 0.56, 0], "gray": [0, 0, 0, 0.50], "grey": [0, 0, 0, 0.50], "black": [0, 0, 0, 1], "white": [0, 0, 0, 0], "invisible": [-1, -1, -1, -1], "null": [-1, -1, -1, -1], "transparent": [-1, -1, -1, -1], } for greylevel in range(0,101): color_list["grey%02d"%greylevel] = [0, 0, 0, float(100-greylevel)/100] color_list["gray%02d"%greylevel] = [0, 0, 0, float(100-greylevel)/100] color_names = color_list.keys() color_names.sort() # Write ppl_colors.h output = open("src/settings/epsColors.h","w") output.write("""// This file auto-generated by colorsGenerate.py #ifndef _EPSCOLORS_H #define _EPSCOLORS_H 1 """) for i in range(len(color_names)): output.write("#define COLOR_%s %d\n"%(color_names[i].upper() , i+20000)) output.write("\n#ifndef _EPSCOLORS_C\n") output.write("extern char *SW_COLOR_STR[];\n") output.write("extern int SW_COLOR_DCL[];\n") output.write("extern int SW_COLOR_INT[];\n\n") output.write("extern double SW_COLOR_CMYK_C[];\n") output.write("extern double SW_COLOR_CMYK_M[];\n") output.write("extern double SW_COLOR_CMYK_Y[];\n") output.write("extern double SW_COLOR_CMYK_K[];\n") output.write("#endif\n\n#endif\n") output.close() # Write ppl_colors.c output = open("src/settings/epsColors.c","w") output.write("""// This file auto-generated by colorsGenerate.py #define _EPSCOLORS_C 1 #include "epsColors.h" char *SW_COLOR_STR[] = {""") for i in range(len(color_names)): output.write(""" "%s" , """%color_names[i]) output.write("};\nint SW_COLOR_DCL[] = {") for i in range(len(color_names)): output.write(""" %d , """%len(color_names[i])) output.write("};\nint SW_COLOR_INT[] = {") for i in range(len(color_names)): output.write(""" COLOR_%s , """%(color_names[i].upper())) output.write("-1};\ndouble SW_COLOR_CMYK_C[] = {") for i in range(len(color_names)): output.write(""" %f , """%(color_list[color_names[i]][0])) output.write("};\ndouble SW_COLOR_CMYK_M[] = {") for i in range(len(color_names)): output.write(""" %f , """%(color_list[color_names[i]][1])) output.write("};\ndouble SW_COLOR_CMYK_Y[] = {") for i in range(len(color_names)): output.write(""" %f , """%(color_list[color_names[i]][2])) output.write("};\ndouble SW_COLOR_CMYK_K[] = {") for i in range(len(color_names)): output.write(""" %f , """%(color_list[color_names[i]][3])) output.write("};\n") output.close() pyxplot-0.9.2/configure0000775000175000017500000002474412026340554013546 0ustar dcf21dcf21#!/bin/sh # # Installation script for Pyxplot version 0.9.2 # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: configure 1293 2012-08-28 14:47:56Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # 0. START CONSTRUCTING A MAKEFILE rm -f conf.* echo "" > Makefile echo "PATHLINK=/" > Makefile # 1. TEST THE ECHO COMMAND TO SEE WHICH VARIANT WE HAVE case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in *c*,-n*) ECHO_N= ECHO_C=' ' ECHO_T=' ' ;; *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; *) ECHO_N= ECHO_C='\c' ECHO_T= ;; esac # 2. CHECK FOR LATEX echo $ECHO_N "Checking for latex ............. $ECHO_C" whichout=`which latex 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "LATEX_COMMAND=${whichout}" >> Makefile else echo "NO" ; echo "ERROR: Required program latex could not be found." >&2 ; exit fi # 3. CHECK FOR CONVERT echo $ECHO_N "Checking for ImageMagick convert............ $ECHO_C" whichout=`which convert 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "CONVERT_COMMAND=${whichout}" >> Makefile else echo "NO" ; echo "ERROR: Required program convert could not be found." >&2 ; exit fi # 4. CHECK FOR SED echo $ECHO_N "Checking for sed ............. $ECHO_C" whichout=`which sed 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "SED_COMMAND=${whichout}" >> Makefile else echo "NO" ; echo "ERROR: Required program sed could not be found." >&2 ; exit fi # 5. CHECK FOR GUNZIP echo $ECHO_N "Checking for gunzip ............. $ECHO_C" whichout=`which gunzip 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "GUNZIP_COMMAND=-D GUNZIP_COMMAND=\"\\\"${whichout} -c\\\"\"" >> Makefile else echo "NO" echo "GUNZIP_COMMAND=" >> Makefile echo "WARNING: Gunzip could not be found. Installation will proceed, but Pyxplot will not be able to plot .gz files." >&2 fi # 6. CHECK FOR WGET echo $ECHO_N "Checking for wget ............. $ECHO_C" whichout=`which wget 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "WGET_COMMAND=-D WGET_COMMAND=\"\\\"${whichout} -O -\\\"\"" >> Makefile else echo "NO" echo "WGET_COMMAND=" >> Makefile echo "WARNING: wget could not be found. Installation will proceed, but Pyxplot will not be able to plot files directly from URLs." >&2 fi # 7. CHECK FOR GHOSTSCRIPT echo $ECHO_N "Checking for ghostscript ............. $ECHO_C" whichout=`which gs 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "GS_COMMAND=${whichout}" >> Makefile else echo "NO" ; echo "ERROR: Required program ghostscript could not be found." >&2 ; exit fi # 8. FIND GHOSTVIEW echo $ECHO_N "Checking for ghostview ............. $ECHO_C" whichout_gv=`which gv 2> conf.stderr` rm -f conf.* if test "`echo $whichout_gv | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout_gv="" ; fi if test "$whichout_gv" != "" ; then echo $ECHO_N "YES (gv$ECHO_C" echo "GV_COMMAND=${whichout_gv}" >> Makefile if test "`gv --v 2> conf.stderr`" = "" ; then rm -f conf.* echo ", single hyphen options)" echo "GV_OPT=-" >> Makefile else rm -f conf.* echo ", double hyphen options)" echo "GV_OPT=--" >> Makefile fi else echo "NO" echo "GV_COMMAND=/bin/false" >> Makefile fi # 9. FIND GGV echo $ECHO_N "Checking for ggv ............. $ECHO_C" whichout_ggv=`which ggv 2> conf.stderr` rm -f conf.* if test "`echo $whichout_ggv | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout_ggv="" ; fi if test "$whichout_ggv" != "" ; then echo "YES (ggv, don't forget to set \"watch file\" in the viewer preferences!)" echo "GGV_COMMAND=${whichout_ggv}" >> Makefile else echo "NO" echo "GGV_COMMAND=/bin/false" >> Makefile fi # 10. FIND MAKE echo $ECHO_N "Checking for GNU make ............. $ECHO_C" whichout_make=`which make 2> conf.stderr` whichout_gmake=`which gmake 2> conf.stderr2` rm -f conf.* if test "`echo $whichout_make | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout_make="" ; fi if test "`echo $whichout_gmake | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout_gmake="" ; fi if test "$whichout_gmake" != "" ; then echo "YES (gmake)" echo "MAKE_COMMAND=${whichout_gmake}" >> Makefile MAKE_COMMAND="gmake" elif test "$whichout_make" != "" ; then echo "YES (make)" echo "MAKE_COMMAND=${whichout_make}" >> Makefile MAKE_COMMAND="make" else echo "NO" echo "ERROR: Required program 'make' could not be found." >&2 exit fi # 11. CHECK TO SEE WHETHER THIS SYSTEM HAS GCC INSTALLED echo $ECHO_N "Checking for gcc ............. $ECHO_C" whichout=`which gcc 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" else echo "NO" ; echo "ERROR: Required program gcc could not be found." >&2 ; exit fi # 12. CHECK TO SEE WHETHER THIS SYSTEM HAS GNU READLINE HEADERS echo $ECHO_N "Checking for libreadline-dev ............. $ECHO_C" if printf '#include \n#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" echo "HAVE_READLINE=-D HAVE_READLINE=1" >> Makefile echo "LINK_READLINE=-ltermcap -lreadline" >> Makefile else rm -f conf.* echo "NO" echo "HAVE_READLINE=-D NOHAVE_READLINE=1" >> Makefile echo "LINK_READLINE=" >> Makefile fi # 13. CHECK TO SEE WHETHER THIS SYSTEM HAS CFITSIO HEADERS echo $ECHO_N "Checking for libcfitsio-dev ............. $ECHO_C" if printf '#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" echo "HAVE_FITSIO=-D HAVE_FITSIO=1" >> Makefile echo "LINK_FITSIO=-lcfitsio" >> Makefile else rm -f conf.* echo "NO" echo "HAVE_FITSIO=-D NOHAVE_FITSIO=1" >> Makefile echo "LINK_FITSIO=" >> Makefile fi # 14. CHECK TO SEE WHETHER THIS SYSTEM HAS GSL HEADERS echo $ECHO_N "Checking for libgsl0-dev ............. $ECHO_C" if printf '#include \nint main() { return 0; }\n' | gcc `gsl-config --cflags` -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" else rm -f conf.* echo "NO" echo "ERROR: Header files for required library 'libgsl' could not be found." >&2 exit fi echo $ECHO_N "Checking version of libgsl0-dev ............ $ECHO_C" if expr `gsl-config --version` \>= 1.10 > conf.stdout then rm -f conf.* echo "YES" else rm -f conf.* echo "NO" echo "ERROR: Pyxplot requires a version of gsl >= 1.10. Installed version is `gsl-config --version`." >&2 exit fi # 15. CHECK TO SEE WHETHER THIS SYSTEM HAS FFTW HEADERS echo $ECHO_N "Checking for libfftw3-dev ............. $ECHO_C" if printf '#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" echo "HAVE_FFTW3=-D HAVE_FFTW3=1" >> Makefile echo "LINK_FFTW=-lfftw3" >> Makefile else rm -f conf.* echo "NO" echo $ECHO_N "Checking for libfftw2-dev ............. $ECHO_C" if printf '#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" echo "LINK_FFTW=-lfftw" >> Makefile else rm -f conf.* echo "NO" echo "ERROR: Header files for required library 'libfftw' could not be found." >&2 exit fi fi # 16. CHECK TO SEE WHETHER THIS SYSTEM HAS LIBXML2 HEADERS echo $ECHO_N "Checking for libxml2-dev ............. $ECHO_C" whichout=`which xml2-config 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" else echo "NO" echo "ERROR: Header files for required library 'libxml2' could not be found." >&2 exit fi # 17. CHECK TO SEE WHETHER THIS SYSTEM HAS LIBPNG HEADERS echo $ECHO_N "Checking for libpng-dev ............. $ECHO_C" if printf '#include \n#include \n#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" else rm -f conf.* echo "NO" echo "ERROR: Header files for required library 'libpng' could not be found." >&2 exit fi # 18. CHECK TO SEE WHETHER THIS SYSTEM HAS KPATHSEA HEADERS echo $ECHO_N "Checking for libkpathsea-dev ............. $ECHO_C" if printf '#include \n#include \n#include \nint main() { return 0; }\n' | gcc -x c - -o conf.out > conf.stdout 2> conf.stderr then rm -f conf.* echo "YES" echo "HAVE_KPATHSEA=-D HAVE_KPATHSEA=1" >> Makefile echo "LINK_KPATHSEA=-lkpathsea" >> Makefile echo "KPSE_COMMAND=/dev/null" >> Makefile else rm -f conf.* echo "NO" echo "HAVE_KPATHSEA=-D NOHAVE_KPATHSEA=1" >> Makefile echo "LINK_KPATHSEA=" >> Makefile # If we don't have libkpathsea, check that we do have kpsewhich echo $ECHO_N "Checking for kpsewhich ............. $ECHO_C" whichout=`which kpsewhich 2> conf.stderr` rm -f conf.* if test "`echo $whichout | sed 's/\([a-z]*\).*/\1/'`" = "no" ; then whichout="" ; fi if test "$whichout" != "" ; then echo "YES" echo "KPSE_COMMAND=${whichout}" >> Makefile else echo "NO" ; echo "ERROR: Neither the header files for the library 'libkpathsea-dev', nor the program kpsewhich could not be found." >&2 ; exit fi fi # 19. OUTPUT MAKEFILE cat Makefile.skel >> Makefile echo "Configuration successful." echo "To continue installation, type '${MAKE_COMMAND}'." pyxplot-0.9.2/COPYING0000664000175000017500000004311012026340554012656 0ustar dcf21dcf21 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. pyxplot-0.9.2/ChangeLog0000664000175000017500000005361712026340554013412 0ustar dcf21dcf212012 Sep 19: Pyxplot 0.9.2 - Version 0.9.2 corrects a large number of minor bugs. 2012 Aug 29: Pyxplot 0.9.1 - Version 0.9.1 is a minor update with new support for running Pyxplot on Raspberry Pi. It fixes SIGBUS errors in Pyxplot's math engine when run on armhf architectures. 2012 Aug 1: Pyxplot 0.9.0 - Version 0.9 is a major update. Many new data types have been introduced, each of which has methods which can be called in an object-orientated fashion. These include: - Colors, which can be stored in variables for subsequent use in vector graphics commands. The addition and subtraction operators act on colors to allow color mixing. - Dates, which can be imported from calendar dates, unix times or Julian dates. Dates can be subtracted to give time intervals. - Lists and dictionaries, which can be iterated over, or used to feed calculated data into the plot and tabulate commands. - Vectors and matrices, which allow matrix algebra. These types interface cleanly with Pyxplot’s vector-graphics commands, allowing positions to be specified as vector expressions. - File handles, which allow Pyxplot to read data from files, or write data or logs to files. - Modules and classes, which allow object-orientated programming. - In addition, Pyxplot’s range of operators has been extended to include most of those in the C programming language, allowing expressions such as pyxplot> print (a=3)+(b=2) 5 pyxplot> print a>0?"yes":"no" yes pyxplot> print "%s %s"%(++a,b++) 4 2 pyxplot> print (a+=10 , b+=10 , a+b) 27 to be written. - INCOMPATIBILITIES WITH PYXPLOT 0.8. - Some functions and variables have been renamed. Variables whose names used to begin phy_ now live in a module called phy. They may be accessed as, for example, phy.c. Similarly, random number generating functions now live in a module called random; statistics functions in a module called stats; time-handling functions in time; operating system functions in os; and astronomy functions in ast. The contents of these modules can be listed by typing, for example, print phy. - Custom colors, which used to be specified using syntax such as rgb0.2:0.3:0.4, should now be specified using the rgb(r,g,b) functions, as, for example, rgb(0.2,0.3,0.4). Custom colors can now be stored in variables for later use. - The range of escape characters which can be used in strings has been increased, so that, for example, \n is a newline and \t a tab. As in python, prepending the string with the character r disables all escape character expansion. As backslashes are common characters in latex command strings, the easiest approach is to always prepend latex strings with an r. As in python, triple quotes, e.g.\ r"""2 \times 3""" can be used where required. - In the foreach command, square brackets should be used to delimit lists of items to iterate over. The Pyxplot 0.8 syntax foreach i in (1,2,3) should now be written foreach i in [1,2,3]. 2011 Jan 7: Pyxplot 0.8.4 - Two-dimensional parametric grid plotting implemented. - Bugfix to the dots plot style; filled triangles replaces with filled circles. - Bugfix to linewidths used when drawing line icons on graph legends. - Bugfix to Makefile to ensure libraries link correctly under Red Hat and SUSE. - Code cleanup to ensure correct compilation with -O2 optimisation. 2010 Sep 15: Pyxplot 0.8.3 - @ macro expansion operator implemented. - assert command implemented. - for command behaviour changed such that "for i=1 to 10" includes a final iteration with i=10. - Point types rearranged into a more logical order. - Improved support for newer Windows bitmap images. - Bugfix to the 'set unit preferred' command. - Binary not operator bugfixed. - Bugfix to handling of comma-separated horizontal datafiles. - Mathematical function finite() added. 2010 Aug 4: PyxPlot 0.8.2 - 3D plotting implemented. - New plot styles colourmap, contourmap and surface added. - Interpolation of 2D datagrids and bitmap images implemented. - Stepwise interpolation mode added. - Dependency on libkpathsea relaxed to make installation under MacOS easier; linking to the library is still strongly recommended on systems where it is readily available. - Mathematical functions fractal_julia(), fractal_mandelbrot() and prime() added. - Many bug fixes, especially to the ticking of axes. 2010 Jun 1: Pyxplot 0.8.1 - Mathematical functions time_fromunix(), time_unix(), zernike() and zernikeR() added. - Bug fix to the ticking of linked axes. - Bug fix to the ticking of axes with blank axis tick labels. - Makefile and configure script improved for portability. 2010 May 19: Pyxplot 0.8.0 - The handling of large datafiles has been streamlined to require around an order-of-magnitude less time and memory. - Pyxplot's mathematical environment has been extended to handle complex numbers and quantities with physical units. - The range of mathematical functions built into Pyxplot has been massively extended. - The solve command has been added to allow the solution of systems of equations. - The maximise and minimise commands have been added to allow searches for local extrema of functions. - An fft command has been added for performing Fourier transforms on data. - New plot styles -- filledregion and yerrorshaded -- have been added for plotting filled error regions. - The configuration of linked axes has been entirely redesigned. - Parametric function plotting has been implemented. - Colours can now be specified by RGB, HSB or CMYK components, as well as by name. - Several commands, e.g. box, circle, ellipse, etc., have been added to allow vector graphics to be produced in Pyxplot's multiplot environment. - The jpeg command has been generalised to allow the incorporation of not only jpeg images, but also bmp, gif and png images, onto multiplot canvases. The command has been renamed image in recognition of its wider applicability. Image transparency is now supported in gif and png images. - The spline command, now renamed the interpolate command, has been extended up provide many types of interpolation between datapoints. - A wide range of conditional and flow control structures have been added to Pyxplot's command language -- these are the do, for, foreach, if and while commands and the conditionalS and conditionalN mathematical functions. - Input filters have been introduced as a mechanism by which datafiles in arbitrary formats can be read. - Pyxplot's commandline interface now supports tab completion. - The show command has been reworked to produce pastable output. - Many minor bugs have been fixed. 2009 Nov 17: Pyxplot 0.7.1 - Bug fix to the xyerrorrange plot style. - Bug fix to the exec command. - Bug fix to remove deprecation error messgaes when run on python 2.6. 2008 Oct 14: Pyxplot 0.7.0 - Supplying filename '-' to plot causes data to be read from stdin. - Required version of PyX upgraded 0.9 -> 0.10. - exec command implemented. - use of string variables introduced. pythonesque "%s"%string syntax implemented. perlesque regular expressions implemented. - function evaluation routines overhauled and optimised. - datafile reading routines optimised to drastically improve memory/cpu efficiency. - histogram command implemented. - tabulate command implemented. - list command implemented. - set label with colour implemented. - text with colour implemented. 2007 Mar 15: Pyxplot 0.6.3.1 - Minor bugfix so that gv will work with -watch. 2007 Feb 26: Pyxplot 0.6.3 - Manual updated - Some minor bugfixes 2007 Jan 19: Pyxplot 0.6.2 - 'enlarge' terminal option implemented. - pdf terminal implemented. - set preamble command implemented. - LaTeX preambles bugfixed, so that the '\usepackage' command can now be used. - 'X11_persist' terminal bugfixed to work correctly from non-interactive sessions. - Large number of minor bugfixes. 2006 Dec 27: Pyxplot 0.6.1 - Major bug-fixes to the set and unset commands. - Command reference chapter added to User Manual. - Command syntax references added to the help command system. - 'text' and 'set label' commands extended to allow rotation of text through arbitrary angles. - Semi-functional 'jpeg' and 'eps' commands added. Left undocumented because they're unstable and need a bit of work. 2006 Nov 12: Pyxplot 0.6.0 - New more-reliable command parser implemented, with improved syntax errors. - delete_arrow, delete_text, undelete_arrow, undelete_text and move_text commands removed from API. The move, delete and undelete commands now act on all kinds of multiplot object. - set terminal command no longer recognised enhanced and noenhanced keywords. The postscript and eps terminal keywords should now be used in their place. - Automatic ticking of axes overhauled, and the set xtics and set mxtics commands implemented for those who do not like the default ticking schemes. - set log and set nolog command now allow axes to work with log bases other than 10. - The select modifier after the plot, fit, replot and spline commands can now only be used once; to specify multiple select criteria, use the and logical operator. - X11_persist terminal implemented. - Requirement on python 2.4 eased to python 2.3. - Requirements on scipy and readline eased; Pyxplot will now work in reduced form without them. - Requirements on dvips and gs are dropped; postscript handling now done by Pyxplot itself. 2006 Sep 09: Pyxplot 0.5.8 - Many bugfixes to error trapping and reporting. 2006 Aug 26: Pyxplot 0.5.7 - set display command implemented. - set keycolumns command implemented. - CTRL-C behaviour changed; no longer quits Pyxplot. - plot '*.dat' now arranges files alphabetically. - Escaping of LaTeX < and > symbols fixed. - Major bugfix to fit command's error estimation. - Major bugfix to the positioning of legends in the "outside" and "below" positions to avoid overlapping with axes. - help command text substantially revised. 2006 Aug 18: Pyxplot 0.5.6 - Ability to unset variables via "a=" implemented. - Handling on scipy error messages in the int_dx and spline commands improved. - Colour-highlighted terminal added. - The inline help system made much more complete. - select modifier implemented. - set texthalign and set textvalign implemented. - set xticdir command implemented. - Support for CSV input datafiles implemented. - pyxplot_watch quiet mode added. Also, behaviour changed to allow the watching of files, even when they do not initially exist. - Labels can now be placed on "nolabels", "nolabelstics" and "invisible" axes. Example 10 changed to demonstrate this. - set log, when issued on its own, now applies to all axes, rather than throwing an error. 2006 Jul 25: Pyxplot 0.5.5 - pyxplot_watch implemented. - fit command now gives error estimates, as well as correlation matrices. - Many new pointtypes added, including upper and lower limit symbols. - Handling of SIGINT improved; now exits current command in interactive mode, and exits Pyxplot when running a script. - Quote characters can now be escaped in LaTeX strings, to allow strings with both ' and " characters to be rendered. - Installer no longer creates any files belonging to root in the user's homespace. - show xlabel and show xrange implemented. - Bug fix: cd command no longer crashes if target directory doesn't exist. - Bug fix: some commands, e.g. plot, which previously didn't work when capitalised, now do. - Major bug fix to int_dx and diff_dx functions. 2006 Jul 3: Pyxplot 0.5.4 - edit command implemented. - Numerical integration and differentiation functions implemented. - New makefile installer added. - man page added. - Brief tour of gnuplot syntax added to documentation. - Many minor bug fixes. 2006 Jun 27: Pyxplot 0.5.3 - set bar and set palette implemented. - Stacked barcharts implemented. - Command history files and the save command implemented. - Plotting of functions with errorbars implemented. - Ability to define a LaTeX preamble implemented. - Bug fix to smoothed splines, to ensure that smoothing is always applied to a sensible degree by default. - Bug fix to the autoscaling of bar charts, histograms and errorbars, to ensure that their full extent is contained within the plot area. - Bug fix to arrow plotting, to prevent PyX from crashing if arrows of zero lengths are plotting (they have no direction...) 2006 Jun 14: Pyxplot 0.5.2 - spline command, and csplines/acsplines plot styles implemented. - Syntax plot[0:1], with no space, now allowed. - Automatic names of datasets in legends no longer have full paths, but only the path in the form that the user specified it. - Bug fix to the handling of LaTeX special characters in the automatic names of datasets, e.g. file paths containing underscores. - Error messages now sent to stderr, rather than stdout. - multiplot mode now plots items in the order that they are plotted; previously all arrows and text labels had been plotted in front of plots. - set backup command implemented, for keeping backups of overwritten files. - Bug fix, enabling the use of axis x5 without axis x3, and likewise for y. - unset axis command implemented, for removing axes from plots. - 'invisible', 'nolabels', and 'nolabelsticks' axis title implemented, for producing axes without text labels. - plot 'every' modifier re-implemented, to use the same syntax as gnuplot. - fit command re-implemented to work with functions of > 1 variable. - plot with pointlines defined as alias for 'linespoints'. - plot using rows syntax implemented, for plotting horizontally-arranged datafiles. - Bug fix to replot command in multiplot mode, to take account of any move commands applied to the last plot. - Bug fix to errorbar pointsizes. pointsize modifier now produces sensible output with all errorbar plot styles. - show command re-implemented to accept any word that the set command will. 2006 Jun 2: Pyxplot 0.5.1 - Pling and cd commands implemented; ` ` shell command substitution implemented. - Arrows (both from set arrow and the arrow command) can now have linetypes and colours set. - Colours can now be specified as either palette indices or PyX colour names in all contexts -- e.g. 'plot with colour red'. - Function plotting fixed to allow plotting of functions which are not valid across the whole range of the x-axis. - Transparent terminals now have anti-aliasing disabled. - Warnings now issued when too many columns are specified in plot command; duplicate errors filtered out in two-pass plotting. - Function splicing implemented. - Documentation: sections on barcharts, function splicing, and datafile globbing added. 2006 May 27: Pyxplot 0.5.0 - Name changed to Pyxplot. - Change to distribution format: PyX Version 0.9 now ships with package. - Safety installer added; checks for required packages. - 'errorrange' plot styles added; allow errorbars to be given as min/max values, rather than as a standard deviation. - 'boxes', 'wboxes', 'steps', 'fsteps', 'histeps' and 'impulses' plot styles implemented -- allow the production of histograms and bar charts. - plot with fillcolour implemented, to allow coloured bar charts. - Handling of broken datafiles sanitised: now warns for each broken line. - gridlines on multiple axes, e.g. 'set grid x1x2x3' now allowed. - Major bugfix to the way autoscaling works: linked axes share information and scale intelligently between plots. - --help and --version commandline options implemented. - 'using' specifiers for datafiles can now include expressions, such as $(2+x). - eps terminal fixed to produce encapsulated postscript. - datafile names now glob, so that plot '*' will plot many datafiles. - Documentation: examples 6,7 and 8 added. 2006 May 18: GnuPlot+ 0.4.3 - text and arrow commands now accept expressions rather than just floats for positional coordinates. - clear command major bug-fixed. - 'plot with' clause bugfixed; state variable was not resetting. - Automatical key titles for datafile datasets made more informative. - Autoscaling of multiple axes bugfixed. - Autoscaling of inverted axes fixed. - set grid command fixed to only produce x/y gridlines when requested. - X11_singlewindow changed to use gv --watch. - landscape terminal postscript header detection bugfixed. - noenhanced terminal changed to produce proper postscript. - Plotting of single column datafiles without using specifier fixed. 2006 May 4: GnuPlot+ 0.4.2 - Autoscaling redesigned, no longer uses PyX for this. - Numerical expression handling fixed in set title, set origin and set label. - Handling of children fixed, to prevent zombies from lingering around. - arrow command implemented. - set textcolour, set axescolour, set gridmajcolour, set gridmincolour and set fontsize implemented. - Colour palette can now be set in configuration file. - Ranges for axes other then x1/y1 can now be set in the plot command. - Postscript noenhanced can now produce plots almost as big as an A4 sheet. - Plotting of one column datafiles, against datapoint number, implemented. - Negative errorbars error trapped. - Comment lines now allowed in command files. 2006 May 1: GnuPlot+ 0.4.1 - Documentation converted from ASCII to LaTeX. - ChangeLog added. - Configuration files now supported. - Prevention of temporary files in /tmp overwriting pre-existing files. - set term enhanced / noenhanced / landscape / portrait / png / gif / jpeg / transparent / solid / invert / noinvert implemented. - set dpi implemented, to allow user to choose quality of gif/jpg/png output. - `set grid' command now allows user to specify which axes grid attaches to. (extended API) - Support introduced for plotting gzipped datafiles. Filenames ending in '.gz' are assumed to be gzipped. - load command implemented. - move command implemented. - Long lines can now be split using '\' linesplit character at the end of a line. Any whitespace at the beginning of the next is omitted. - text / delete_text / undelete_text / move_text commands implemented. - refresh command implemented. (extended API) - point types, line styles, and colours now start at 1, for gnuplot compatibility. - default terminal changed to postscript for non-interactive sessions. 2006 Apr 27: GnuPlot+ 0.4.0 - Bug fix: now looks for input scripts in the user's cwd, not in /tmp. - 'set logscale' is now valid syntax (as in gnuplot), as well as 'set log'. - multiplot implemented, including linked axes, though with some brokenness if linked axes are allowed to autoscale. - 'dots' plotting style implemented. - Bug fix: can now include a plot 'with' clause after an 'axes' clause; could not previously without an error message arising. - Pointstyles now increment between plotted datasets, even in a colour terminal where the colours also increment. - garbage collection of .eps files from the X11 terminal added. Previously they were left to fester in /tmp. - pointlinewidth added as a plot style, specifying the linewidth to be used in plotting points. 'set plw' and 'set lw' both added (extended API). - delete, clear and undelete commands added to the multiplot environment. - unset command implemented. - set notitle implemented. 2006 Apr 14: GnuPlot+ 0.3.2 - The autoscaling of logarithmic axes made more trust-worthy: error checks to ensure that they do not try to cover negative ordinates. - Error checks put in place to prevent empty keys being plotted, which made PyX crash previously. Now can plot empty graphs happily. - Datasets with blank titles removed from the key, to allow users to plot some datasets to be omitted from the key. This is not possible in gnuplot. - Bug fix to prevent PyX's texrunner from crashing irreparably upon receiving bad LaTeX. Now uses a spanner to attempt to return it to working order for the next plot. - Bug fix to the autoscaling of axes with no range of data -- previous did not work for negative ordinates. Now displays an axes with a range of +/- 1.0 around the data. 2006 Apr 12: GnuPlot+ 0.3.1 - Plotting of functions fixed: plot command will now plot any algebraic expression, not just functions of the form f(x). - Space added after command prompt. 2006 Apr 12: GnuPlot+ 0.3.0 - X11_singlewindow and X11_multiwindow terminals implemented, as distinct from just standard X11. - Key positioning allowed to be xcentre, ycentre, below and outside, as well as in the corners of the plot. Key allowed to be offseted in position. - Datasets colours can be set via 'plot with colour ' - Datasets are split when there is a blank line in the datafile; lines are not joined up between the two segments. - set size implemented; can now change aspect ratio of plots. - working directory of GnuPlot+ changed to /tmp, so that LaTeX's temporary files are stored there rather than in the user's cwd. 2006 Mar 30: GnuPlot+ 0.2.0 - Standard GnuPlot dual axes improved upon, allowing users to add x3, x4 axes, etc, up to any number of axes that may be desired. - Autocomplete mechanism for commandline substantially cleaned up and debugged. - Bug fixes to the plotting of arrows/labels. Now appear *above* gridlines, not below. 2006 Feb 26: GnuPlot+ 0.1.0 pyxplot-0.9.2/src/0000775000175000017500000000000012026340554012413 5ustar dcf21dcf21pyxplot-0.9.2/src/helpers/0000775000175000017500000000000012026340554014055 5ustar dcf21dcf21pyxplot-0.9.2/src/helpers/pyxplot_watch.c0000664000175000017500000002155312026340554017134 0ustar dcf21dcf21// pyxplot_watch.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pyxplot_watch.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "settings/settingTypes.h" #include "userspace/context.h" int cancellationFlag=0; void RunPyxplotOnFile(pplerr_context *context, char *fname) { char LineBuffer[LSTR_LENGTH]; int interactive, status; interactive = ((isatty(STDIN_FILENO) == 1) && (context->session_default.splash == SW_ONOFF_ON)); if (interactive) { sprintf(LineBuffer, "[%s] Running %s.", ppl_strStrip(ppl_friendlyTimestring(), context->tempErrStr), fname); ppl_report(context,LineBuffer); } sprintf(LineBuffer, "%s -q %s %s", PPLBINARY, (context->session_default.color == SW_ONOFF_ON) ? "-c" : "-m", fname); status = system(LineBuffer); if (status && !interactive) { sprintf(LineBuffer, "[%s] Encountered problem in script file %s.", ppl_strStrip(ppl_friendlyTimestring(), context->tempErrStr), fname); ppl_error(context,ERR_PREFORMED, -1, -1, LineBuffer); } if (interactive) { sprintf(LineBuffer, "[%s] Finished %s.", ppl_strStrip(ppl_friendlyTimestring(), context->tempErrStr), fname); ppl_report(context,LineBuffer); } return; } int main(int argc, char **argv) { struct timespec waitperiod, waitedperiod; // A time.h timespec specifier; used for sleeping char init_string[LSTR_LENGTH], help_string[LSTR_LENGTH], version_string[FNAME_LENGTH], version_string_underline[FNAME_LENGTH]; int i, j, HaveFilenames, DoneWork; glob_t GlobData; pplerr_context *context; dict *StatInfodict; struct stat StatInfo, *StatInfoPtr; // Initialise sub-modules context = malloc(sizeof(pplerr_context)); if (context==NULL) { printf("malloc fail."); return 1; } context->error_input_linenumber = -1; context->error_input_filename[0] = '\0'; strcpy(context->error_source,"main "); if (DEBUG) ppl_log(context,"Initialising Pyxplot Watch."); ppl_memAlloc_MemoryInit(context, &ppl_error, &ppl_log); StatInfodict = ppl_dictInit(1); // Set up default session settings context->session_default.splash = SW_ONOFF_ON; context->session_default.color = SW_ONOFF_ON; context->session_default.color_rep= SW_TERMCOL_GRN; context->session_default.color_wrn= SW_TERMCOL_BRN; context->session_default.color_err= SW_TERMCOL_RED; // Make help and version strings sprintf(version_string, "\nPyxplot Watch %s\n", VERSION); sprintf(help_string , "%s\ %s\n\ \n\ Usage: pyxplot_watch \n\ -h, --help: Display this help.\n\ -v, --version: Display version number.\n\ -q, --quiet: Turn off initial welcome message.\n\ -V, --verbose: Turn on initial welcome message.\n\ -c, --color: Use colored highlighting of output.\n\ -m, --monochrome: Turn off colored highlighting.\n\ \n\ A brief introduction to Pyxplot can be obtained by typing 'man pyxplot'; the\n\ full Users' Guide can be found in the file:\n\ %s%spyxplot.pdf\n\ \n\ For the latest information on Pyxplot development, see the project website:\n\ \n", version_string, ppl_strUnderline(version_string, version_string_underline), DOCDIR, PATHLINK); sprintf(init_string, "\n\ _ _ PYXPLOT WATCH\n\ _ __ _ ___ ___ __ | | ___ | |_ Version %s\n\ | '_ \\| | | \\ \\/ / '_ \\| |/ _ \\| __| %s\n\ | |_) | |_| |> <| |_) | | (_) | |_\n\ | .__/ \\__, /_/\\_\\ .__/|_|\\___/ \\__| Copyright (C) 2006-2012 Dominic Ford\n\ |_| |___/ |_| 2008-2012 Ross Church\n\ \n\ For documentation and more information, see .\n\ ", VERSION, DATE); // Scan command-line options for any switches HaveFilenames=0; for (i=1; isession_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "-quiet" )==0) context->session_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "--quiet" )==0) context->session_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "-V" )==0) context->session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "-verbose" )==0) context->session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "--verbose" )==0) context->session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "-c" )==0) context->session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-colour" )==0) context->session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "--colour" )==0) context->session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-color" )==0) context->session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "--color" )==0) context->session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-m" )==0) context->session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "-mono" )==0) context->session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "--mono" )==0) context->session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "-monochrome" )==0) context->session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "--monochrome")==0) context->session_default.color = SW_ONOFF_OFF; else if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "-version")==0) || (strcmp(argv[i], "--version")==0)) { ppl_report(context,version_string); if (DEBUG) ppl_log(context,"Reported version number as requested."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 0; } else if ((strcmp(argv[i], "-h")==0) || (strcmp(argv[i], "-help")==0) || (strcmp(argv[i], "--help")==0)) { ppl_report(context,help_string); if (DEBUG) ppl_log(context,"Reported help text as requested."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 0; } else { sprintf(context->tempErrStr, "Received switch '%s' which was not recognised. Type 'pyxplot_watch -help' for a list of available command-line options.", argv[i]); ppl_error(context,ERR_PREFORMED, -1, -1, NULL); if (DEBUG) ppl_log(context,"Received unexpected command-line switch."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 1; } } // Produce splash text if ((isatty(STDIN_FILENO) == 1) && (context->session_default.splash == SW_ONOFF_ON)) ppl_report(context,init_string); // Check that we have some filenames to watch if (!HaveFilenames) { ppl_error(context,ERR_PREFORMED, -1, -1, "No filenames were supplied to watch. Pyxplot Watch's command-line syntax is:\n\npyxplot_watch [options] filename_list\n\nAs Pyxplot Watch has no work to do, it is exiting..."); exit(1); } // Scan command-line options and glob all filenames while (1) { DoneWork = 0; for (i=1; ist_mtime >= StatInfo.st_mtime)) continue; // This file has not been modified lately ppl_dictAppendCpy(StatInfodict, GlobData.gl_pathv[j], (void *)&StatInfo, sizeof(struct stat)); DoneWork = 1; RunPyxplotOnFile(context, GlobData.gl_pathv[j]); waitperiod.tv_sec = 0; waitperiod.tv_nsec = 100000000; nanosleep(&waitperiod,&waitedperiod); } globfree(&GlobData); } if (!DoneWork) { waitperiod.tv_sec = 1; waitperiod.tv_nsec = 0; nanosleep(&waitperiod,&waitedperiod); } } // Never get here... free(context); return 0; } pyxplot-0.9.2/src/helpers/pyxplot_fitshelper.c0000664000175000017500000001772412026340554020200 0ustar dcf21dcf21// pyxplot_fitshelper.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pyxplot_fitshelper.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #ifdef HAVE_FITSIO #include #endif #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" int cancellationFlag=0; int main(int argc, char **argv) { char help_string[LSTR_LENGTH], version_string[FNAME_LENGTH], version_string_underline[FNAME_LENGTH], warntext[FNAME_LENGTH]; char *filename=NULL; int i, HaveFilename=0; #ifdef HAVE_FITSIO fitsfile *fptr=NULL; int j, status=0, hdupos, hdutype, nkeys, bitpix, naxis, ncols, anynull=0, dispwidth[16384]; long naxes[256], nrows; char card[FLEN_CARD], keyword[FLEN_KEYWORD], colname[FLEN_VALUE], nullstr[]="nan", tabval[16384]="\0", *valptr; #endif #ifndef HAVE_FITSIO strcpy(warntext,"*** WARNING ***\nAs the cfitsio library was not installed on this computer when Pyxplot was\n\ installed, Pyxplot has been compiled with no support for fits files. This\n\ application is a dummy filter which does nothing.\n\n"); #else strcpy(warntext,""); #endif // Make help and version strings sprintf(version_string, "\nPyxplot Fits Helper %s\n\n", VERSION); sprintf(help_string , "\nPyxplot Fits Helper %s\n\ %s\n\ \n\ %sUsage: pyxplot_fitshelper \n\ -h, --help: Display this help.\n\ -v, --version: Display version number.\n\ \n\ This application is used as in input filter to convert tables of data in FITS\n\ format into ASCII for reading into Pyxplot. It is the filter which Pyxplot uses\n\ when asked to plot a .fits file, but is also generally useful whenever it is\n\ desired to convert data from FITS format into plain text.\n\ \n\ A brief introduction to Pyxplot can be obtained by typing 'man pyxplot'; the\n\ full Users' Guide can be found in the file:\n\ %s%spyxplot.pdf\n\ \n\ For the latest information on Pyxplot development, see the project website:\n\ \n\n", VERSION, ppl_strUnderline(version_string, version_string_underline), warntext, DOCDIR, PATHLINK); // Scan command-line options for any switches HaveFilename=0; for (i=1; i 1) { fprintf(stderr, "\npyxplot_fitshelper should be provided with only one filename on the command\nline to act upon. Multiple filenames appear to have been supplied. Type\n'pyxplot_fitshelper -help' for a list of available command-line options.\n\n"); return 1; } #ifndef HAVE_FITSIO fprintf(stderr, "\nThe cfitsio library was not installed on this computer when Pyxplot was\n\ installed, and consequently Pyxplot was compiled with no support for fits\n\ files. The fits helper application which you are using is a dummy which does\n\ nothing. To plot this datafile, you need to install libcfitsio and then\n\ recompile Pyxplot.\n\n"); exit(1); #else if (fits_open_file(&fptr, filename, READONLY, &status) != 0) { fits_report_error(stderr, status); exit(1); } fits_get_hdu_num(fptr, &hdupos); // Get the current HDU number fprintf(stdout, "# Listing the contents of file <%s>\n", filename); fprintf(stdout, "# This ASCII representation generated by %s.\n", ppl_strStrip(version_string,warntext)); fprintf(stdout, "# Conversion performed at %s.\n", ppl_strStrip(ppl_friendlyTimestring(),warntext)); for (; !status; hdupos++) // Loop through extensions in this fits file { fits_get_hdrspace(fptr, &nkeys, NULL, &status); // Get number of keywords in this extension fprintf(stdout, "\n\n\n\n# HDU %d\n#\n", hdupos); for (i=0; i<=nkeys; i++) // List keys from this header { if (fits_read_record(fptr, i, card, &status)) break; fprintf(stdout, "# %s\n", card); } fits_get_hdu_type(fptr, &hdutype, &status); // Get HDU type if (hdutype == IMAGE_HDU) { fits_get_img_param(fptr, 256, &bitpix, &naxis, naxes, &status); fprintf(stdout, "\n# Image array, with %d bits per pixel, and %d axes", abs(bitpix), naxis); if (naxis>0) fprintf(stdout, ". Size: "); for (i=0; i # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: pyxplot_timehelper.sh 1293 2012-08-28 14:47:56Z dcf21 $ # # PyXPlot 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. # # You should have received a copy of the GNU General Public License along with # PyXPlot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # This is an example input filter for PyXPlot which uses some simple regular # expressions to replace the names of days of the week and months of the year # with numbers, so that textual dates can be parsed by PyXPlot. if test "$1" != "" then if test -e $1 then if test "$2" = "" then cat $1 | sed -e 's/:/ /g' -e 's:/: :g' -e 's/[Mm]on\(day\)\?/ 1 /g' -e 's/[Tt]ue\(s\(day\)\?\)\?/ 2 /g' -e 's/[Ww]ed\(nesday\)\?/ 3 /g' -e 's/[Tt]hu\(r\(s\(day\)\?\)\?\)\?/ 4 /g' -e 's/[Ff]ri\(day\)\?/ 5 /g' -e 's/[Ss]at\(urday\)\?/ 6 /g' -e 's/[Ss]un\(day\)\?/ 7 /g' -e 's/[Jj]an\(uary\)\?/ 1 /g' -e 's/[Ff]eb\(ruary\)\?/ 2 /g' -e 's/[Mm]ar\(ch\)\?/ 3 /g' -e 's/[Aa]pr\(il\)\?/ 4 /g' -e 's/[Mm]ay/ 5 /g' -e 's/[Jj]une\?/ 6 /g' -e 's/[Jj]uly\?/ 7 /g' -e 's/[Aa]ug\(ust\)\?/ 8 /g' -e 's/[Ss]ep\(t\(ember\)\?\)\?/ 9 /g' -e 's/[Oo]ct\(ober\)\?/ 10 /g' -e 's/[Nn]ov\(ember\)\?/ 11 /g' -e 's/[Dd]ec\(ember\)\?/ 12 /g' -e 's/\[/ [ /g' -e 's/\]/ ] /g' else echo "pyxplot_timehelper should be passed the name of only one file to process on the commandline." >&2 fi else echo "pyxplot_timehelper cannot open input file." >&2 fi else echo "pyxplot_timehelper should be passed the name of a file to process on the commandline." >&2 fi pyxplot-0.9.2/src/datafile.h0000664000175000017500000001521012026340554014334 0ustar dcf21dcf21// datafile.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: datafile.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_DATAFILE_H #define _PPL_DATAFILE_H 1 #define DATAFILE_CONTINUOUS 24001 #define DATAFILE_DISCONTINUOUS 24002 #define DATAFILE_ROW 24101 #define DATAFILE_COL 24102 #define USING_ITEMS_MAX 32 #define MAX_DATACOLS 16384 #define DATAFILE_NERRS 10 // The approximate number of bytes we seek to put in each data block #define DATAFILE_DATABLOCK_BYTES 524288 #include "coreUtils/list.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" // rawDataTabls structure, used for storing raw text from datafiles prior to rotation when "with rows" is used typedef struct rawDataBlock { char **text; // Array of BlockLength x [string data from datafile] long int *fileLine; // For each string above... store the line number in the data file that it came from long int blockLength; long int blockPosition; // Where have we filled up to? struct rawDataBlock *next; struct rawDataBlock *prev; } rawDataBlock; typedef struct rawDataTable { long int Nrows; int memContext; struct rawDataBlock *first; struct rawDataBlock *current; } rawDataTable; // DataTable structure, used for returning tables of VALUEs from ppl_datafile.c typedef struct dataBlock { double *data_real; // Array of Ncolumns x array of length BlockLength pplObj *data_obj; char **text; // Array of BlockLength x string labels for datapoints long int *fileLine_real; // For each double above... store the line number in the data file that it came from long int *fileLine_obj; unsigned char *split; // Array of length BlockLength; TRUE if we should break data before this next datapoint long int blockLength; long int blockPosition; // Where have we filled up to? struct dataBlock *next; struct dataBlock *prev; } dataBlock; typedef struct dataTable { int Ncolumns_real; int Ncolumns_obj; long int Nrows; int memContext; pplObj *firstEntries; // Array of size Ncolumns; store units for data in each column here struct dataBlock *first; struct dataBlock *current; } dataTable; // Functions in ppl_datafile.c dataBlock *ppldata_NewDataBlock (const int Ncolumns_real, const int Ncolumns_obj, const int memContext, const int length); dataTable *ppldata_NewDataTable (const int Ncolumns_real, const int Ncolumns_obj, const int memContext, const int length); rawDataBlock *ppldata_NewRawDataBlock (const int memContext); rawDataTable *ppldata_NewRawDataTable (const int memContext); int ppldata_DataTable_AddRow (dataTable *i); int ppldata_RawDataTable_AddRow(rawDataTable *i); void ppldata_DataTable_List (ppl_context *c, dataTable *i); FILE *ppldata_LaunchCoProcess (ppl_context *c, char *filename, int wildcardMatchNumber, char *filenameOut, char *errout); void ppldata_UsingConvert (ppl_context *c, pplExpr *input, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int iterDepth); void ppldata_ApplyUsingList (ppl_context *c, dataTable *out, pplExpr **usingExprs, pplExpr *labelExpr, pplExpr *selectExpr, int continuity, int *discontinuity, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int *errCount, int iterDepth); void ppldata_RotateRawData (ppl_context *c, rawDataTable **in, dataTable *out, pplExpr **usingExprs, pplExpr *labelExpr, pplExpr *selectExpr, int continuity, char *filename, long block_count, long index_number, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int *errCount, int iterDepth); dataTable *ppldata_sort(ppl_context *c, dataTable *in, int sortCol, int ignoreContinuity); int ppldata_autoUsingList(ppl_context *c, pplExpr **usingExprs, int Ncols, char *errtext); void ppldata_fromFile (ppl_context *c, dataTable **out, char *filename, int wildcardMatchNumber, char *filenameOut, parserLine **dataSpool, int indexNo, pplExpr **usingExprs, int autoUsingExprs, int Ncols, int NusingObjs, pplExpr *labelExpr, pplExpr *selectExpr, pplExpr *sortBy, int usingRowCol, long *everyList, int continuity, int persistent, int *status, char *errtext, int *errCount, int iterDepth); void ppldata_fromFuncs (ppl_context *c, dataTable **out, pplExpr **fnlist, int fnlist_len, double *rasterX, int rasterXlen, int parametric, pplObj *unitX, double *rasterY, int rasterYlen, pplObj *unitY, pplExpr **usingExprs, int autoUsingExprs, int Ncols, int NusingObjs, pplExpr *labelExpr, pplExpr *selectExpr, pplExpr *sortBy, int continuity, int *status, char *errtext, int *errCount, int iterDepth); void ppldata_fromVectors (ppl_context *c, dataTable **out, pplObj *objList, int objListLen, pplExpr **usingExprs, int autoUsingExprs, int Ncols, int NusingObjs, pplExpr *labelExpr, pplExpr *selectExpr, pplExpr *sortBy, int continuity, int *status, char *errtext, int *errCount, int iterDepth); void ppldata_fromCmd (ppl_context *c, dataTable **out, parserLine *pl, parserOutput *in, int wildcardMatchNumber, char *filenameOut, parserLine **dataSpool, const int *ptab, const int stkbase, int Ncols, int NusingObjs, double *min, int *minSet, double *max, int *maxSet, pplObj *unitRange, int persistent, int *status, char *errtext, int *errCount, int iterDepth); #endif pyxplot-0.9.2/src/children.h0000664000175000017500000000416212026340554014357 0ustar dcf21dcf21// children.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: children.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CHILDREN_H #define _CHILDREN_H 1 #include "userspace/context.h" // Functions to be called from main Pyxplot process void pplcsp_init (ppl_context *context); void pplcsp_checkForGvOutput (ppl_context *context); void pplcsp_sendCommand (ppl_context *context, char *cmd); // Functions to be called from the Child Support Process void pplcsp_main (ppl_context *context); void pplcsp_checkForChildExits (int signo); void pplcsp_checkForNewCommands (ppl_context *context); void pplcsp_processCommand (ppl_context *context, char *in); int pplcsp_forkNewGv (ppl_context *context, char *fname, int *gv_list); void pplcsp_killAllGvs (ppl_context *context); void pplcsp_killLatestSinglewindow(ppl_context *context); // Functions for spawning helper processes void pplcsp_checkForHelperExits (int signo); void pplcsp_killAllHelpers (ppl_context *context); void pplcsp_forkSed (ppl_context *context, char *cmd, int *fstdin, int *fstdout); void pplcsp_forkLaTeX (ppl_context *context, char *filename, int *PidOut, int *fstdin, int *fstdout); void pplcsp_forkInputFilter (ppl_context *context, char **cmd, int *fstdout); void pplcsp_forkKpseWhich (ppl_context *context, const char *ftype, int *fstdout); #endif pyxplot-0.9.2/src/datafile_rasters.c0000664000175000017500000001413312026340554016075 0ustar dcf21dcf21// datafile_rasters.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: datafile_rasters.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _DATAFILE_RASTERS_C 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "parser/parser.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" void ppldata_fromFuncs_checkSpecialRaster(ppl_context *C, pplExpr **fnlist, int fnlist_len, char *dummyVar, double *min, double *max, pplObj *unit, double **raster, int *rasterLen) { int i, j, pos, commaPos=0, bracketLevel=0, containsOperator=0, containsDummy=0, NWords=0, outputContext, contextRough=-1; int dummyArgNo=0; char newWord=1, fail=0; char c; char *buf = C->errcontext.tempErrStr; char *currentFnName="", *dummyInFunction=NULL; list *bracketStack, *bracketCommaPos; pplObj *funcObjPtr=NULL; pplFunc *funcPtr=NULL; // Make temporary rough workspace outputContext = ppl_memAlloc_GetMemContext(); contextRough = ppl_memAlloc_DescendIntoNewContext(); bracketStack = ppl_listInit(0); bracketCommaPos = ppl_listInit(0); for (i=0; iascii[j++]; if ((isalnum(c)) || (c=='_')) { newWord=0; buf[pos++] = c; continue; } if ((!newWord) && (pos>0)) NWords++; if (!newWord) buf[pos++] = '\0'; newWord=1; pos=0; if ((c<=' ') && (c!='\0')) continue; if (strcmp(buf, dummyVar)==0) { containsDummy=1; if (containsOperator || (NWords>1)) fail=1; if ((dummyInFunction != NULL) && (currentFnName != NULL)) { if ((strcmp(dummyInFunction, currentFnName)!=0) || (dummyArgNo != commaPos)) fail=1; } if (currentFnName==NULL) fail=1; else { dummyInFunction = currentFnName; dummyArgNo = commaPos; } } if (c=='(') { if (containsDummy) fail=1; ppl_listAppendCpy(bracketCommaPos, &commaPos, sizeof(int)); ppl_listAppendCpy(bracketStack, buf, strlen(buf)+1); bracketLevel++; currentFnName = (char *)ppl_listLast(bracketStack); containsOperator = 0; containsDummy = 0; NWords = 0; buf[0]='\0'; continue; } buf[0]='\0'; if (c==')') { if (bracketLevel>0) { ppl_listPop(bracketStack); currentFnName = (char *)ppl_listLast(bracketStack); commaPos = *(int *)ppl_listPop(bracketCommaPos); containsOperator = 1; containsDummy = 0; NWords = 10; bracketLevel--; } continue; } if (c==',') { commaPos++; containsOperator = 0; containsDummy = 0; NWords = 0; continue; } if (c=='\0') break; containsOperator=1; if (containsDummy) fail=1; } } if (fail || (dummyInFunction==NULL) || (dummyInFunction[0]=='\0')) goto CLEANUP; // Look up function which dummy variable is an argument to ppl_contextVarLookup(C, dummyInFunction, &funcObjPtr, 0); if ( (funcObjPtr==NULL) || (funcObjPtr->objType!=PPLOBJ_FUNC) ) goto CLEANUP; funcPtr = (pplFunc *)funcObjPtr->auxil; if (funcPtr==NULL) goto CLEANUP; if ((funcPtr->functionType!=PPL_FUNC_HISTOGRAM) && (funcPtr->functionType!=PPL_FUNC_FFT)) goto CLEANUP; if (dummyArgNo >= funcPtr->minArgs) goto CLEANUP; // Make custom raster if (funcPtr->functionType == PPL_FUNC_HISTOGRAM) { histogramDescriptor *desc = (histogramDescriptor *)funcPtr->functionPtr; double *outputRaster; int rasterCount=0; long NInput = desc->Nbins-1; if (NInput<1) NInput=1; outputRaster = (double *)ppl_memAlloc_incontext(NInput*sizeof(double), outputContext); if (outputRaster == NULL) goto CLEANUP; for (i=0; i<(desc->Nbins-1); i++) { double midpoint = desc->log?sqrt(desc->bins[i]*desc->bins[i+1]) : ((desc->bins[i]+desc->bins[i+1])/2); if ( ((min==NULL)||(*min<=midpoint)) && ((max==NULL)||(*max>=midpoint)) ) { outputRaster[ rasterCount++ ] = midpoint; } } *raster = outputRaster; *rasterLen = rasterCount; } else if (funcPtr->functionType == PPL_FUNC_FFT) { FFTDescriptor *desc = (FFTDescriptor *)funcPtr->functionPtr; double *outputRaster; int rasterCount=0; if (dummyArgNo >= desc->Ndims) goto CLEANUP; outputRaster = (double *)ppl_memAlloc_incontext(desc->XSize[dummyArgNo]*sizeof(double), outputContext); if (outputRaster == NULL) goto CLEANUP; for (i=0; iXSize[dummyArgNo]; i++) { double x = (i-desc->XSize[dummyArgNo]/2.0) / desc->range[dummyArgNo].real; if ( ((min==NULL)||(*min<=x)) && ((max==NULL)||(*max>=x)) ) { outputRaster[ rasterCount++ ] = x; } } *raster = outputRaster; *rasterLen = rasterCount; } CLEANUP: // Delete rough workspace if (contextRough>0) ppl_memAlloc_AscendOutOfContext(contextRough); return; } pyxplot-0.9.2/src/readConf.c0000664000175000017500000023166112026340554014311 0ustar dcf21dcf21// readConf.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: readConf.c 1273 2012-07-20 00:18:37Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_READCONF_C 1 #include #include #include #include #include #include #include "commands/set.h" #include "coreUtils/errorReport.h" #include "epsMaker/eps_settings.h" #include "expressions/expCompile.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "parser/parser.h" #include "settings/arrows_fns.h" #include "settings/axes_fns.h" #include "settings/epsColors.h" #include "settings/colors.h" #include "settings/labels_fns.h" #include "settings/papersizes.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" static void _ReadConfig_FetchKey(char *line, char *out) { char *scan = out; while ((*line != '\0') && ((*(scan) = *(line++)) != '=')) scan++; *scan = '\0'; ppl_strStrip(out, out); return; } static void _ReadConfig_FetchValue(char *line, char *out) { char *scan = out; while ((*line != '\0') && (*(line++) != '=')); while (*line != '\0') *(scan++) = *(line++); *scan = '\0'; ppl_strStrip(out, out); return; } static void ppl_readConfigFile(ppl_context *c, char *ConfigFname) { char linebuffer[LSTR_LENGTH], setkey[LSTR_LENGTH], setvalue[LSTR_LENGTH], ColorName[SSTR_LENGTH], *StringScan; char *linebufferPtr = &linebuffer[0]; char errtext[LSTR_LENGTH]; FILE *infile; int state=-1; int linecounter=0; int i, j, k, PalettePos, ColorNumber; double fl, PaperHeight, PaperWidth; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Scanning configuration file %s.", ConfigFname); ppl_log(&c->errcontext, NULL); } if ((infile=fopen(ConfigFname,"r")) == NULL) { if (DEBUG) { ppl_log(&c->errcontext, "File does not exist."); } return; } while ((!feof(infile)) && (!ferror(infile))) { linecounter++; ppl_file_readline(infile, &linebufferPtr, NULL, LSTR_LENGTH); ppl_strStrip(linebuffer, linebuffer); if (linebuffer[0] == '\0') continue; else if (ppl_strCmpNoCase(linebuffer, "[settings]" )==0) {state= 1; continue;} else if (ppl_strCmpNoCase(linebuffer, "[terminal]" )==0) {state= 2; continue;} else if (ppl_strCmpNoCase(linebuffer, "[colours]" )==0) {state= 3; continue;} else if (ppl_strCmpNoCase(linebuffer, "[colors]" )==0) {state= 3; continue;} else if (ppl_strCmpNoCase(linebuffer, "[latex]" )==0) {state= 4; continue;} else if (ppl_strCmpNoCase(linebuffer, "[variables]")==0) {state= 5; continue;} else if (ppl_strCmpNoCase(linebuffer, "[functions]")==0) {state= 6; continue;} else if (ppl_strCmpNoCase(linebuffer, "[units]" )==0) {state= 7; continue;} else if (ppl_strCmpNoCase(linebuffer, "[filters]" )==0) {state= 8; continue;} else if (ppl_strCmpNoCase(linebuffer, "[script]" )==0) {state= 9; continue;} else if (ppl_strCmpNoCase(linebuffer, "[styling]" )==0) {state=10; continue;} _ReadConfig_FetchKey (linebuffer, setkey ); _ReadConfig_FetchValue(linebuffer, setvalue); if (state == 1) // [settings] section { ppl_strUpper(setkey, setkey); if (strcmp(setkey, "ASPECT" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.AutoAspect = SW_ONOFF_ON; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue))&&(fl>=1e-6)&&(fl<=1e4))) { c->set->graph_default.aspect = fl; c->set->graph_default.AutoAspect = SW_ONOFF_OFF; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AUTOASPECT" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.AutoAspect = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ZASPECT" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.AutoZAspect = SW_ONOFF_ON; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue))&&(fl>=1e-6)&&(fl<=1e4))) { c->set->graph_default.zaspect = fl; c->set->graph_default.AutoZAspect = SW_ONOFF_OFF; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AUTOZASPECT" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.AutoZAspect = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "AXESCOLOUR" )==0) || (strcmp(setkey, "AXESCOLOR")==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_COLOR_INT,SW_COLOR_STR))>0) c->set->graph_default.AxesColor = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXISUNITSTYLE")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_AXISUNITSTY_INT,SW_AXISUNITSTY_STR))>0) c->set->graph_default.AxisUnitStyle = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BACKUP" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .backup = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BAR" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.bar = fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BINORIGIN" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->term_default.BinOriginAuto = 1; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->term_default.BinOrigin.real = fl; c->set->term_default.BinOriginAuto = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BINWIDTH" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->term_default.BinWidthAuto = 1; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->term_default.BinWidth.real = fl; c->set->term_default.BinWidthAuto = (fl<0.0); } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BOXFROM" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.BoxFromAuto = 1; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.BoxFrom.real = fl; c->set->graph_default.BoxFromAuto = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BOXWIDTH" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.BoxWidthAuto = 1; } else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.BoxWidth.real = fl; c->set->graph_default.BoxWidthAuto = (fl<0.0); } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "CALENDARIN" )==0) { if (ppl_strCmpNoCase(setvalue, "muslim")==0) { c->set->term_default.CalendarIn = SW_CALENDAR_ISLAMIC; } else if (ppl_strCmpNoCase(setvalue, "jewish")==0) { c->set->term_default.CalendarIn = SW_CALENDAR_HEBREW; } else if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_CALENDAR_INT, SW_CALENDAR_STR ))>0) c->set->term_default.CalendarIn = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "CALENDAROUT" )==0) { if (ppl_strCmpNoCase(setvalue, "muslim")==0) { c->set->term_default.CalendarOut = SW_CALENDAR_ISLAMIC; } else if (ppl_strCmpNoCase(setvalue, "jewish")==0) { c->set->term_default.CalendarOut = SW_CALENDAR_HEBREW; } else if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_CALENDAR_INT, SW_CALENDAR_STR ))>0) c->set->term_default.CalendarOut= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "CLIP" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.clip = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "COLKEY" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.ColKey = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "COLKEYPOS" )==0) { if (ppl_strCmpNoCase(setvalue, "outside")==0) { c->set->graph_default.ColKeyPos = SW_COLKEYPOS_R; } else if (ppl_strCmpNoCase(setvalue, "below" )==0) { c->set->graph_default.ColKeyPos = SW_COLKEYPOS_B; } else if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_COLKEYPOS_INT,SW_COLKEYPOS_STR))>0) c->set->graph_default.ColKeyPos = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOUR" )==0) || (strcmp(setkey, "COLOR")==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .color = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "CONTOURS" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.ContoursN = ppl_max((int)fl, 2); else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "CONTOURS_LABEL")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.ContoursLabel = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } #define DO_CRANGE(C,X) \ else if (strcmp(setkey, "C" X "RANGE_LOG" )==0) \ { \ if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Clog[C] = i; \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_MIN" )==0) \ { \ if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.Cminauto[C] = SW_BOOL_TRUE; } \ else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Cmin[C].real = fl; c->set->graph_default.Cminauto[C] = SW_BOOL_FALSE; } \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_MIN_AUTO")==0) \ { \ if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Cminauto[C] = i; \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_MAX" )==0) \ { \ if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.Cmaxauto[C] = SW_BOOL_TRUE; } \ else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Cmax[C].real = fl; c->set->graph_default.Cmaxauto[C] = SW_BOOL_FALSE; } \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_MAX_AUTO")==0) \ { \ if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Cmaxauto[C] = i; \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_RENORM")==0) \ { \ if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Crenorm[C] = i; \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } \ else if (strcmp(setkey, "C" X "RANGE_REVERSE")==0) \ { \ if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Creverse[C] = i; \ else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ } DO_CRANGE(0,"1") DO_CRANGE(1,"2") DO_CRANGE(2,"3") DO_CRANGE(3,"4") else if (strcmp(setkey, "DATASTYLE" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_STYLE_INT, SW_STYLE_STR ))>0) { c->set->graph_default.dataStyle.linespoints = i; c->set->graph_default.dataStyle.USElinespoints=1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "DISPLAY" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .display = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "DPI" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue))&&(fl>2))) c->set->term_default .dpi = fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "FONTSIZE" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.FontSize = fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "FUNCSTYLE" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_STYLE_INT, SW_STYLE_STR ))>0) { c->set->graph_default.funcStyle.linespoints = i; c->set->graph_default.funcStyle.USElinespoints=1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRID" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.grid = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRIDAXISX" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl)) && (i==strlen(setvalue)) && (fl>=0) && (fl<=MAX_AXES))) { c->set->graph_default.GridAxisX[1] = 0; c->set->graph_default.GridAxisX[(int)fl] = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRIDAXISY" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl)) && (i==strlen(setvalue)) && (fl>=0) && (fl<=MAX_AXES))) { c->set->graph_default.GridAxisY[1] = 0; c->set->graph_default.GridAxisY[(int)fl] = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRIDAXISZ" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl)) && (i==strlen(setvalue)) && (fl>=0) && (fl<=MAX_AXES))) { c->set->graph_default.GridAxisZ[1] = 0; c->set->graph_default.GridAxisZ[(int)fl] = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "GRIDMAJCOLOUR")==0) || (strcmp(setkey, "GRIDMAJCOLOR")==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_COLOR_INT,SW_COLOR_STR))>0) c->set->graph_default.GridMajColor = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "GRIDMINCOLOUR")==0) || (strcmp(setkey, "GRIDMINCOLOR")==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_COLOR_INT,SW_COLOR_STR))>0) c->set->graph_default.GridMinColor = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "KEY" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->graph_default.key = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "KEYCOLUMNS" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.KeyColumns = ppl_max((int)fl, 0); else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "KEYPOS" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_KEYPOS_INT,SW_KEYPOS_STR))>0) c->set->graph_default.KeyPos = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "KEY_XOFF" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.KeyXOff.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "KEY_YOFF" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.KeyYOff.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "LANDSCAPE" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .landscape = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "LINEWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.LineWidth = fabs(fl); else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "MULTIPLOT" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .multiplot = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "NUMCOMPLEX" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .ComplexNumbers= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "NUMDISPLAY" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_DISPLAY_INT, SW_DISPLAY_STR ))>0) c->set->term_default.NumDisplay = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "NUMERR" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .ExplicitErrors= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "NUMSF" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->term_default .SignificantFigures = ppl_min(ppl_max((int)fl, 1), 30); else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ORIGINX" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.OriginX.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ORIGINY" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.OriginY.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "OUTPUT" )==0) { strcpy(c->set->term_default.output , setvalue); } else if (strcmp(setkey, "PAPERHEIGHT" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->term_default .PaperHeight.real = fl/1000; PaperHeight = c->set->term_default.PaperHeight.real * 1000; PaperWidth = c->set->term_default.PaperWidth .real * 1000; ppl_GetPaperName(c->set->term_default.PaperName, &PaperHeight, &PaperWidth); } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "PAPERNAME" )==0) { { ppl_PaperSizeByName(setvalue, &PaperHeight, &PaperWidth); if (PaperHeight <= 0) {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised papersize specified for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } c->set->term_default.PaperHeight.real = PaperHeight/1000; c->set->term_default.PaperWidth.real = PaperWidth/1000; ppl_GetPaperName(c->set->term_default.PaperName, &PaperHeight, &PaperWidth); } } else if (strcmp(setkey, "PAPERWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->term_default .PaperWidth.real = fl/1000; PaperHeight = c->set->term_default.PaperHeight.real * 1000; PaperWidth = c->set->term_default.PaperWidth .real * 1000; ppl_GetPaperName(c->set->term_default.PaperName, &PaperHeight, &PaperWidth); } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "POINTLINEWIDTH")==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.PointLineWidth= fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .",linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "POINTSIZE" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.PointSize = fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } // else if (strcmp(setkey, "PROJECTION" )==0) // if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_PROJ_INT, SW_PROJ_STR ))>0) c->set->graph_default.projection = i; // else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } else if (strcmp(setkey, "SAMPLES" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.samples = ppl_max((int)fl, 2); else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "SAMPLES_METHOD")==0) if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_SAMPLEMETHOD_INT,SW_SAMPLEMETHOD_STR))>0) c->set->graph_default.Sample2DMethod = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } else if (strcmp(setkey, "SAMPLES_X" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.SamplesXAuto = SW_BOOL_TRUE; } \ else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.SamplesX = ppl_max((int)fl, 2); c->set->graph_default.SamplesXAuto = SW_BOOL_FALSE; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "SAMPLES_X_AUTO")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.SamplesXAuto = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "SAMPLES_Y" )==0) { if (ppl_strCmpNoCase(setvalue, "auto")==0) { c->set->graph_default.SamplesYAuto = SW_BOOL_TRUE; } \ else if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.SamplesY = ppl_max((int)fl, 2); c->set->graph_default.SamplesYAuto = SW_BOOL_FALSE; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "SAMPLES_Y_AUTO")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.SamplesYAuto = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TERMANTIALIAS")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .TermAntiAlias = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TERMENLARGE" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .TermEnlarge = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ENLARGE" )==0) // ENLARGE, as opposed to TERMENLARGE is supported for back-compatibility with Pyxplot 0.7 { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .TermEnlarge = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TERMINVERT" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .TermInvert = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TERMTRANSPARENT")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .TermTransparent= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting .",linecounter,ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TERMTYPE" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_TERMTYPE_INT,SW_TERMTYPE_STR))>0) { c->set->term_default.TermType = i; c->termtypeSetInConfigfile = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "TEXTCOLOUR" )==0) || (strcmp(setkey, "TEXTCOLOR")==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_COLOR_INT,SW_COLOR_STR))>0) c->set->graph_default.TextColor = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TEXTHALIGN" )==0) { if (ppl_strCmpNoCase(setvalue, "centre")==0) { c->set->graph_default.TextHAlign = SW_HALIGN_CENT; } \ else if (ppl_strCmpNoCase(setvalue, "middle")==0) { c->set->graph_default.TextHAlign = SW_HALIGN_CENT; } \ else if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_HALIGN_INT,SW_HALIGN_STR))>0) c->set->graph_default.TextHAlign = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TEXTVALIGN" )==0) { if (ppl_strCmpNoCase(setvalue, "centre")==0) { c->set->graph_default.TextVAlign = SW_VALIGN_CENT; } \ else if (ppl_strCmpNoCase(setvalue, "middle")==0) { c->set->graph_default.TextVAlign = SW_VALIGN_CENT; } \ else if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_VALIGN_INT,SW_VALIGN_STR))>0) c->set->graph_default.TextVAlign = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TITLE" )==0) { strcpy(c->set->graph_default.title , setvalue); } else if (strcmp(setkey, "TITLE_XOFF" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.TitleXOff.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TITLE_YOFF" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.TitleYOff.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TRANGE_LOG" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Tlog = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TRANGE_MIN" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Tmin.real = fl; c->set->graph_default.USE_T_or_uv = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "TRANGE_MAX" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Tmax.real = fl; c->set->graph_default.USE_T_or_uv = 1; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "UNITABBREV" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .UnitDisplayAbbrev= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "UNITANGLEDIMLESS")==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .UnitAngleDimless= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "UNITPREFIX" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->set->term_default .UnitDisplayPrefix= i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "UNITSCHEME" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_UNITSCH_INT,SW_UNITSCH_STR))>0) c->set->term_default.UnitScheme = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "URANGE_LOG" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Ulog = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "URANGE_MIN" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Umin.real = fl; c->set->graph_default.USE_T_or_uv = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "URANGE_MAX" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Umax.real = fl; c->set->graph_default.USE_T_or_uv = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "VRANGE_LOG" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue,SW_BOOL_INT,SW_BOOL_STR))>0) c->set->graph_default.Vlog = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "VRANGE_MIN" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Vmin.real = fl; c->set->graph_default.USE_T_or_uv = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "VRANGE_MAX" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) { c->set->graph_default.Vmax.real = fl; c->set->graph_default.USE_T_or_uv = 0; } else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "WIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.width.real = fl/100; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "VIEW_XY" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.XYview.real = fl/180*M_PI; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "VIEW_YZ" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) c->set->graph_default.YZview.real = fl/180*M_PI; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised setting name '%s'.", linecounter, ConfigFname, setkey); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (state == 2) // [terminal] section { ppl_strUpper(setkey, setkey); if ((strcmp(setkey, "COLOUR" )==0) || (strcmp(setkey, "COLOR" )==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue, SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->errcontext.session_default.color = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOUR_ERR" )==0) || (strcmp(setkey, "COLOR_ERR" )==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue, SW_TERMCOL_INT, SW_TERMCOL_STR))>0) c->errcontext.session_default.color_err = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOUR_REP" )==0) || (strcmp(setkey, "COLOR_REP" )==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue, SW_TERMCOL_INT, SW_TERMCOL_STR))>0) c->errcontext.session_default.color_rep = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOUR_WRN" )==0) || (strcmp(setkey, "COLOR_WRN" )==0)) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue, SW_TERMCOL_INT, SW_TERMCOL_STR))>0) c->errcontext.session_default.color_wrn = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "SPLASH" )==0) { if ((i=ppl_fetchSettingByName(&c->errcontext,setvalue, SW_ONOFF_INT, SW_ONOFF_STR ))>0) c->errcontext.session_default.splash = i; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised setting name '%s'.", linecounter, ConfigFname, setkey); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (state == 3) // [colors] section { ppl_strUpper(setkey, setkey); if (strcmp(setkey, "PALETTE" )==0) { PalettePos = 0; StringScan = setvalue; while (strlen(ppl_strCommaSeparatedListScan(&StringScan, ColorName)) != 0) { if (PalettePos == PALETTE_LENGTH-1) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Specified palette is too long.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); c->set->palette_default[PalettePos] = -1; continue; } else { ppl_strUpper(ColorName,ColorName); ColorNumber = ppl_fetchSettingByName(&c->errcontext,ColorName, SW_COLOR_INT, SW_COLOR_STR); if (ColorNumber<=0) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Color '%s' not recognised.", linecounter, ConfigFname, ColorName); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); } else { c->set->palette_default [PalettePos ] = ColorNumber; c->set->paletteS_default[PalettePos ] = 0; c->set->palette1_default[PalettePos ] = 0.0; c->set->palette2_default[PalettePos ] = 0.0; c->set->palette3_default[PalettePos ] = 0.0; c->set->palette4_default[PalettePos++] = 0.0; } } } if (PalettePos > 0) { c->set->palette_default[PalettePos] = -1; } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: The specified palette does not contain any colors.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); } } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised setting name '%s'.", linecounter, ConfigFname, setkey); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (state == 4) // [latex] section { ppl_strUpper(setkey, setkey); if (strcmp(setkey, "PREAMBLE" )==0) strcpy(c->set->term_default.LatexPreamble, setvalue); else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised setting name '%s'.", linecounter, ConfigFname, setkey); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (state == 5) // [variables] section { int stat=0; parserLine *pl = NULL; parserStatus *ps = NULL; ppl_error_setstreaminfo(&c->errcontext, linecounter, ConfigFname); ppl_parserStatInit(&ps,&pl); if ( (ps==NULL) || (c->inputLineBuffer == NULL) ) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); continue; } ppl_tbClear(c); // If line is blank, ignore it { int i=0,j=0; for (i=0; linebuffer[i]!='\0'; i++) if (linebuffer[i]>' ') { j=1; break; } if (j==0) continue; } stat = ppl_parserCompile(c, ps, c->errcontext.error_input_linenumber,c->errcontext.error_input_sourceId,c->errcontext.error_input_filename, linebuffer, 0, 0); if ( (!stat) && (!c->errStat.status) && (ps->blockDepth==0) ) ppl_parserExecute(c, *ps->rootpl, "var_set", 0, 1); if (stat || c->errStat.status) ppl_tbWrite(c); ppl_parserStatFree(&ps); } else if (state == 6) // [functions] section { int stat=0; parserLine *pl = NULL; parserStatus *ps = NULL; ppl_error_setstreaminfo(&c->errcontext, linecounter, ConfigFname); ppl_parserStatInit(&ps,&pl); if ( (ps==NULL) || (c->inputLineBuffer == NULL) ) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); continue; } ppl_tbClear(c); // If line is blank, ignore it { int i=0,j=0; for (i=0; linebuffer[i]!='\0'; i++) if (linebuffer[i]>' ') { j=1; break; } if (j==0) continue; } stat = ppl_parserCompile(c, ps, c->errcontext.error_input_linenumber,c->errcontext.error_input_sourceId,c->errcontext.error_input_filename, linebuffer, 0, 0); if ( (!stat) && (!c->errStat.status) && (ps->blockDepth==0) ) ppl_parserExecute(c, *ps->rootpl, "func_set", 0, 1); if (stat || c->errStat.status) ppl_tbWrite(c); ppl_parserStatFree(&ps); } else if (state == 7) // [units] section { #define GET_UNITNAME(output, last, type, sep, LaTeX) \ if (!LaTeX) { if (isalpha(setkey[i])) do { i++; } while ((isalnum(setkey[i])) || (setkey[i]=='_')); } \ else { while ((setkey[i]!=sep)&&(setkey[i]!='\0')) i++; } \ if (i==j) \ { \ if (&last==&output) \ { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal %s name.", linecounter, ConfigFname, type); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ else \ { \ output = (char *)malloc(strlen(last)+1); \ if (output==NULL) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Out of memory error whilst generating new unit.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ strcpy(output, last); \ } \ } else { \ output = (char *)malloc(i-j+1); \ if (output==NULL) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Out of memory error whilst generating new unit.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } \ strncpy(output, setkey+j, i-j); output[i-j]='\0'; \ } \ while ((setkey[i]<=' ')&&(setkey[i]!='\0')) i++; \ if (setkey[i]==sep) i++; \ while ((setkey[i]<=' ')&&(setkey[i]!='\0')) i++; \ j=i; i=j=0; if (c->unit_pos == UNITS_MAX) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unit definition list full.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } GET_UNITNAME( c->unit_database[c->unit_pos].nameFs , c->unit_database[c->unit_pos].nameFs , "unit" , '/' , 0); GET_UNITNAME( c->unit_database[c->unit_pos].nameAs , c->unit_database[c->unit_pos].nameFs , "unit" , '/' , 0); GET_UNITNAME( c->unit_database[c->unit_pos].nameLs , c->unit_database[c->unit_pos].nameAs , "unit" , '/' , 1); GET_UNITNAME( c->unit_database[c->unit_pos].nameFp , c->unit_database[c->unit_pos].nameFs , "unit" , '/' , 0); GET_UNITNAME( c->unit_database[c->unit_pos].nameAp , c->unit_database[c->unit_pos].nameAs , "unit" , '/' , 0); GET_UNITNAME( c->unit_database[c->unit_pos].nameLp , c->unit_database[c->unit_pos].nameAp , "unit" , ':' , 1); GET_UNITNAME( c->unit_database[c->unit_pos].quantity, c->unit_database[c->unit_pos].quantity, "quantity", ' ' , 0); if (setvalue[0]=='\0') { if (c->baseunit_pos == UNITS_MAX_BASEUNITS) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s:\nBase unit definition list full.", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } c->unit_database[c->unit_pos++].exponent[c->baseunit_pos++] = 1; } else { pplObj setnumeric; setnumeric.refCount=1; j = k = -1; ppl_unitsStringEvaluate(c, setvalue, &setnumeric, &k, &j, errtext); if (j >= 0) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: %s", linecounter, ConfigFname, errtext); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } if (setvalue[k]!='\0') { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unexpected trailing matter in definition", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } if (setnumeric.flagComplex) { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Multiplier in units definition cannot be complex", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } for (j=0; junit_database[c->unit_pos].exponent[j] = setnumeric.exponent[j]; c->unit_database[c->unit_pos].multiplier = setnumeric.real; c->unit_pos++; } } else if (state == 8) // [filters] section { pplObj setnumeric; char *tmp = (char *)malloc(strlen(setvalue)+1); if (tmp!=NULL) { strcpy(tmp, setvalue); pplObjStr(&setnumeric,1,1,tmp); setnumeric.refCount=1; ppl_dictAppendCpy(c->set->filters,setkey,(void *)&setnumeric,sizeof(pplObj)); } } else if (state == 9) // [script] section { c->set->term_current = c->set->term_default; // Copy settings for directive_set() c->set->graph_current = c->set->graph_default; for (i=0; iset->palette_current [i] = c->set->palette_default [i]; c->set->paletteS_current[i] = c->set->paletteS_default[i]; c->set->palette1_current[i] = c->set->palette1_default[i]; c->set->palette2_current[i] = c->set->palette2_default[i]; c->set->palette3_current[i] = c->set->palette3_default[i]; c->set->palette4_current[i] = c->set->palette4_default[i]; } for (i=0; iset->XAxes[i]) ); pplaxis_copy(c,&(c->set->XAxes[i]), &(c->set->XAxesDefault[i])); pplaxis_destroy(c, &(c->set->YAxes[i]) ); pplaxis_copy(c,&(c->set->YAxes[i]), &(c->set->YAxesDefault[i])); pplaxis_destroy(c, &(c->set->ZAxes[i]) ); pplaxis_copy(c,&(c->set->ZAxes[i]), &(c->set->ZAxesDefault[i])); } for (i=0; iset->plot_styles[i])); ppl_withWordsCpy(c, &(c->set->plot_styles[i]) , &(c->set->plot_styles_default[i])); } pplarrow_list_destroy(c, &c->set->pplarrow_list); pplarrow_list_copy(c, &c->set->pplarrow_list, &c->set->pplarrow_list_default); ppllabel_list_destroy(c, &c->set->ppllabel_list); ppllabel_list_copy(c, &c->set->ppllabel_list, &c->set->ppllabel_list_default); { int stat=0; parserLine *pl = NULL; parserStatus *ps = NULL; ppl_parserStatInit(&ps,&pl); ppl_error_setstreaminfo(&c->errcontext, linecounter, ConfigFname); if ( (ps==NULL) || (c->inputLineBuffer == NULL) ) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); continue; } ppl_tbClear(c); // If line is blank, ignore it { int i=0,j=0; for (i=0; linebuffer[i]!='\0'; i++) if (linebuffer[i]>' ') { j=1; break; } if (j==0) continue; } stat = ppl_parserCompile(c, ps, c->errcontext.error_input_linenumber,c->errcontext.error_input_sourceId,c->errcontext.error_input_filename, linebuffer, 0, 0); if ( (!stat) && (!c->errStat.status) && (ps->blockDepth==0) ) ppl_parserExecute(c, *ps->rootpl, "set", 0, 1); if (stat || c->errStat.status) ppl_tbWrite(c); ppl_parserStatFree(&ps); } c->set->term_default = c->set->term_current; // Copy changed settings into defaults c->set->graph_default = c->set->graph_current; for (i=0; iset->palette_default [i] = c->set->palette_current [i]; c->set->paletteS_default[i] = c->set->paletteS_current[i]; c->set->palette1_default[i] = c->set->palette1_current[i]; c->set->palette2_default[i] = c->set->palette2_current[i]; c->set->palette3_default[i] = c->set->palette3_current[i]; c->set->palette4_default[i] = c->set->palette4_current[i]; } for (i=0; iset->XAxesDefault[i]) ); pplaxis_copy(c,&(c->set->XAxesDefault[i]), &(c->set->XAxes[i])); pplaxis_destroy(c, &(c->set->YAxesDefault[i]) ); pplaxis_copy(c,&(c->set->YAxesDefault[i]), &(c->set->YAxes[i])); pplaxis_destroy(c, &(c->set->ZAxesDefault[i]) ); pplaxis_copy(c,&(c->set->ZAxesDefault[i]), &(c->set->ZAxes[i])); } for (i=0; iset->plot_styles_default[i])); ppl_withWordsCpy(c, &(c->set->plot_styles_default[i]) , &(c->set->plot_styles[i])); } pplarrow_list_destroy(c, &c->set->pplarrow_list_default); pplarrow_list_copy(c, &c->set->pplarrow_list_default, &c->set->pplarrow_list); ppllabel_list_destroy(c, &c->set->ppllabel_list_default); ppllabel_list_copy(c, &c->set->ppllabel_list_default, &c->set->ppllabel_list); } else if (state == 10) // [styling] section { ppl_strUpper(setkey, setkey); if (strcmp(setkey, "BASELINE_LINEWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_DEFAULT_LINEWIDTH = fl * EPS_BASE_DEFAULT_LINEWIDTH; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "BASELINE_POINTSIZE" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_DEFAULT_PS = fl * EPS_BASE_DEFAULT_PS; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ARROW_HEADANGLE" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_ARROW_ANGLE = fl * M_PI / 180; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ARROW_HEADSIZE" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_ARROW_HEADSIZE = fl * EPS_BASE_ARROW_HEADSIZE; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "ARROW_HEADBACKINDENT")==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_ARROW_CONSTRICT = fl; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXES_SEPARATION" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_AXES_SEPARATION = fl * EPS_BASE_AXES_SEPARATION; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXES_TEXTGAP" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_AXES_TEXTGAP = fl * EPS_BASE_AXES_TEXTGAP; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXES_LINEWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_AXES_LINEWIDTH = fl * EPS_BASE_AXES_LINEWIDTH; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXES_MAJTICKLEN" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_AXES_MAJTICKLEN = fl * EPS_BASE_AXES_MAJTICKLEN; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "AXES_MINTICKLEN" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_AXES_MINTICKLEN = fl * EPS_BASE_AXES_MINTICKLEN; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOURSCALE_MARGIN" )==0) || (strcmp(setkey, "COLORSCALE_MARGIN" )==0)) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_COLORSCALE_MARGIN= fl * EPS_BASE_COLORSCALE_MARG; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if((strcmp(setkey, "COLOURSCALE_WIDTH" )==0) || (strcmp(setkey, "COLORSCALE_WIDTH" )==0)) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_COLORSCALE_WIDTH = fl * EPS_BASE_COLORSCALE_WIDTH; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRID_MAJLINEWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_GRID_MAJLINEWIDTH = fl * EPS_BASE_GRID_MAJLINEWIDTH; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else if (strcmp(setkey, "GRID_MINLINEWIDTH" )==0) { if (fl=ppl_getFloat(setvalue, &i), ((gsl_finite(fl))&&(i==strlen(setvalue)))) EPS_GRID_MINLINEWIDTH = fl * EPS_BASE_GRID_MINLINEWIDTH; else {sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Illegal value for setting ." , linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Unrecognised setting name '%s'.", linecounter, ConfigFname, setkey); ppl_warning(&c->errcontext, ERR_PREFORMED, c->errcontext.tempErrStr); continue; } } else { sprintf(c->errcontext.tempErrStr, "Error in line %d of configuration file %s: Settings need to be preceded by a block name such as [settings].", linecounter, ConfigFname); ppl_warning(&c->errcontext, ERR_PREFORMED, NULL); break; } } fclose(infile); return; } void ppl_readconfig(ppl_context *c) { int i; char ConfigFname[FNAME_LENGTH]; sprintf(ConfigFname, "%s%s%s", c->errcontext.session_default.homedir, PATHLINK, ".pyxplotrc"); ppl_readConfigFile(c, ConfigFname); sprintf(ConfigFname, "%s", ".pyxplotrc"); ppl_readConfigFile(c, ConfigFname); // Copy Default Settings to Current Settings c->set->term_current = c->set->term_default; c->set->graph_current = c->set->graph_default; for (i=0; iset->palette_current [i] = c->set->palette_default [i]; c->set->paletteS_current[i] = c->set->paletteS_default[i]; c->set->palette1_current[i] = c->set->palette1_default[i]; c->set->palette2_current[i] = c->set->palette2_default[i]; c->set->palette3_current[i] = c->set->palette3_default[i]; c->set->palette4_current[i] = c->set->palette4_default[i]; } for (i=0; iset->XAxes[i]) ); pplaxis_copy(c,&(c->set->XAxes[i]), &(c->set->XAxesDefault[i])); pplaxis_destroy(c, &(c->set->YAxes[i]) ); pplaxis_copy(c,&(c->set->YAxes[i]), &(c->set->YAxesDefault[i])); pplaxis_destroy(c, &(c->set->ZAxes[i]) ); pplaxis_copy(c,&(c->set->ZAxes[i]), &(c->set->ZAxesDefault[i])); } for (i=0; iset->plot_styles[i])); ppl_withWordsCpy(c, &(c->set->plot_styles[i]) , &(c->set->plot_styles_default[i])); } pplarrow_list_destroy(c, &c->set->pplarrow_list); pplarrow_list_copy(c, &c->set->pplarrow_list, &c->set->pplarrow_list_default); ppllabel_list_destroy(c, &c->set->ppllabel_list); ppllabel_list_copy(c, &c->set->ppllabel_list, &c->set->ppllabel_list_default); // Copy List of Preferred Units ppl_listFree(c->unit_PreferredUnits_default); c->unit_PreferredUnits_default = ppl_listCpy(c->unit_PreferredUnits, 1, sizeof(PreferredUnit)); return; } pyxplot-0.9.2/src/epsMaker/0000775000175000017500000000000012026340554014162 5ustar dcf21dcf21pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto3.c0000664000175000017500000000727012026340554021004 0ustar dcf21dcf21// eps_plot_ticking_auto3.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto3.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contain an algorithm for the automatic placement of ticks along axes. // METHOD 3: This axis is linked to another axis of the same length. Use the // same ticking scheme. #define _PPL_EPS_PLOT_TICKING_AUTO3_C 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "mathsTools/dcfmath.h" #include "stringTools/asciidouble.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_plot_ticking_auto2.h" #include "epsMaker/eps_plot_ticking_auto3.h" void eps_plot_ticking_auto3(EPSComm *x, pplset_axis *axis, double UnitMultiplier, unsigned char *AutoTicks, pplset_axis *linkedto) { int i, Nticks_maj, Nticks_min, OutContext; if (DEBUG) ppl_log(&x->c->errcontext,"Using eps_plot_ticking_auto3()"); OutContext = ppl_memAlloc_GetMemContext(); if (linkedto==NULL) goto FAIL; if (axis->linkusing != NULL) goto FAIL; if (linkedto->PhysicalLengthMinor != axis->PhysicalLengthMinor) goto FAIL; if ((linkedto->TickListStrings==NULL)||(linkedto->MTickListStrings==NULL)) goto FAIL; for (Nticks_maj=0; linkedto-> TickListStrings[Nticks_maj]!=NULL; Nticks_maj++); for (Nticks_min=0; linkedto->MTickListStrings[Nticks_min]!=NULL; Nticks_min++); axis-> TickListPositions = linkedto-> TickListPositions; axis->MTickListPositions = linkedto->MTickListPositions; if (axis->format==NULL) { axis-> TickListStrings = linkedto-> TickListStrings; } else { axis-> TickListStrings = (char **)ppl_memAlloc((Nticks_maj+1) * sizeof(char *)); if (axis->TickListStrings==NULL) goto FAIL; for (i=0; iTickListPositions[i]-1e8, axis) * UnitMultiplier; xtmp = eps_plot_axis_InvGetPosition(axis->TickListPositions[i] , axis) * UnitMultiplier; xtmpB = eps_plot_axis_InvGetPosition(axis->TickListPositions[i] , axis) * UnitMultiplier; if ((gsl_finite(xtmpA))&&(gsl_finite(xtmpB))&&(((xtmpA<=0.0)&&(xtmpB>=0.0))||((xtmpA>=0.0)&&(xtmpB<=0.0)))) xtmp=0.0; TickLabelFromFormat(x, &axis->TickListStrings[i], axis->format, xtmp, &axis->DataUnit, axis->xyz, OutContext); } axis->TickListStrings[i] = NULL; } axis->MTickListStrings = (char **)ppl_memAlloc((Nticks_min+1) * sizeof(char *)); if (axis->MTickListStrings == NULL) goto FAIL; for (i=0; iMTickListStrings[i] = ""; axis->MTickListStrings[i] = NULL; // Finished goto CLEANUP; FAIL: if (DEBUG) ppl_log(&x->c->errcontext,"eps_plot_ticking_auto3() has failed"); eps_plot_ticking_auto2(x, axis, UnitMultiplier, AutoTicks, linkedto); CLEANUP: return; } pyxplot-0.9.2/src/epsMaker/eps_ellipse.h0000664000175000017500000000165412026340554016645 0ustar dcf21dcf21// eps_ellipse.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_ellipse.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_ELLIPSE_H #define _PPL_EPS_ELLIPSE_H 1 #include "epsMaker/eps_comm.h" void eps_ellps_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_ellipse.c0000664000175000017500000001054112026340554016633 0ustar dcf21dcf21// eps_ellipse.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_ellipse.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_ELLIPSE 1 #include #include #include #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_ellipse.h" #include "epsMaker/eps_settings.h" void eps_ellps_RenderEPS(EPSComm *x) { int lt; unsigned char filled=0, stroked=0; double lw, lw_scale, xc, yc, a, b, r; double a_inv, b_inv; withWords ww; // Print label at top of postscript description of ellipse fprintf(x->epsbuffer, "%% Canvas item %d [ellipse]\n", x->current->id); eps_core_clear(x); // Calculate position of centre of elipse and its major/minor axes in TeX points xc = x->current->xpos * M_TO_PS; yc = x->current->ypos * M_TO_PS; a = x->current->xpos2 * M_TO_PS; b = x->current->ypos2 * M_TO_PS; r = x->current->rotation; // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(x->c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Set color of outline of ellipse eps_core_SetColor(x, &ww, 1); // Set linewidth and linetype of outline if (ww.USElinewidth) lw_scale = ww.linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww.USElinetype) lt = ww.linetype; else lt = 1; IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); // Set up postscript axes so that a unit circle produces the desired ellipse fprintf(x->epsbuffer, "gsave\n"); fprintf(x->epsbuffer, "%.2f %.2f translate\n", xc, yc); fprintf(x->epsbuffer, "%.2f rotate\n", r*180/M_PI); fprintf(x->epsbuffer, "%.2f %.2f scale\n", a, b); // Set fill color of ellipse eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); // Fill ellipse IF_NOT_INVISIBLE { if (!x->current->arcset) fprintf(x->epsbuffer, "0 0 1 0 360 arc\nclosepath\nfill\n"); else fprintf(x->epsbuffer, "0 0 1 %.2f %.2f arc\n0 0 lineto\nclosepath\nfill\n", x->current->arcfrom*180/M_PI, x->current->arcto*180/M_PI); filled = 1; } // Set color of outline of ellipse eps_core_SetColor(x, &ww, 1); // Make path representing the outline of ellipse IF_NOT_INVISIBLE { if (!x->current->arcset) fprintf(x->epsbuffer, "0 0 1 0 360 arc\nclosepath\n"); // NB: Leave this path unstroked until we've done a grestore else fprintf(x->epsbuffer, "0 0 1 %.2f %.2f arc\n", x->current->arcfrom*180/M_PI, x->current->arcto*180/M_PI); stroked = 1; } // Undo scaling of axes so that linewidths come out right if (a < 1e-8) { a_inv=1e8; } else { a_inv=1.0/a; } if (b < 1e-8) { b_inv=1e8; } else { b_inv=1.0/a; } fprintf(x->epsbuffer, "%f %f scale\n", a_inv, b_inv); // Now we can stroke the path of the ellipse IF_NOT_INVISIBLE fprintf(x->epsbuffer, "stroke\n"); // Stroke outline AFTER grestore, so that linewidth is not scaled. // Undo scaling of postscript axes fprintf(x->epsbuffer, "grestore\n"); x->LastLinewidth = -1; x->LastLinetype = -1; x->LastPSColor[0]='\0'; // Factor ellipse into EPS file's bounding box if (filled || stroked) { eps_core_BoundingBox(x , xc-a*cos(r)-b*sin(r) , yc-a*sin(-r)-b*cos(r) , lw); eps_core_BoundingBox(x , xc-a*cos(r)+b*sin(r) , yc-a*sin(-r)+b*cos(r) , lw); eps_core_BoundingBox(x , xc+a*cos(r)-b*sin(r) , yc+a*sin(-r)-b*cos(r) , lw); eps_core_BoundingBox(x , xc+a*cos(r)+b*sin(r) , yc+a*sin(-r)+b*cos(r) , lw); } // Free with words ppl_withWordsDestroy(x->c, &ww); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_plot.c0000664000175000017500000013370112026340554016160 0ustar dcf21dcf21// eps_plot.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT 1 #include #include #include #include #include #include #include "commands/interpolate_2d_engine.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "settings/colors.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "mathsTools/dcfmath.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_axespaint.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_colormap.h" #include "epsMaker/eps_plot_contourmap.h" #include "epsMaker/eps_plot_filledregion.h" #include "epsMaker/eps_plot_gridlines.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_labelsarrows.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_plot_linedraw.h" #include "epsMaker/eps_plot_linkedaxes.h" #include "epsMaker/eps_plot_styles.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_plot_ticking_auto2.h" #include "epsMaker/eps_plot_ticking_auto3.h" #include "epsMaker/eps_plot_ticking_auto.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_settings.h" #include "datafile.h" #include "datafile_rasters.h" // If a plot dataset has any with_words of the form "with linewidth $4", these // need to be evaluated for every datapoint. We do this by adding additional // items to the UsingList for these datasets. First, we need to check that the // UsingList supplied by the user is of an acceptable form. If it is of the // wrong length, we do nothing; it will fail in due course in ppl_datafile // anyway. If the list is empty, we auto-generate a default list. int eps_plot_AddUsingItemsForWithWords(ppl_context *c, withWords *ww, int *NExpect, unsigned char *autoUsingList, pplExpr ***usingList, int *Nusing, int *NObjs, char *errtext) { *NObjs = 0; *autoUsingList = 0; // If using list was empty, generate an automatic list before we start if (*Nusing==0) { if (*usingList==NULL) *usingList = (pplExpr **)ppl_memAlloc(((*NExpect)+8)*sizeof(pplExpr *)); if (*usingList==NULL) { sprintf(errtext, "Out of memory (a)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return 1; } if (ppldata_autoUsingList(c, *usingList, *NExpect, errtext)) return 1; *Nusing = *NExpect; *autoUsingList = 1; } else if ((*Nusing==1) && (*NExpect==2)) // Prepend data point number if only one number specified in using statement { int end=0,ep=0,es=0; char ascii[10]; pplExpr *exptmp=NULL; (*usingList)[1] = (*usingList)[0]; sprintf(ascii, "%d", 0); ppl_expCompile(c,0,0,"",ascii,&end,0,0,0,&exptmp,&ep,&es,errtext); if (es || c->errStat.status) { ppl_tbClear(c); sprintf(errtext, "Out of memory (b)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return 1; } (*usingList)[0] = pplExpr_tmpcpy(exptmp); pplExpr_free(exptmp); if ((*usingList)[0]==NULL) { sprintf(errtext, "Out of memory (c)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return 1; } *Nusing=2; } // If using list is wrong length, give up and let ppl_datafile return an error if (*Nusing != *NExpect) return 0; if (ww->linespoints == SW_STYLE_CONTOURMAP) return 0; // Contourplot evaluate expressions in terms of c1 #define ADD_FAKE_USING_ITEM(X) \ { \ (*usingList)[(*NExpect)++] = pplExpr_tmpcpy(X); \ *Nusing = *NExpect; \ } // Now cycle through all with_words which can be item-specific if (ww->EXPlinetype != NULL) ADD_FAKE_USING_ITEM(ww->EXPlinetype ); if (ww->EXPlinewidth != NULL) ADD_FAKE_USING_ITEM(ww->EXPlinewidth ); if (ww->EXPpointlinewidth != NULL) ADD_FAKE_USING_ITEM(ww->EXPpointlinewidth); if (ww->EXPpointsize != NULL) ADD_FAKE_USING_ITEM(ww->EXPpointsize ); if (ww->EXPpointtype != NULL) ADD_FAKE_USING_ITEM(ww->EXPpointtype ); if (ww->EXPcolor != NULL) { ADD_FAKE_USING_ITEM(ww->EXPcolor ); (*NObjs)++; } if (ww->EXPfillcolor != NULL) { ADD_FAKE_USING_ITEM(ww->EXPfillcolor ); (*NObjs)++; } return 0; } #define PROJ_DBL \ { \ dbl = DataRow[i--]; \ if (i<0) i=0; \ if (!gsl_finite(dbl)) dbl=0.0; \ } #define PROJ0_1 \ { \ PROJ_DBL; \ if (dbl < 0.0) dbl= 0.0; \ if (dbl > 1.0) dbl= 1.0; \ } #define PROJ_INT \ { \ PROJ_DBL; \ if (dbl < INT_MIN) dbl=INT_MIN+1; \ if (dbl > INT_MAX) dbl=INT_MAX-1; \ } void eps_plot_WithWordsFromUsingItems(ppl_context *c, withWords *ww, double *DataRow, pplObj *ObjRow, int Ncolumns, int Ncol_obj) { int i=Ncolumns-1, j=Ncol_obj-1; double dbl; if (ww->linespoints == SW_STYLE_CONTOURMAP) return; // Contourplot evaluate expressions in terms of c1 if (ww->EXPfillcolor != NULL) { ppl_colorFromObj(c, &ObjRow[j--], &ww->fillcolor, &ww->FillCol1234Space, &ww->EXPfillcolor, &ww->fillcolor1, &ww->fillcolor2, &ww->fillcolor3, &ww->fillcolor4, &ww->USEfillcolor, &ww->USEfillcolor1234); } if (ww->EXPcolor != NULL) { ppl_colorFromObj(c, &ObjRow[j--], &ww->color, &ww->Col1234Space, &ww->EXPcolor, &ww->color1, &ww->color2, &ww->color3, &ww->color4, &ww->USEcolor, &ww->USEcolor1234); } if (ww->EXPpointtype != NULL) { PROJ_INT ; ww->USEpointtype = 1; ww->pointtype = (int)dbl; ww->AUTOpointtype = 0; } if (ww->EXPpointsize != NULL) { PROJ_DBL ; ww->USEpointsize = 1; ww->pointsize = dbl; } if (ww->EXPpointlinewidth != NULL) { PROJ_DBL ; ww->USEpointlinewidth = 1; ww->pointlinewidth = dbl; } if (ww->EXPlinewidth != NULL) { PROJ_DBL ; ww->USElinewidth = 1; ww->linewidth = dbl; } if (ww->EXPlinetype != NULL) { PROJ_INT ; ww->USElinetype = 1; ww->linetype = (int)dbl; ww->AUTOlinetype = 0; } return; } #define WWCUID(X) \ if (!firstValues[i].dimensionless) { sprintf(c->errcontext.tempErrStr, "The expression specified for the %s should have been dimensionless, but instead had units of <%s>. Cannot plot this dataset.", X, ppl_printUnit(c, firstValues+i, NULL, NULL, 0, 1, 0)); ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, NULL); return 1; } \ i--; \ if (i<0) i=0; int eps_plot_WithWordsCheckUsingItemsDimLess(ppl_context *c, withWords *ww, pplObj *firstValues, int Ncolumns, int Ncolumns_obj, int *NDataCols) { int i = Ncolumns-1; if (ww->linespoints == SW_STYLE_CONTOURMAP) return 0; // Contourplot evaluate expressions in terms of c1 if (ww->EXPpointtype != NULL) { WWCUID("point type"); } if (ww->EXPpointsize != NULL) { WWCUID("point size"); } if (ww->EXPpointlinewidth != NULL) { WWCUID("point line width"); } if (ww->EXPlinewidth != NULL) { WWCUID("line width"); } if (ww->EXPlinetype != NULL) { WWCUID("line type"); } if (NDataCols!=NULL) *NDataCols=i+1; // The number of columns which contain data which is not from with .... expressions return 0; } // Private routines for sorting 3D positions by depth and azimuth when clipping 3D plots static int SortByDepth(const void *x, const void *y) { const double *xd = (const double *)x; const double *yd = (const double *)y; if (xd[2]>yd[2]) return 1; if (xd[2]ay) return 1; if (ax 0) { errCount--; #define COUNTERR_END if (errCount==0) { sprintf(c->errcontext.tempErrStr, "Too many errors: no more errors will be shown."); \ ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { ppl_warning(&c->errcontext,ERR_STACKED,"Stack forward reference detected."); } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } // Loop through all of the datasets plotted in a single plot command. // Initialise the datastructures for the plot command which we will fill in the // process of deciding how to render the graph. Then read in data from // datafiles and parametric functions. Do not read in data from non-parametric // functions as we need to finalise axis ranges first, before we know what // raster we will sample them on. void eps_plot_ReadAccessibleData(EPSComm *x) { ppl_context *c = x->c; int i, j, k, Ndatasets, Ccounter=0, LTcounter=0, PTcounter=0; canvas_plotdesc *pd; canvas_plotrange *pr; pplset_axis *axis, *axissets[3]; withWords ww_default; double *ordinate_raster, *ordinate2_raster, size[3], ScreenSize[3], ScreenBearing[3]; axissets[0] = x->current->XAxes; axissets[1] = x->current->YAxes; axissets[2] = x->current->ZAxes; // Work out lengths of x-, y- and z-axes size[0] = x->current->settings.width.real; if (x->current->settings.AutoAspect == SW_ONOFF_ON) size[1] = size[0] * 2.0/(1.0+sqrt(5)); else size[1] = size[0] * x->current->settings.aspect; if (x->current->settings.AutoZAspect == SW_ONOFF_ON) size[2] = size[0] * 2.0/(1.0+sqrt(5)); else size[2] = size[0] * x->current->settings.zaspect; // Work out projected lengths of these axes on screen if (!x->current->ThreeDim) { memcpy(ScreenSize, size, 3*sizeof(double)); ScreenBearing[0] = M_PI/2; ScreenBearing[1] = 0.0; ScreenBearing[2] = 0.0; } else for (j=0; j<3; j++) { double x1,y1,z1,x2,y2,z2; eps_plot_ThreeDimProject((j==0)?0:0.5,(j==1)?0:0.5,(j==2)?0:0.5,&x->current->settings,0,0,size[0],size[1],size[2],&x1,&y1,&z1); eps_plot_ThreeDimProject((j==0)?1:0.5,(j==1)?1:0.5,(j==2)?1:0.5,&x->current->settings,0,0,size[0],size[1],size[2],&x2,&y2,&z2); ScreenSize [j] = hypot(x2-x1,y2-y1); ScreenBearing[j] = atan2(x2-x1,y2-y1); if (!gsl_finite(ScreenSize [j])) ScreenSize [j] = 0.0; if (!gsl_finite(ScreenBearing[j])) ScreenBearing[j] = 0.0; } // First clear all range information from all axes. // Also, transfer range information from [Min,Max,unit] to [HardMin,HardMax,HardUnit]. for (j=0; j<3; j++) { pplset_axis *axes = axissets[j]; double PhysicalLengthMajor = ScreenSize[j] / (0.015 + 0.01*fabs(sin(ScreenBearing[j]))); double PhysicalLengthMinor = ScreenSize[j] / 0.004; for (i=0; icurrent->id; axes[i].TickListFinalised = 0; axes[i].TickListPositions = axes[i].MTickListPositions = NULL; axes[i].TickListStrings = axes[i].MTickListStrings = NULL; pplObjNum(&axes[i].DataUnit,0,0,0); } } // Transfer range information from plot [foo:bar] to HardMin and HardMax variables in axes pr = x->current->plotranges; k = 0; while (pr != NULL) { int Ndirs, xyz, axis_n; Ndirs = x->current->ThreeDim ? 3 : 2; xyz = (k%Ndirs); axis_n = 1+k/Ndirs; if (axis_n > MAX_AXES) axis_n=0; axis = &axissets[xyz][axis_n]; // Check if we have partial range which conflicts with units of range of axis if ((pr->MinSet && (!pr->MaxSet)) && axis->HardMaxSet && (!pr->AutoMaxSet) && (!ppl_unitsDimEqual(&axis->HardUnit, &pr->unit))) { sprintf(c->errcontext.tempErrStr, "The minimum limit specified for axis %c%d in the plot command has conflicting units with the maximum limit of that axis: the former has units of <%s> whilst the latter has units of <%s>.", "xyzc"[xyz], axis_n, ppl_printUnit(c,&pr->unit,NULL,NULL,0,1,0), ppl_printUnit(c,&axis->HardUnit,NULL,NULL,1,1,0)); ppl_error(&c->errcontext,ERR_NUMERICAL, -1, -1, NULL); *(x->status) = 1; return; } if (((!pr->MinSet) && pr->MaxSet) && axis->HardMinSet && (!pr->AutoMinSet) && (!ppl_unitsDimEqual(&axis->HardUnit, &pr->unit))) { sprintf(c->errcontext.tempErrStr, "The maximum limit specified for axis %c%d in the plot command has conflicting units with the minimum limit of that axis: the former has units of <%s> whilst the latter has units of <%s>.", "xyzc"[xyz], axis_n, ppl_printUnit(c,&pr->unit,NULL,NULL,0,1,0), ppl_printUnit(c,&axis->HardUnit,NULL,NULL,1,1,0)); ppl_error(&c->errcontext,ERR_NUMERICAL, -1, -1, NULL); *(x->status) = 1; return; } // Read information about axis range out of list of ranges supplied to the plot command, ready to pass to eps_plot_ticking if (pr->MinSet) { axis->HardMinSet = 1; axis->HardMin = pr->min; } if (pr->MaxSet) { axis->HardMaxSet = 1; axis->HardMax = pr->max; } if (pr->AutoMinSet) { axis->HardAutoMinSet = 1; axis->HardMinSet = 0; } if (pr->AutoMaxSet) { axis->HardAutoMaxSet = 1; axis->HardMaxSet = 0; } // Update axis->HardUnit to be the canonical reference for the units of the range specified for this axis if (pr->MinSet || pr->MaxSet) { axis->HardUnitSet=1; axis->HardUnit=pr->unit; } if ((!axis->HardMinSet) && (!axis->HardMaxSet) && (axis->tics.tickList==NULL) && (((axis->log==SW_BOOL_TRUE)?(axis->tics.tickMinSet):(axis->tics.tickStepSet))==0) && (axis->ticsM.tickList==NULL) && (((axis->log==SW_BOOL_TRUE)?(axis->ticsM.tickMinSet):(axis->ticsM.tickStepSet))==0)) { axis->HardUnitSet=0; } pr=pr->next; k++; } // Proprogate range information to linked axes for (j=0; j<3; j++) { pplset_axis *axes = axissets[j]; for (i=0; icurrent->plotitems; Ndatasets = 0; while (pd != NULL) { pd=pd->next; Ndatasets++; } // Malloc pointers to data tables where data to be plotted will be stored if (Ndatasets>0) { int i; x->current->plotdata = (dataTable **)ppl_memAlloc(Ndatasets * sizeof(dataTable *)); x->current->DatasetTextID = (int *)ppl_memAlloc(Ndatasets * sizeof(int)); if ( (x->current->plotdata==NULL) || (x->current->DatasetTextID==NULL) ) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (d)."); *(x->status) = 1; return; } for (i=0; icurrent->plotdata [i] = NULL; for (i=0; icurrent->DatasetTextID[i] = 0; } else { x->current->plotdata = NULL; x->current->DatasetTextID = NULL; } // Make raster on which to evaluate parametric functions if (x->current->settings.USE_T_or_uv) { ordinate_raster = (double *)ppl_memAlloc(x->current->settings.samples * sizeof(double)); ordinate2_raster = NULL; if (ordinate_raster == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (e)."); *(x->status) = 1; return; } if (x->current->settings.Tlog == SW_BOOL_TRUE) ppl_logRaster(ordinate_raster, x->current->settings.Tmin.real, x->current->settings.Tmax.real, x->current->settings.samples); else ppl_linRaster(ordinate_raster, x->current->settings.Tmin.real, x->current->settings.Tmax.real, x->current->settings.samples); } else { int SX = (x->current->settings.SamplesXAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX; int SY = (x->current->settings.SamplesYAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY; ordinate_raster = (double *)ppl_memAlloc(x->current->settings.SamplesX * sizeof(double)); ordinate2_raster = (double *)ppl_memAlloc(x->current->settings.SamplesY * sizeof(double)); if ((ordinate_raster == NULL)||(ordinate2_raster == NULL)) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (f)."); *(x->status) = 1; return; } if (x->current->settings.Ulog == SW_BOOL_TRUE) ppl_logRaster(ordinate_raster , x->current->settings.Umin.real, x->current->settings.Umax.real, SX); else ppl_linRaster(ordinate_raster , x->current->settings.Umin.real, x->current->settings.Umax.real, SX); if (x->current->settings.Vlog == SW_BOOL_TRUE) ppl_logRaster(ordinate2_raster, x->current->settings.Vmin.real, x->current->settings.Vmax.real, SY); else ppl_linRaster(ordinate2_raster, x->current->settings.Vmin.real, x->current->settings.Vmax.real, SY); } // Loop through all datasets pd = x->current->plotitems; i = 0; while (pd != NULL) { double *special_raster=NULL, *special_raster2=NULL; pd->filenameFinal=NULL; pd->TitleFinal=NULL; pd->TitleFinal_col=0; pd->TitleFinal_height = pd->TitleFinal_width = pd->TitleFinal_xpos = pd->TitleFinal_ypos = 0; // Merge together with words to form a final set eps_withwords_default(x, &ww_default, &x->current->settings, pd->function, Ccounter, LTcounter, PTcounter, c->set->term_current.color==SW_ONOFF_ON); ppl_withWordsDestroy(c, &pd->ww_final); if (pd->function != 0) { ppl_withWordsMerge(c, &pd->ww_final, &pd->ww, &x->current->settings.funcStyle, &ww_default, NULL, NULL, 1); } else { ppl_withWordsMerge(c, &pd->ww_final, &pd->ww, &x->current->settings.dataStyle, &ww_default, NULL, NULL, 1); } eps_withwords_default_counterinc(x, &Ccounter, <counter, &PTcounter, c->set->term_current.color==SW_ONOFF_ON, &pd->ww_final, &x->current->settings); // Mark up axes which are going to be used for any dataset, from datafile or functions axissets[pd->axis1xyz][pd->axis1].FinalActive = 1; axissets[pd->axis2xyz][pd->axis2].FinalActive = 1; axissets[pd->axis3xyz][pd->axis3].FinalActive = 1; // If plotting a datafile, can read in data now, so do so if ((pd->function == 0) || (pd->parametric == 1)) { pplExpr **UsingList; unsigned char autoUsingList = 0; int NUsing = pd->NUsing; int nObjs = 0; int errCount = DATAFILE_NERRS; int status = 0; int NExpect = eps_plot_styles_NDataColumns(&c->errcontext, pd->ww_final.linespoints, x->current->ThreeDim); UsingList = (pplExpr **)ppl_memAlloc( (USING_ITEMS_MAX+8) * sizeof(pplExpr *) ); if (UsingList == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory."); *(x->status) = 1; return; } memcpy(UsingList, pd->UsingList, NUsing*sizeof(pplExpr *)); if (pd->ww_final.linespoints==SW_STYLE_COLORMAP) { int listlen = NUsing; if ((listlen>=3)&&(listlen<=6)) NExpect=listlen; else if ((pd->function)&&(pd->NFunctions>=3)&&(pd->NFunctions<=6)) NExpect=pd->NFunctions; } if (eps_plot_AddUsingItemsForWithWords(c, &pd->ww_final, &NExpect, &autoUsingList, &UsingList, &NUsing, &nObjs, c->errcontext.tempErrStr)) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, NULL); *(x->status) = 1; return; } // Add extra using items for, e.g. "linewidth $3". if (pd->function == 0) // Read data from file { if (pd->filename != NULL) // Read data from file { if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from file '%s' for dataset %d in plot item %d", pd->filename, i+1, x->current->id); ppl_log(&c->errcontext,NULL); } if (pd->PersistentDataTable==NULL) { char *fnameFinal, tmp[FNAME_LENGTH]=""; ppldata_fromFile(c, x->current->plotdata+i, pd->filename, 0, tmp, NULL, pd->index, UsingList, autoUsingList, NExpect, nObjs, pd->label, pd->SelectCriterion, NULL, pd->UsingRowCols, pd->EveryList, pd->continuity, 0, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); fnameFinal = (char *)ppl_memAlloc(strlen(tmp)+1); if (fnameFinal!=NULL) strcpy(fnameFinal, tmp); pd->filenameFinal = fnameFinal; } else x->current->plotdata[i] = pd->PersistentDataTable; } else if (pd->vectors != NULL) { if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from vectors for dataset %d in plot item %d", i+1, x->current->id); ppl_log(&c->errcontext,NULL); } ppldata_fromVectors(c, x->current->plotdata+i, pd->vectors, pd->NFunctions, UsingList, autoUsingList, NExpect, nObjs, pd->label, pd->SelectCriterion, NULL, pd->continuity, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); } } else { int Nsamples , Nsamples2, USE_T_or_uv; pplObj *raster_unit , *raster2_unit; USE_T_or_uv = x->current->settings.USE_T_or_uv; if (pd->TRangeSet) USE_T_or_uv = !pd->VRangeSet; if (USE_T_or_uv) { special_raster = ordinate_raster; special_raster2 = NULL; Nsamples = x->current->settings.samples; Nsamples2 = 0; raster_unit = &x->current->settings.Tmin; raster2_unit = NULL; ppldata_fromFuncs_checkSpecialRaster(c, pd->functions, pd->NFunctions, "t", &x->current->settings.Tmin.real, &x->current->settings.Tmax.real, raster_unit, &special_raster, &Nsamples); } else { special_raster = ordinate_raster; special_raster2 = ordinate2_raster; Nsamples = (x->current->settings.SamplesXAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX; Nsamples2 = (x->current->settings.SamplesYAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY; raster_unit = &x->current->settings.Umin; raster2_unit = &x->current->settings.Vmin; ppldata_fromFuncs_checkSpecialRaster(c, pd->functions, pd->NFunctions, "u", &x->current->settings.Umin.real, &x->current->settings.Umax.real, raster_unit, &special_raster, &Nsamples); ppldata_fromFuncs_checkSpecialRaster(c, pd->functions, pd->NFunctions, "v", &x->current->settings.Vmin.real, &x->current->settings.Vmax.real, raster2_unit, &special_raster2, &Nsamples2); } if ((special_raster == ordinate_raster) && (pd->TRangeSet)) { int N; if (USE_T_or_uv) N = x->current->settings.samples; else N = (x->current->settings.SamplesXAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX; special_raster = (double *)ppl_memAlloc(N * sizeof(double)); if (special_raster == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (g)."); *(x->status) = 1; return; } if ((USE_T_or_uv ? x->current->settings.Tlog : x->current->settings.Ulog) == SW_BOOL_TRUE) ppl_logRaster(special_raster, pd->Tmin.real, pd->Tmax.real, N); else ppl_linRaster(special_raster, pd->Tmin.real, pd->Tmax.real, N); Nsamples = N; raster_unit = &pd->Tmin; } if ((special_raster2 == ordinate2_raster) && (pd->VRangeSet)) { int N; N = (x->current->settings.SamplesYAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY; special_raster2 = (double *)ppl_memAlloc(N * sizeof(double)); if (special_raster2 == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (h)."); *(x->status) = 1; return; } if (x->current->settings.Vlog == SW_BOOL_TRUE) ppl_logRaster(special_raster2, pd->Vmin.real, pd->Vmax.real, N); else ppl_linRaster(special_raster2, pd->Vmin.real, pd->Vmax.real, N); Nsamples2 = N; raster2_unit = &pd->Vmin; } if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from parametric functions for dataset %d in plot item %d", i+1, x->current->id); ppl_log(&c->errcontext,NULL); } ppldata_fromFuncs(c, x->current->plotdata+i, pd->functions, pd->NFunctions, special_raster, Nsamples, 1, raster_unit, special_raster2, Nsamples2, raster2_unit, UsingList, autoUsingList, NExpect, nObjs, pd->label, pd->SelectCriterion, NULL, pd->continuity, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); pd->GridXSize = Nsamples; pd->GridYSize = Nsamples2; } if (status) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, NULL); x->current->plotdata[i]=NULL; } else { // Update axes to reflect usage status=eps_plot_styles_UpdateUsage(x, x->current->plotdata[i], pd->ww_final.linespoints, x->current->ThreeDim, &axissets[pd->axis1xyz][pd->axis1], &axissets[pd->axis2xyz][pd->axis2], &axissets[pd->axis3xyz][pd->axis3], &x->current->settings, pd->axis1xyz, pd->axis2xyz, pd->axis3xyz, pd->axis1, pd->axis2, pd->axis3, x->current->id); if (status) { *(x->status) = 1; return; } eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis1xyz][pd->axis1]); eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis2xyz][pd->axis2]); eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis3xyz][pd->axis3]); } // If plotting surface, colormap or contourmap, resample data onto grid if (((pd->ww_final.linespoints==SW_STYLE_SURFACE)&&(special_raster2==NULL)) || (pd->ww_final.linespoints==SW_STYLE_COLORMAP) || (pd->ww_final.linespoints==SW_STYLE_CONTOURMAP)) { dataTable *tmpdata = x->current->plotdata[i]; // Fix range of axes eps_plot_LinkedAxisForwardPropagate(x, &axissets[pd->axis1xyz][pd->axis1], 1); if (*x->status) return; eps_plot_LinkedAxisForwardPropagate(x, &axissets[pd->axis2xyz][pd->axis2], 1); if (*x->status) return; ppl_interp2d_grid(c, x->current->plotdata+i, &x->current->settings, tmpdata, &axissets[pd->axis1xyz][pd->axis1], &axissets[pd->axis2xyz][pd->axis2], (pd->ww_final.linespoints!=SW_STYLE_COLORMAP), &pd->GridXSize, &pd->GridYSize); } } pd=pd->next; i++; } return; } // Loop through all of the datasets plotting within a single plot command, and // pick out those which are plotting functions which need to be rasterised // along an ordinate axis (i.e. those which are not parametric). At this stage, // we need to finalise the range of the ordinate axis, create a raster of // values along it, and sample the function. After calling this function, all // datasets plotted by the plot command will then have been sampled and be // ready for plotting. void eps_plot_SampleFunctions(EPSComm *x) { ppl_context *c = x->c; int a, i, j, OrdinateRasterLen, Nsamples, OrdinateRasterLen2; canvas_plotdesc *pd; pplset_axis *OrdinateAxis, *OrdinateAxis2, *axissets[3]; unsigned char prev_RangeFinalised, prev_TickListFinalised; char errbuffer[LSTR_LENGTH]; unsigned char SampleGrid; double *OrdinateRaster, *OrdinateRaster2; double *SpecialRaster; axissets[0] = x->current->XAxes; axissets[1] = x->current->YAxes; axissets[2] = x->current->ZAxes; // Loop through all datasets pd = x->current->plotitems; i = 0; while (pd != NULL) { if ((pd->function == 1) && (pd->parametric == 0)) { int status = 0; int errCount = DATAFILE_NERRS; int NExpect = eps_plot_styles_NDataColumns(&c->errcontext, pd->ww_final.linespoints, x->current->ThreeDim); int NUsing = pd->NUsing; int nObjs = 0; unsigned char autoUsingList = 0; pplExpr **UsingList; OrdinateAxis = &axissets[pd->axis1xyz][pd->axis1]; prev_RangeFinalised = axissets[pd->axis1xyz][pd->axis1].RangeFinalised; prev_TickListFinalised = axissets[pd->axis1xyz][pd->axis1].TickListFinalised; UsingList = (pplExpr **)ppl_memAlloc( (USING_ITEMS_MAX+8) * sizeof(pplExpr *) ); if (UsingList == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory."); *(x->status) = 1; return; } memcpy(UsingList, pd->UsingList, NUsing*sizeof(pplExpr *)); if (pd->ww_final.linespoints==SW_STYLE_COLORMAP) { int listlen = NUsing; if ((listlen>=3)&&(listlen<=6)) NExpect=listlen; else if ((pd->function)&&(pd->NFunctions>=1)&&(pd->NFunctions<=4)) NExpect=pd->NFunctions+2; } if (eps_plot_AddUsingItemsForWithWords(c, &pd->ww_final, &NExpect, &autoUsingList, &UsingList, &NUsing, &nObjs, c->errcontext.tempErrStr)) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, NULL); *(x->status) = 1; return; } // Add extra using items for, e.g. "linewidth $3". if (NExpect != NUsing) { sprintf(c->errcontext.tempErrStr, "The supplied using ... clause contains the wrong number of items. We need %d columns of data, but %d have been supplied.", NExpect, NUsing); ppl_error(&c->errcontext,ERR_SYNTAX,-1,-1,NULL); *(x->status) = 1; return; } // Check whether we're sampling along one axis, or sampling a grid SampleGrid = (pd->ww_final.linespoints == SW_STYLE_SURFACE) || (pd->ww_final.linespoints == SW_STYLE_COLORMAP) || (pd->ww_final.linespoints == SW_STYLE_CONTOURMAP); OrdinateAxis2 = SampleGrid ? (&axissets[pd->axis2xyz][pd->axis2]) : NULL; OrdinateRasterLen2 = 0; OrdinateRaster2 = NULL; // Loop over one (or two) ordinate axes for (a=0; a<=SampleGrid; a++) { int *_OrdinateRasterLen; double **_OrdinateRaster; pplset_axis **_OrdinateAxis; if (!a) { _OrdinateRasterLen = &OrdinateRasterLen ; _OrdinateRaster = &OrdinateRaster ; _OrdinateAxis = &OrdinateAxis ; } else { _OrdinateRasterLen = &OrdinateRasterLen2; _OrdinateRaster = &OrdinateRaster2; _OrdinateAxis = &OrdinateAxis2; } // Fix range of ordinate axis eps_plot_LinkedAxisForwardPropagate(x, *_OrdinateAxis, 1); if (*x->status) return; // Fetch ordinate raster to plot function along if ((pd->ww_final.linespoints == SW_STYLE_BOXES) || (pd->ww_final.linespoints == SW_STYLE_HISTEPS)) { // boxes and histeps plot styles have their own special rasters int k; double left, right, left2=GSL_NAN, right2=GSL_NAN, width; left = eps_plot_axis_InvGetPosition(0.0, *_OrdinateAxis); right = eps_plot_axis_InvGetPosition(1.0, *_OrdinateAxis); if (x->current->settings.BoxWidth.real>0) width = x->current->settings.BoxWidth.real; else width = fabs(left-right)/(x->current->settings.samples); left += width/2 * ((right>left) ? 1.0 : -1.0); right += width/2 * ((left>right) ? 1.0 : -1.0); for (k=0; k<=(*_OrdinateAxis)->AxisValueTurnings; k++) { left2 = eps_plot_axis_GetPosition(left, *_OrdinateAxis, k, 0); if (gsl_finite(left2 )) break; } for (k=(*_OrdinateAxis)->AxisValueTurnings; k>=0; k++) { right2 = eps_plot_axis_GetPosition(right,*_OrdinateAxis, k, 0); if (gsl_finite(right2)) break; } if ((!gsl_finite(left2))||(!gsl_finite(right2))||(right2<=left2)||(left2<0)||(left2>1)||(right2<0)||(right2>1)) { left2=0.0; right2=1.0; } *_OrdinateRaster = (double *)ppl_memAlloc(x->current->settings.samples * sizeof(double)); if (*_OrdinateRaster == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (i)."); *(x->status) = 1; return; } for (j=0; jcurrent->settings.samples; j++) (*_OrdinateRaster)[j] = eps_plot_axis_InvGetPosition(left2 + (right2-left2)*((double)j)/(x->current->settings.samples-1), *_OrdinateAxis); *_OrdinateRasterLen = x->current->settings.samples; } else // all other plot styles have rasters running from min -> max { if (SampleGrid || (*_OrdinateAxis)->OrdinateRaster == NULL) // Make ordinate raster if we don't already have one { int Nsamp = (!SampleGrid) ? x->current->settings.samples : ((!a) ? ( (x->current->settings.SamplesXAuto == SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX ) : ( (x->current->settings.SamplesYAuto == SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY ) ); *_OrdinateRaster = (double *)ppl_memAlloc(Nsamp * sizeof(double)); if (*_OrdinateRaster == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (j)."); *(x->status) = 1; return; } for (j=0; jOrdinateRaster = *_OrdinateRaster; (*_OrdinateAxis)->OrdinateRasterLen = *_OrdinateRasterLen; } } else { *_OrdinateRaster = (*_OrdinateAxis)->OrdinateRaster; *_OrdinateRasterLen = (*_OrdinateAxis)->OrdinateRasterLen; } } } if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from functions for dataset %d in plot item %d", i+1, x->current->id); ppl_log(&c->errcontext,NULL); } // Get data from functions SpecialRaster = OrdinateRaster; Nsamples = OrdinateRasterLen; if (!SampleGrid) { ppldata_fromFuncs_checkSpecialRaster(c, pd->functions, pd->NFunctions, pd->parametric?"t":"x", NULL, NULL, &OrdinateAxis->DataUnit, &SpecialRaster, &Nsamples); } ppldata_fromFuncs(c, x->current->plotdata+i, pd->functions, pd->NFunctions, SpecialRaster, Nsamples, pd->parametric, &OrdinateAxis->DataUnit, OrdinateRaster2, OrdinateRasterLen2, (OrdinateAxis2==NULL)?NULL:&OrdinateAxis2->DataUnit, UsingList, autoUsingList, NExpect, nObjs, pd->label, pd->SelectCriterion, NULL, pd->continuity, &status, errbuffer, &errCount, x->iterDepth); pd->GridXSize = Nsamples; pd->GridYSize = OrdinateRasterLen2; if (status) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, errbuffer); x->current->plotdata[i]=NULL; } // Update axes to reflect usage status=eps_plot_styles_UpdateUsage(x, x->current->plotdata[i], pd->ww_final.linespoints, x->current->ThreeDim, &axissets[pd->axis1xyz][pd->axis1], &axissets[pd->axis2xyz][pd->axis2], &axissets[pd->axis3xyz][pd->axis3], &x->current->settings, pd->axis1xyz, pd->axis2xyz, pd->axis3xyz, pd->axis1, pd->axis2, pd->axis3, x->current->id); if (status) { *(x->status) = 1; return; } eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis1xyz][pd->axis1]); eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis2xyz][pd->axis2]); eps_plot_LinkedAxisBackPropagate(x, &axissets[pd->axis3xyz][pd->axis3]); if (!SampleGrid) { axissets[pd->axis1xyz][pd->axis1].RangeFinalised = prev_RangeFinalised; axissets[pd->axis1xyz][pd->axis1].TickListFinalised = prev_TickListFinalised; } } pd=pd->next; i++; } return; } void eps_plot_YieldUpText(EPSComm *x) { int j, k, l; canvas_plotdesc *pd; dataBlock *blk; pplset_axis *axes; x->current->FirstTextID = x->NTextItems; // Labels attached to data points pd = x->current->plotitems; k = 0; while (pd != NULL) // loop over all datasets { pd->CRangeDisplay = 0; x->current->DatasetTextID[k] = x->NTextItems; if (pd->ww_final.linespoints == SW_STYLE_COLORMAP) { eps_plot_colormap_YieldText(x, x->current->plotdata[k], &x->current->settings, pd); } else if (pd->ww_final.linespoints == SW_STYLE_CONTOURMAP) { eps_plot_contourmap_YieldText(x, x->current->plotdata[k], &x->current->settings, pd); } else if (x->current->plotdata[k] != NULL) { blk = x->current->plotdata[k]->first; while (blk != NULL) { if (blk->text != NULL) for (j=0; jblockPosition; j++) { YIELD_TEXTITEM(blk->text[j]); } blk=blk->next; } } pd=pd->next; k++; } // Text for the 'set label' command x->current->SetLabelTextID = x->NTextItems; eps_plot_labelsarrows_YieldUpText(x); // Graph legend x->current->LegendTextID = x->NTextItems; GraphLegend_YieldUpText(x); // Axis labels and titles for (j=0; j<2+(x->current->ThreeDim); j++) { if (j==0) axes = x->current->XAxes; else if (j==1) axes = x->current->YAxes; else axes = x->current->ZAxes; for (k=0; kNTextItems; if (axes[k]. TickListPositions != NULL) for (l=0; axes[k]. TickListStrings[l]!=NULL; l++) { YIELD_TEXTITEM(axes[k]. TickListStrings[l]); } // Major tick labels if (axes[k].MTickListPositions != NULL) for (l=0; axes[k].MTickListStrings[l]!=NULL; l++) { YIELD_TEXTITEM(axes[k].MTickListStrings[l]); } // Minor tick labels YIELD_TEXTITEM(axes[k].FinalAxisLabel); } } // Title of plot x->current->TitleTextID = x->NTextItems; YIELD_TEXTITEM(x->current->settings.title); return; } // Finally, produce a postscript plot void eps_plot_RenderEPS(EPSComm *x) { ppl_context *c = x->c; int i, j, status, xyzaxis[3]; double origin_x, origin_y, width, height, zdepth; canvas_plotdesc *pd; pplset_axis *a1, *a2, *a3, *axissets[3]; x->LaTeXpageno = x->current->FirstTextID; axissets[0] = x->current->XAxes; axissets[1] = x->current->YAxes; axissets[2] = x->current->ZAxes; // Write header at top of postscript fprintf(x->epsbuffer, "%% Canvas item %d [plot]\n", x->current->id); // Calculate positions of the four corners of graph origin_x = x->current->settings.OriginX.real * M_TO_PS; origin_y = x->current->settings.OriginY.real * M_TO_PS; width = x->current->settings.width .real * M_TO_PS; if (x->current->settings.AutoAspect == SW_ONOFF_ON) height = width * 2.0/(1.0+sqrt(5)); else height = width * x->current->settings.aspect; if (x->current->settings.AutoZAspect == SW_ONOFF_ON) zdepth = width * 2.0/(1.0+sqrt(5)); else zdepth = width * x->current->settings.zaspect; // Turn on clipping if 'set clip' is set if (x->current->settings.clip == SW_ONOFF_ON) { if (x->current->ThreeDim) // 3D clip region is the edge of a cuboidal box { int i; double xap, yap, zap, data[3*8]; for (i=0;i<8;i++) { xap=((i&1)!=0); yap=((i&2)!=0); zap=((i&4)!=0); eps_plot_ThreeDimProject(xap,yap,zap,&x->current->settings,origin_x,origin_y,width,height,zdepth,data+3*i,data+3*i+1,data+3*i+2); } SortByAzimuthXCentre = origin_x; SortByAzimuthYCentre = origin_y; qsort((void *)(data ),8,3*sizeof(double),SortByDepth); if ((data[3*0+2]==data[3*1+2])&&(hypot(data[3*0+0]-origin_x,data[3*0+1]-origin_y)>hypot(data[3*1+0]-origin_x,data[3*1+1]-origin_y))) TriSwap(data+3*0,data+3*1); if ((data[3*7+2]==data[3*6+2])&&(hypot(data[3*7+0]-origin_x,data[3*7+1]-origin_y)>hypot(data[3*6+0]-origin_x,data[3*6+1]-origin_y))) TriSwap(data+3*7,data+3*6); qsort((void *)(data+3),6,3*sizeof(double),SortByAzimuth); fprintf(x->epsbuffer, "gsave\nnewpath\n"); for (i=1;i<7;i++) fprintf(x->epsbuffer, "%.2f %.2f %sto\n", data[3*i], data[3*i+1], (i==1)?"move":"line"); fprintf(x->epsbuffer, "closepath\nclip newpath\n"); } else // 2D clip region is a simple rectangular box { fprintf(x->epsbuffer, "gsave\nnewpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nclip newpath\n",origin_x,origin_y,origin_x+width,origin_y,origin_x+width,origin_y+height,origin_x,origin_y+height); } } // Render colormaps and then contourmaps for (j=0; j<2; j++) { int style = j ? SW_STYLE_CONTOURMAP : SW_STYLE_COLORMAP; for (pd = x->current->plotitems, i=0; pd != NULL; pd=pd->next, i++) // loop over all datasets if (pd->ww_final.linespoints == style) { x->LaTeXpageno = x->current->DatasetTextID[i]; a1 = &axissets[pd->axis1xyz][pd->axis1]; a2 = &axissets[pd->axis2xyz][pd->axis2]; a3 = &axissets[pd->axis3xyz][pd->axis3]; xyzaxis[pd->axis1xyz] = 0; xyzaxis[pd->axis2xyz] = 1; xyzaxis[pd->axis3xyz] = 2; status = (j?eps_plot_contourmap:eps_plot_colormap)(x, x->current->plotdata[i], x->current->ThreeDim, xyzaxis[0], xyzaxis[1], xyzaxis[2], &x->current->settings, pd, i, origin_x, origin_y, width, height, zdepth); if (status) { *(x->status) = 1; return; } } if (j==0) { // Render gridlines after colormaps and before contourmaps eps_plot_gridlines(x, origin_x, origin_y, width, height, zdepth); } } // Activate three-dimensional buffer if graph is 3D if (x->current->ThreeDim) ThreeDimBuffer_Activate(x); // Render axes (back) eps_plot_axespaint(x, origin_x, origin_y, width, height, zdepth, 0); // Render each dataset in turn (except colormaps, which we've already rendered) for (pd = x->current->plotitems, i=0; pd != NULL; pd=pd->next, i++) // loop over all datasets { x->LaTeXpageno = x->current->DatasetTextID[i]; a1 = &axissets[pd->axis1xyz][pd->axis1]; a2 = &axissets[pd->axis2xyz][pd->axis2]; a3 = &axissets[pd->axis3xyz][pd->axis3]; xyzaxis[pd->axis1xyz] = 0; xyzaxis[pd->axis2xyz] = 1; xyzaxis[pd->axis3xyz] = 2; status = eps_plot_dataset(x, x->current->plotdata[i], pd->ww_final.linespoints, x->current->ThreeDim, a1, a2, a3, xyzaxis[0], xyzaxis[1], xyzaxis[2], &x->current->settings, pd, origin_x, origin_y, width, height, zdepth); if (status) { *(x->status) = 1; return; } } // Render text labels and arrows eps_plot_labelsarrows(x, origin_x, origin_y, width, height, zdepth); // Deactivate three-dimensional buffer ThreeDimBuffer_Deactivate(x); // Turn off clipping if 'set clip' is set if (x->current->settings.clip == SW_ONOFF_ON) { fprintf(x->epsbuffer, "grestore\n"); x->LastLinewidth = -1; x->LastLinetype = -1; x->LastPSColor[0]='\0'; } // Render axes (front) eps_plot_axespaint(x, origin_x, origin_y, width, height, zdepth, 1); // Render colormap scales eps_plot_colormap_DrawScales(x, origin_x, origin_y, width, height, zdepth); // Render legend GraphLegend_Render(x, width, height, zdepth); // Put the title on the top of the graph x->LaTeXpageno = x->current->TitleTextID; if ((x->current->settings.title != NULL) && (x->current->settings.title[0] != '\0')) { int pageno = x->LaTeXpageno++; withWords ww; ppl_withWordsZero(c, &ww); if (x->current->settings.TextColor > 0) { ww.color = x->current->settings.TextColor; ww.USEcolor = 1; } else { ww.Col1234Space = x->current->settings.TextCol1234Space; ww.color1 = x->current->settings.TextColor1; ww.color2 = x->current->settings.TextColor2; ww.color3 = x->current->settings.TextColor3; ww.color4 = x->current->settings.TextColor4; ww.USEcolor1234 = 1; } eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE canvas_EPSRenderTextItem(x, NULL, pageno, (x->current->ThreeDim ? origin_x : (origin_x+width/2))/M_TO_PS, x->current->PlotTopMargin/M_TO_PS+4e-3, SW_HALIGN_CENT, SW_VALIGN_BOT, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_plot.h0000664000175000017500000000324012026340554016157 0ustar dcf21dcf21// eps_plot.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_H #define _PPL_EPS_PLOT_H 1 #include "coreUtils/list.h" #include "expressions/expCompile.h" #include "settings/settings.h" #include "epsMaker/eps_comm.h" #include "userspace/pplObj.h" int eps_plot_AddUsingItemsForWithWords(ppl_context *c, withWords *ww, int *NExpect, unsigned char *autoUsingList, pplExpr ***usingList, int *Nusing, int *NObjs, char *errtext); void eps_plot_WithWordsFromUsingItems(ppl_context *c, withWords *ww, double *DataRow, pplObj *ObjRow, int Ncolumns_real, int Ncolumns_obj); int eps_plot_WithWordsCheckUsingItemsDimLess(ppl_context *c, withWords *ww, pplObj *firstValues, int Ncolumns_real, int Ncolumns_obj, int *NDataCols); void eps_plot_ReadAccessibleData(EPSComm *x); void eps_plot_SampleFunctions(EPSComm *x); void eps_plot_DecideAxisRanges(EPSComm *x); void eps_plot_YieldUpText(EPSComm *x); void eps_plot_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_style.c0000664000175000017500000006707312026340554016352 0ustar dcf21dcf21// eps_style.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_style.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_STYLE_C 1 #include #include #include #include "epsMaker/eps_style.h" // Line types char *eps_LineType(int lt, double lw, double offset) { static char output[256]; lt = (lt-1) % 9; while (lt<0) lt+=9; if (lt==0) sprintf(output, "0 setlinecap [] %.2f setdash", offset); // solid else if (lt==1) sprintf(output, "0 setlinecap [%.2f] %.2f setdash", 2*lw, offset); // dashed else if (lt==2) sprintf(output, "1 setlinecap [0 %.2f] %.2f setdash", 2*lw, offset); // dotted else if (lt==3) sprintf(output, "1 setlinecap [0 %.2f %.2f %.2f] %.2f setdash", 2*lw, 2*lw, 2*lw, offset); // dash-dotted else if (lt==4) sprintf(output, "0 setlinecap [%.2f %.2f] %.2f setdash", 7*lw, 2*lw, offset); // long dash else if (lt==5) sprintf(output, "1 setlinecap [%.2f %.2f 0 %.2f] %.2f setdash", 7*lw, 2*lw, 2*lw, offset); // long dash - dot else if (lt==6) sprintf(output, "1 setlinecap [%.2f %.2f 0 %.2f 0 %.2f] %.2f setdash", 7*lw, 2*lw, 2*lw, 2*lw, offset); // long dash - dot dot else if (lt==7) sprintf(output, "1 setlinecap [%.2f %.2f 0 %.2f 0 %.2f 0 %.2f] %.2f setdash", 7*lw, 2*lw, 2*lw, 2*lw, 2*lw, offset); // long dash - dot dot dot else if (lt==8) sprintf(output, "0 setlinecap [%.2f %.2f %.2f %.2f] %.2f setdash", 7*lw, 2*lw, 2*lw, 2*lw, offset); // long dash - dash return output; } // Point types // NB the fact that point types 29-42 depend upon point types 1-14 and 15-28, and that this must be accounted for in canvasDraw.c char *eps_PointTypes[N_POINTTYPES] = { "/pt1 {newpath 2 copy ps75 sub exch ps75 sub exch moveto ps75 2 mul dup rlineto closepath stroke ps75 add exch ps75 sub exch moveto ps75 2 mul dup -1 mul rlineto closepath stroke } bind def", "/pt2 {newpath ps75 add exch ps75 add exch moveto ps75 -2 mul 0 rlineto 0 ps75 -2 mul rlineto ps75 2 mul 0 rlineto closepath stroke} bind def", "/pt3 {newpath 2 copy exch ps75 1.1 mul add exch moveto ps75 1.1 mul 0 360 arc stroke} bind def", "/pt4 {newpath exch ps 1.183 mul add exch ps75 sub moveto ps -1.183 mul ps 2.049 mul 2 copy rlineto -1 mul rlineto closepath stroke} bind def", "/pt5 {newpath exch ps75 add exch moveto ps75 -1 mul ps 1.3 mul 2 copy 2 copy rlineto -1 mul rlineto -1 mul exch -1 mul exch rlineto closepath stroke} bind def", "/pt6 {newpath exch ps add exch moveto ps -.5 mul ps 0.866 mul rlineto ps -1 mul 0 rlineto ps -.5 mul ps -.866 mul 2 copy rlineto exch -1 mul exch rlineto ps 0 rlineto closepath stroke} bind def", "/pt7 {newpath 2 copy ps add moveto /theta 162 def 4 { 2 copy exch theta cos ps mul add exch theta sin ps mul add lineto /theta theta 72 add def } repeat closepath stroke pop pop} bind def", "/pt8 {newpath exch ps 1.183 mul add exch ps75 add moveto ps -1.183 mul ps -2.049 mul 2 copy rlineto -1 mul rlineto closepath stroke} bind def", "/pt9 {newpath ps 1.183 mul add exch ps75 sub exch moveto ps 2.049 mul ps -1.183 mul 2 copy rlineto exch -1 mul exch rlineto closepath stroke} bind def", "/pt10 {newpath ps 1.183 mul add exch ps75 add exch moveto ps -2.049 mul ps -1.183 mul 2 copy rlineto exch -1 mul exch rlineto closepath stroke} bind def", "/pt11 {newpath 10 {2 copy} repeat ps add moveto /theta 126 def 5 { exch ps 4 div theta cos mul add exch ps 4 div theta sin mul add lineto /theta theta 36 add def exch ps theta cos mul add exch ps theta sin mul add lineto /theta theta 36 add def } repeat closepath stroke} bind def", "/pt12 {newpath moveto ps75 dup rlineto ps -1.5 mul 0 rlineto ps 1.5 mul dup dup neg rlineto neg 0 rlineto closepath stroke} bind def", "/pt13 {newpath moveto ps75 dup rlineto 0 ps -1.5 mul rlineto ps 1.5 mul neg dup dup neg rlineto 0 exch rlineto closepath stroke} bind def", "/pt14 {newpath 5 {2 copy} repeat /theta 90 def 3 { exch ps theta cos mul add exch ps theta sin mul add moveto lineto stroke /theta theta 120 add def} repeat } bind def", "/pt15 {newpath 2 copy exch ps sub exch moveto ps 2 mul 0 rlineto closepath stroke ps sub moveto 0 ps 2 mul rlineto closepath stroke } bind def", "/pt16 {newpath ps75 add exch ps75 add exch moveto ps75 -2 mul 0 rlineto 0 ps75 -2 mul rlineto ps75 2 mul 0 rlineto closepath fill} bind def", "/pt17 {newpath 2 copy exch ps75 1.1 mul add exch moveto ps75 1.1 mul 0 360 arc fill} bind def", "/pt18 {newpath exch ps 1.183 mul add exch ps75 sub moveto ps -1.183 mul ps 2.049 mul 2 copy rlineto -1 mul rlineto closepath fill} bind def", "/pt19 {newpath exch ps75 add exch moveto ps75 -1 mul ps 1.3 mul 2 copy 2 copy rlineto -1 mul rlineto -1 mul exch -1 mul exch rlineto closepath fill} bind def", "/pt20 {newpath exch ps add exch moveto ps -.5 mul ps 0.866 mul rlineto ps -1 mul 0 rlineto ps -.5 mul ps -.866 mul 2 copy rlineto exch -1 mul exch rlineto ps 0 rlineto closepath fill} bind def", "/pt21 {newpath 2 copy ps add moveto /theta 162 def 4 { 2 copy exch theta cos ps mul add exch theta sin ps mul add lineto /theta theta 72 add def } repeat closepath fill pop pop} bind def", "/pt22 {newpath exch ps 1.183 mul add exch ps75 add moveto ps -1.183 mul ps -2.049 mul 2 copy rlineto -1 mul rlineto closepath fill} bind def", "/pt23 {newpath ps 1.183 mul add exch ps75 sub exch moveto ps 2.049 mul ps -1.183 mul 2 copy rlineto exch -1 mul exch rlineto closepath fill} bind def", "/pt24 {newpath ps 1.183 mul add exch ps75 add exch moveto ps -2.049 mul ps -1.183 mul 2 copy rlineto exch -1 mul exch rlineto closepath fill} bind def", "/pt25 {newpath 10 {2 copy} repeat ps add moveto /theta 126 def 5 { exch ps 4 div theta cos mul add exch ps 4 div theta sin mul add lineto /theta theta 36 add def exch ps theta cos mul add exch ps theta sin mul add lineto /theta theta 36 add def } repeat closepath fill} bind def", "/pt26 {newpath moveto ps75 dup rlineto ps -1.5 mul 0 rlineto ps 1.5 mul dup dup neg rlineto neg 0 rlineto closepath fill} bind def", "/pt27 {newpath moveto ps75 dup rlineto 0 ps -1.5 mul rlineto ps 1.5 mul neg dup dup neg rlineto 0 exch rlineto closepath fill} bind def", "/pt28 {newpath 5 {2 copy} repeat /theta 270 def 3 { exch ps theta cos mul add exch ps theta sin mul add moveto lineto stroke /theta theta 120 add def} repeat } bind def", "/pt29 {newpath 2 copy pt1 pt15} bind def", "/pt30 {newpath 2 copy pt16 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt2 5 2 roll setrgbcolor} bind def", "/pt31 {newpath 2 copy pt17 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt3 5 2 roll setrgbcolor} bind def", "/pt32 {newpath 2 copy pt18 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt4 5 2 roll setrgbcolor} bind def", "/pt33 {newpath 2 copy pt19 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt5 5 2 roll setrgbcolor} bind def", "/pt34 {newpath 2 copy pt20 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt6 5 2 roll setrgbcolor} bind def", "/pt35 {newpath 2 copy pt21 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt7 5 2 roll setrgbcolor} bind def", "/pt36 {newpath 2 copy pt22 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt8 5 2 roll setrgbcolor} bind def", "/pt37 {newpath 2 copy pt23 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt9 5 2 roll setrgbcolor} bind def", "/pt38 {newpath 2 copy pt24 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt10 5 2 roll setrgbcolor} bind def", "/pt39 {newpath 2 copy pt25 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt11 5 2 roll setrgbcolor} bind def", "/pt40 {newpath 2 copy pt26 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt12 5 2 roll setrgbcolor} bind def", "/pt41 {newpath 2 copy pt27 currentrgbcolor 0 0 0 setrgbcolor 5 3 roll 2 copy pt13 5 2 roll setrgbcolor} bind def", "/pt42 {newpath 11 {2 copy} repeat /theta 90 def 6 { exch ps theta cos mul add exch ps theta sin mul add moveto lineto stroke /theta theta 60 add def} repeat } bind def", "/pt43 {newpath 2 copy moveto << /ShadingType 3 /ColorSpace /DeviceRGB /Coords [currentpoint exch ps 0.4 mul sub exch ps 0.3 mul add 0 currentpoint ps] /Function << /FunctionType 2 /Domain [0 1] /C1 [ currentrgbcolor ] /C0 [ 1 1 1 ] /N 1>> >> shfill } bind def", "/pt44 {newpath 2 copy moveto << /ShadingType 3 /ColorSpace /DeviceRGB /Coords [currentpoint exch ps 0.4 mul sub exch ps 0.3 mul add 0 currentpoint ps] /Function << /FunctionType 2 /Domain [0 1] /C1 [ currentrgbcolor ] /C0 [ 1 1 1 ] /N 1>> >> shfill currentrgbcolor 5 3 roll 0 0 0 setrgbcolor ps 0 rmoveto currentpoint exch ps sub exch ps 0 360 arc stroke 5 2 roll setrgbcolor} bind def" }; double eps_PointSize[N_POINTTYPES] = {0.75 , 1.0 , 1.0 , 0.75 , 1.183 , 0.75 , 1.3 , 0.75 , 1.183 , 0.75 , 1.3 , 1.0 , 1.0 , 1.183 , 1.183 , 1.183 , 1.2 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.0 , 1.183 , 1.183 , 1.183 , 1.2 , 1.0 , 1.0}; // ------------------------------------------------- // Star types // ------------------------------------------------- char *eps_StarTypes [N_STARTYPES] = { // STAR TYPE 1: ALPHA ORIONIS "/st1 {\n\ % Inner and outer radii of main and sharp points\n\ /lmout ps def\n\ /lmin ps3d def\n\ /lsout ps2 def\n\ /lsin ps6d def\n\ % Shading type\n\ /shade { alphaShade } bind def\n\ \n\ % First do the six main points\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ /lout ps def\n\ /lin ps3d def\n\ star closepath stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ /theta thetasave def\n\ } repeat\n\ \n\ % Shading of one half of the main point\n\ /theta angle 90 add def\n\ /lout ps def\n\ /lin ps3d def\n\ 6 {\n\ gsave\n\ 2 copy lout theta cpos moveto % Tip of first point\n\ 2 copy lineto\n\ 2 copy lin theta 30 add cpos lineto closepath clip\n\ 2 copy\n\ 8 {\n\ ps30d theta 60 add cpos 2 copy moveto\n\ 2 copy ps theta cpos lineto closepath stroke\n\ } repeat\n\ pop pop\n\ grestore\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 120 add def\n\ 3 {\n\ 2 { 2 copy } repeat ps3d theta cpos moveto\n\ ps3d -1 mul theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 2: BETA ORIONIS "/st2 {\n\ % Inner and outer radii of main and sharp points\n\ /lmout ps def\n\ /lmin ps3d def\n\ /lsout ps15 def\n\ /lsin ps6d def\n\ % Shading type\n\ /shade { betaShade } bind def\n\ \n\ % First do the six main points\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ /lout lmout def\n\ /lin lmin def\n\ star closepath stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ /theta thetasave def\n\ } repeat\n\ \n\ % Internal shading of one half of the main point\n\ /theta angle 90 add def\n\ /lout lmout def\n\ /lin lmin def\n\ 6 {\n\ gsave\n\ 2 copy lout theta cpos moveto % Tip of first point\n\ 2 copy lineto\n\ 2 copy lin theta 30 add cpos lineto closepath clip\n\ 2 copy\n\ 10 {\n\ ps40d theta 60 add cpos 2 copy moveto\n\ 2 copy ps theta cpos lineto closepath stroke\n\ } repeat\n\ pop pop\n\ grestore\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 90 add def\n\ 3 {\n\ 2 copy ps15 ps15 -2 mul theta radLine\n\ /theta theta 30 add def\n\ 2 copy ps3d ps3d -2 mul theta radLine\n\ /theta theta 30 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 3: EPSILON ORIONIS "/st3 {\n\ % Inner and outer radii of main and sharp points\n\ /lmout ps def\n\ /lmin ps3d def\n\ /lsout ps15 def\n\ /lsin ps6d def\n\ % Shading type\n\ /shade { epsilonShade } bind def\n\ \n\ % First do the six main points\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ /lout lmout def\n\ /lin lmin def\n\ star closepath stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ /theta thetasave def\n\ } repeat\n\ \n\ % Internal shading of one half of the main point\n\ /theta angle 90 add def\n\ /lout lmout def\n\ /lin lmin def\n\ 6 {\n\ gsave\n\ 2 copy lout theta cpos moveto % Tip of first point\n\ 2 copy lineto\n\ 2 copy lin theta 30 add cpos lineto closepath clip\n\ 2 copy\n\ 8 {\n\ ps30d theta 60 add cpos 2 copy moveto\n\ 2 copy ps theta cpos lineto closepath stroke\n\ } repeat\n\ pop pop\n\ grestore\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 90 add def\n\ 3 {\n\ 2 copy ps ps4d add dup -2 mul theta radLine\n\ /theta theta 30 add def\n\ 2 copy ps3d ps3d -2 mul theta radLine\n\ /theta theta 30 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 4: Q ORIONIS "/st4 { % q Orionis\n\ % First do the six main points\n\ tlw setlinewidth\n\ /lmin ps3d def\n\ /lmout ps def\n\ /lsin ps6d def\n\ /lsout ps15 def\n\ /shade { qShade } bind def\n\ \n\ /theta angle 90 add def\n\ /lout lmout def\n\ /lin lmin def\n\ star closepath stroke\n\ \n\ % Shading inside the main star\n\ tlw setlinewidth\n\ /theta angle 90 add def\n\ gsave\n\ star closepath clip\n\ 2 copy 2 copy ps15 theta 45 add cpos\n\ 4 2 roll ps15 theta 45 sub cpos\n\ theta angle 90 sub def\n\ 31 {\n\ ps15d theta sin mul sub exch ps15d theta cos mul sub exch 4 2 roll\n\ ps15d theta sin mul sub exch ps15d theta cos mul sub exch 4 2 roll\n\ 4 copy moveto lineto closepath stroke\n\ } repeat\n\ 4 { pop } repeat\n\ grestore\n\ \n\ % Do the thicker lines on one side of the main star\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ 3 {\n\ 2 copy ps3d theta 30 add cpos moveto\n\ 2 copy ps theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ 3 {\n\ 2 copy ps3d theta 30 sub cpos moveto\n\ 2 copy ps theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ %2 copy ps3d theta 30 add cpos moveto 2 copy ps theta cpos lineto stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 120 add def\n\ 3 {\n\ 2 copy lmin lmin -2 mul theta radLine\n\ /theta theta 60 add def\n\ } repeat\n\ /theta angle 90 add def\n\ 3 {\n\ 2 copy ps125 ps125 -2 mul theta radLine\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 5: M ORIONIS "/st5 {\n\ % First do the six main points\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ /lmin ps3d def\n\ /lmout ps def\n\ /lsin ps6d def\n\ /lsout ps15 def\n\ /shade { mShade } bind def\n\ \n\ /lin lmin def\n\ /lout lmout def\n\ star closepath stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 120 add def\n\ 3 {\n\ 2 { 2 copy } repeat ps3d theta cpos moveto\n\ ps3d -1 mul theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 6: TAU ORIONIS "/st6 {\n\ % First do the six main points\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ /lmin ps3d def\n\ /lmout ps def\n\ /lsin ps6d def\n\ /lsout ps15 def\n\ /shade { tauShade } bind def\n\ \n\ /lin lmin def\n\ /lout lmout def\n\ star closepath stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ dopoint\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 120 add def\n\ 3 {\n\ 2 { 2 copy } repeat ps3d theta cpos moveto\n\ ps3d -1 mul theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 7: PI ORIONIS "/st7 {\n\ % Do the lines additional to tau (st6)\n\ /theta angle 90 add def\n\ 6 {\n\ 2 copy ps theta cpos moveto\n\ 2 copy ps15 theta cpos lineto closepath stroke\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ st6\n\ } bind def\n\ ", // STAR TYPE 8: GAMMA ORIONIS "/st8 {\n\ % First do the six main points\n\ tlw setlinewidth\n\ /theta angle 90 add def\n\ /lout ps def\n\ /lin ps3d def\n\ star closepath stroke\n\ \n\ % Do the thicker lines on one side of the main star\n\ blw setlinewidth\n\ /theta angle 90 add def\n\ 3 {\n\ 2 copy ps3d theta 30 add cpos moveto\n\ 2 copy ps theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ 3 {\n\ 2 copy ps3d theta 30 sub cpos moveto\n\ 2 copy ps theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ %2 copy ps3d theta 30 add cpos moveto 2 copy ps theta cpos lineto stroke\n\ \n\ % Now do the six outer points\n\ /theta angle 90 add def\n\ % Theta gets a bit confusing later on, so\n\ /thetasave theta def\n\ tlw setlinewidth\n\ 6 {\n\ gsave\n\ % Clip out the inside of the main points\n\ newpath\n\ /lout ps def\n\ /lin ps3d def\n\ 2 copy lout theta cpos moveto\n\ point\n\ % Then take an arc round to include the tip of the outer point\n\ 2 copy ps15 theta cpos lineto\n\ 2 copy ps15 theta theta 60 sub arcn\n\ closepath clip\n\ \n\ % draw the outer point\n\ newpath\n\ /theta theta 60 sub def\n\ /lout ps6d def\n\ /lin ps125 def\n\ 2 copy lout theta cpos moveto\n\ point\n\ closepath stroke\n\ \n\ % Now put a mask round the smaller-angle part of the outer point\n\ /lout ps125 def\n\ /lin ps6d def\n\ gsave\n\ newpath\n\ /theta theta 90 sub def\n\ 2 copy lout theta cpos moveto point\n\ 2 copy ps15 theta theta 60 sub arcn closepath clip\n\ % Shade in the space between main and outer points (phew)\n\ newpath\n\ gammaShade\n\ grestore\n\ \n\ % Then repeat for the other side of the outer point\n\ % Put a mask round the larger-angle part of the outer point\n\ gsave\n\ newpath\n\ 2 copy lout theta cpos moveto point\n\ 2 copy ps15 theta theta 60 sub arcn closepath clip\n\ % Shade in the space between main and outer points\n\ newpath\n\ /theta theta 30 sub def\n\ gammaShade\n\ grestore\n\ \n\ grestore\n\ % Reset and increment angle for next point\n\ /thetasave thetasave 60 add def\n\ /theta thetasave def\n\ } repeat\n\ \n\ % Do the lines within the main star\n\ tlw setlinewidth\n\ /theta angle 120 add def\n\ 3 {\n\ 2 { 2 copy } repeat ps3d theta cpos moveto\n\ ps3d -1 mul theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ /theta angle 90 add def\n\ 3 {\n\ 2 { 2 copy } repeat ps125 theta cpos moveto\n\ ps125 -1 mul theta cpos lineto stroke\n\ /theta theta 60 add def\n\ } repeat\n\ \n\ pop pop % Tidy up stack\n\ } bind def\n\ ", // STAR TYPE 9: GENERIC STAR "/st9 {newpath 10 {2 copy} repeat ps 10 div add moveto /theta 126 def 5 { exch ps 40 div theta cos mul add exch ps 40 div theta sin mul add lineto /theta theta 36 add def exch ps 10 div theta cos mul add exch ps 10 div theta sin mul add lineto /theta theta 36 add def } repeat closepath fill} bind def" }; double eps_StarSize [N_STARTYPES] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; char *eps_StarCore = "\n\ /ps2 { ps 2 mul } bind def\n\ /ps95 { ps .95 mul } bind def\n\ /ps15 { ps 1.5 mul } bind def\n\ /ps125 { ps 1.25 mul } bind def\n\ \n\ /ps10d { ps 10 div } bind def\n\ /ps15d { ps 15 div } bind def\n\ /ps20d { ps 20 div } bind def\n\ /ps30d { ps 30 div } bind def\n\ /ps40d { ps 40 div } bind def\n\ /ps8d { ps 8 div } bind def\n\ /ps6d { ps 6 div } bind def\n\ /ps4d { ps 4 div } bind def\n\ /ps3d { ps 3 div } bind def\n\ /ps2d { ps 2 div } bind def\n\ /lw 1.5 def % Standard line width\n\ /blw { ps 50 div lw mul } bind def\n\ /tlw { blw 3 div } bind def % Thin line width\n\ \n\ % Subroutine library\n\ % x y l theta cpos: leave x+lcos theta, y+l sin theta on the stack\n\ /cpos { 2 copy cos mul 3 1 roll sin mul exch 4 3 roll add 3 1 roll add } bind def\n\ % x y inner length theta radLine: draws a radial line, length length from centre x,y at angle theta to vertical from inner radius \n\ /radLine {\n\ dup 3 1 roll 6 2 roll cpos 2 copy moveto\n\ 4 2 roll cpos lineto closepath stroke\n\ } bind def\n\ \n\ % From outer point, go in to inner vertex and out to next outer point\n\ % call with centre on stack; leave stack unchanged\n\ /point {\n\ /theta theta 30 add def\n\ 2 copy lin theta cpos lineto % Inner vertex\n\ /theta theta 30 add def\n\ 2 copy lout theta cpos lineto % Outer point \n\ } bind def\n\ \n\ % Before calling star set lin=radius of inner vertices, \n\ % lout=radius of outer vertices\n\ % theta=angle of outer points to the vertical\n\ % Leaves you with a path that looks like a star\n\ /star { 2 copy\n\ lout theta cpos moveto % Tip of first point\n\ 6 { point } repeat\n\ } bind def\n\ \n\ % Apply some shading\n\ \n\ /qShade {\n\ /theta theta 30 sub def\n\ 10 {\n\ % Inner shading (at radius ps3, length ps4d)\n\ 2 copy ps3d ps4d theta radLine\n\ % Middle shading\n\ 2 copy ps75 ps10d theta radLine\n\ % Outer shading \n\ 2 copy ps ps10d theta radLine\n\ /theta theta 3 add def\n\ } repeat\n\ } bind def\n\ /gammaShade {\n\ /theta theta 30 sub def\n\ 10 {\n\ % Inner shading (at radius ps3, length ps4d)\n\ 2 copy ps3d ps4d theta radLine\n\ % Outer shading (at radius ps, length ps3d)\n\ 2 copy ps125 ps10d theta radLine\n\ /theta theta 3 add def\n\ } repeat\n\ % Middle shading with longer lines\n\ /theta theta 30 sub def\n\ 3 {\n\ 2 copy ps95 ps8d theta radLine\n\ /theta theta 30 7 div add def\n\ } repeat\n\ 2 copy ps95 ps10d sub ps10d 3 mul theta radLine\n\ /theta theta 30 7 div add def\n\ 3 {\n\ 2 copy ps95 ps8d theta radLine\n\ /theta theta 30 7 div add def\n\ } repeat\n\ } bind def\n\ \n\ /alphaShade {\n\ qShade\n\ /theta theta 30 sub def\n\ 15 {\n\ 2 copy ps125 ps10d theta radLine\n\ /theta theta 2 add def\n\ } repeat\n\ } bind def\n\ \n\ /betaShade {\n\ qShade\n\ /theta theta 30 sub def\n\ 7 {\n\ 2 copy ps125 ps10d theta radLine\n\ /theta theta 2 add def\n\ } repeat\n\ 2 copy ps125 ps10d sub ps10d 3 mul theta radLine\n\ /theta theta 2 add def\n\ 7 {\n\ 2 copy ps125 ps10d theta radLine\n\ /theta theta 2 add def\n\ } repeat\n\ } bind def\n\ \n\ /epsilonShade {\n\ /theta theta 30 sub def\n\ 4 {\n\ 2 copy ps ps8d theta radLine\n\ /theta theta 10 3 div add def\n\ } repeat\n\ 2 copy ps ps8d sub ps8d 3 mul theta radLine\n\ /theta theta 10 3 div add def\n\ 4 {\n\ 2 copy ps ps8d theta radLine\n\ /theta theta 10 3 div add def\n\ } repeat\n\ } bind def\n\ \n\ /mShade {\n\ /theta theta 30 sub def\n\ 6 {\n\ % Inner shading (at radius ps3, length ps4d)\n\ 2 copy ps3d ps2d theta radLine\n\ /theta theta 5 add def\n\ } repeat\n\ } bind def\n\ \n\ /tauShade {\n\ /theta theta 30 sub def\n\ 5 {\n\ % Inner shading (at radius ps3, length ps4d)\n\ 2 copy ps3d ps4d theta radLine\n\ % Outer shading (at radius ps, length ps3d)\n\ 2 copy ps ps4d theta radLine\n\ /theta theta 6 add def\n\ } repeat\n\ } bind def\n\ \n\ % Two sorts of points, 'main' (inner, wide point) and 'sharp' (outer, thin point)\n\ % Both have inner and outer radii (so lmin, lmout, lsin, lsout)\n\ % This routine draws the outer point and puts the shading in place\n\ /dopoint {\n\ /theta thetasave def\n\ gsave newpath\n\ % Clip out the inside of the main points\n\ /lout lmout def\n\ /lin lmin def\n\ 2 copy lout theta cpos moveto\n\ point\n\ % Then take an arc round to include the tip of the outer point\n\ 2 copy lsout theta cpos lineto\n\ 2 copy lsout theta theta 60 sub arcn\n\ closepath clip\n\ \n\ % draw the outer point\n\ newpath\n\ /theta theta 60 sub def\n\ /lout lsin def\n\ /lin lsout def\n\ 2 copy lout theta cpos moveto\n\ point\n\ closepath stroke\n\ \n\ % Now put a mask round the smaller-angle part of the outer point\n\ /lout lsout def\n\ /lin lsin def\n\ gsave\n\ newpath\n\ /theta theta 90 sub def\n\ 2 copy lout theta cpos moveto point\n\ 2 copy lsout theta theta 60 sub arcn closepath clip\n\ % Shade in the space between main and outer points (phew)\n\ newpath\n\ shade\n\ grestore\n\ \n\ % Then repeat for the other side of the outer point\n\ % Put a mask round the larger-angle part of the outer point\n\ gsave\n\ newpath\n\ 2 copy lout theta cpos moveto point\n\ 2 copy lsout theta theta 60 sub arcn closepath clip\n\ % Shade in the space between main and outer points\n\ newpath\n\ /theta theta 30 sub def\n\ shade\n\ grestore\n\ \n\ grestore\n\ } bind def\n\ "; pyxplot-0.9.2/src/epsMaker/bmp_jpegread.h0000664000175000017500000000255112026340554016755 0ustar dcf21dcf21// bmp_jpegread.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_jpegread.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from JPEG files without performing any // decompression, since the DCT-compressed data can be rewritten straight out // to postscript for decompression by the postscript rasterising engine. #ifndef _PPL_BMP_JPEGREAD_H #define _PPL_BMP_JPEGREAD_H 1 #include #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" void ppl_bmp_jpegread(pplerr_context *ec, FILE *jpeg, bitmap_data *image); #endif pyxplot-0.9.2/src/epsMaker/eps_piechart.h0000664000175000017500000000177012026340554017006 0ustar dcf21dcf21// eps_piechart.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_piechart.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PIECHART_H #define _PPL_EPS_PIECHART_H 1 #include "eps_comm.h" void eps_pie_ReadAccessibleData(EPSComm *x); void eps_pie_YieldUpText(EPSComm *x); void eps_pie_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_linkedaxes.c0000664000175000017500000006525612026340554020400 0ustar dcf21dcf21// eps_plot_linkedaxes.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_linkedaxes.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_LINKEDAXES 1 #include #include #include #include #include #include #include #include "commands/eqnsolve.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_linkedaxes.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_settings.h" // Whenever we update the usage variables MinUsed and MaxUsed for an axis, this // procedure is called. It checks whether the axis is linked, and if so, // updates the usage variables for the axis which it is linked to. This process // may then iteration down a hierarchy of linked axes. As a rule, it is the // axis at the bottom of the linkage hierarchy (i.e. at the end of the linked // list) that has the canonical usage variables. Axes further up may not have // complete information about the usage of the set of linked axes, since usage // does not propagate UP the hierarchy. void eps_plot_LinkedAxisBackPropagate(EPSComm *x, pplset_axis *source) { int IterDepth; pplset_axis *target; canvas_item *item; if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Back-propagating axis usage for axis %c%d on plot %d", "xyzc"[source->xyz], source->axis_n, source->canvas_id); ppl_log(&x->c->errcontext, NULL); } item = x->current; // Propagating MinUsed and MaxUsed variables along links between axes IterDepth = 0; while (1) // loop over as many iterations of linkage as may be necessary { if (IterDepth++ > 100) return; if (!(source->linked && (source->MinUsedSet || source->MaxUsedSet || source->DataUnitSet))) { break; } // proceed only if axis is linked and has usage information if (source->LinkedAxisCanvasID <= 0) { } // Linked to an axis on the same graph; do not change item else // Linked to an axis on a different canvas item { item = x->itemlist->first; while ((item != NULL) && ((item->id)LinkedAxisCanvasID)) item=item->next; if ((item == NULL) || (item->id != source->LinkedAxisCanvasID) || (item->type != CANVAS_PLOT) || (item->XAxes==NULL) || (item->YAxes==NULL) || (item->ZAxes==NULL)) { break; } } if (source->LinkedAxisToXYZ == 0) target = item->XAxes + source->LinkedAxisToNum; else if (source->LinkedAxisToXYZ == 1) target = item->YAxes + source->LinkedAxisToNum; else target = item->ZAxes + source->LinkedAxisToNum; if (source->linkusing != NULL) { eps_plot_LinkUsingBackPropagate(x, source->MinUsed, target, source); eps_plot_LinkUsingBackPropagate(x, source->MaxUsed, target, source); } else { if ((target->DataUnitSet && source->DataUnitSet) && (!ppl_unitsDimEqual(&target->DataUnit , &source->DataUnit))) { sprintf(x->c->errcontext.tempErrStr,"Axis %c%d of plot %d is linked to axis %c%d of plot %d, but axes have data plotted against them with conflicting physical units. The former has units of <%s> whilst the latter has units of <%s>.","xyzc"[source->xyz],source->axis_n,source->canvas_id,"xyzc"[target->xyz],target->axis_n,target->canvas_id,ppl_printUnit(x->c,&target->DataUnit,NULL,NULL,0,1,0),ppl_printUnit(x->c,&source->DataUnit,NULL,NULL,1,1,0)); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); break; } else { if ((source->MinUsedSet) && ((!target->MinUsedSet) || (target->MinUsed > source->MinUsed))) { target->MinUsed=source->MinUsed; target->MinUsedSet=1; } if ((source->MaxUsedSet) && ((!target->MaxUsedSet) || (target->MaxUsed < source->MaxUsed))) { target->MaxUsed=source->MaxUsed; target->MaxUsedSet=1; } if (source->DataUnitSet) { target->DataUnit = source->DataUnit; target->DataUnitSet = 1; } } } source = target; } return; } // Loop through all of the axes on a single plot item, and decide its range. If // the axis is a linked axis, must first decide the range of the axis at the // bottom of the linkage hierarchy. The function // eps_plot_LinkedAxisForwardPropagate deals with this. void eps_plot_DecideAxisRanges(EPSComm *x) { int i, j; pplset_axis *axes=NULL; // Decide the range of each axis in turn for (j=0; j<3; j++) { if (j==0) axes = x->current->XAxes; else if (j==1) axes = x->current->YAxes; else if (j==2) axes = x->current->ZAxes; else ppl_fatal(&x->c->errcontext,__FILE__,__LINE__,"Internal fail."); for (i=0; istatus) return; } if (!axes[i].TickListFinalised) { eps_plot_ticking(x, &axes[i], x->current->settings.AxisUnitStyle, NULL); if (*x->status) return; } } } return; } // As part of the process of determining the range of axis xyz[axis_n], check // whether the axis is linking, and if so fetch usage information from the // bottom of the linkage hierarchy. Propagate this information up through all // intermediate levels of the hierarchy before calling // eps_plot_DecideAxisRange(). void eps_plot_LinkedAxisForwardPropagate(EPSComm *x, pplset_axis *axis, int mode) { int IterDepth, OriginalMode=mode; pplset_axis *source, *target, *target2; canvas_item *item; // Propagate MinUsed and MaxUsed variables along links IterDepth = 0; target = axis; item = x->current; while (1) // loop over as many iterations of linkage as may be necessary to find MinFinal and MaxFinal at the bottom { if (IterDepth++ > 100) break; if ((!target->linked) || target->RangeFinalised) { break; } // proceed only if axis is linked if (target->LinkedAxisCanvasID <= 0) { } // Linked to an axis on the same graph; do not change item else // Linked to an axis on a different canvas item { item = x->itemlist->first; while ((item != NULL) && (item->id)LinkedAxisCanvasID) item=item->next; if ((item == NULL) || (item->id != target->LinkedAxisCanvasID)) { if ((IterDepth==1)&&(mode==0)) { sprintf(x->c->errcontext.tempErrStr,"Axis %c%d of plot %d is linked to axis %c%d of plot %d, but no such plot exists.","xyzc"[target->xyz],target->axis_n,target->canvas_id,"xyzc"[target->LinkedAxisToXYZ],target->LinkedAxisToNum,target->LinkedAxisCanvasID); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } break; } if (item->type != CANVAS_PLOT) { if ((IterDepth==1)&&(mode==0)) { sprintf(x->c->errcontext.tempErrStr,"Axis %c%d of plot %d is linked to axis %c%d of plot %d, but this canvas item is not a plot.","xyzc"[target->xyz],target->axis_n,target->canvas_id,"xyzc"[target->LinkedAxisToXYZ],target->LinkedAxisToNum,target->LinkedAxisCanvasID); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } break; } if ((item->XAxes==NULL)||(item->YAxes==NULL)||(item->ZAxes==NULL)) { if ((IterDepth==1)&&(mode==0)) { sprintf(x->c->errcontext.tempErrStr,"Axis %c%d of plot %d is linked to axis %c%d of plot %d, but this item has NULL axes.","xyzc"[target->xyz],target->axis_n,target->canvas_id,"xyzc"[target->LinkedAxisToXYZ],target->LinkedAxisToNum,target->LinkedAxisCanvasID); ppl_warning(&x->c->errcontext, ERR_INTERNAL, NULL); } break; } } if (target->LinkedAxisToXYZ == 0) target2 = item->XAxes + target->LinkedAxisToNum; else if (target->LinkedAxisToXYZ == 1) target2 = item->YAxes + target->LinkedAxisToNum; else target2 = item->ZAxes + target->LinkedAxisToNum; if (target->DataUnitSet && target2->DataUnitSet && (!ppl_unitsDimEqual(&target->DataUnit , &target2->DataUnit))) break; // If axes are dimensionally incompatible, stop target = target2; } if ((mode==1) && (!target->RangeFinalised)) { eps_plot_ticking(x, target, x->current->settings.AxisUnitStyle, NULL); if (*x->status) return; } IterDepth -= 2; source = target; for ( ; IterDepth>=0 ; IterDepth--) // loop over as many iterations of linkage as may be necessary { int k; target = axis; for (k=0; kLinkedAxisCanvasID <= 0) { item = x->current; } // Linked to an axis on the same graph else // Linked to an axis on a different canvas item { item = x->itemlist->first; while ((item != NULL) && (item->id)LinkedAxisCanvasID) item=item->next; if ((item == NULL) || (item->id != target->LinkedAxisCanvasID) || (item->type != CANVAS_PLOT) || (item->XAxes==NULL) || (item->YAxes==NULL) || (item->ZAxes==NULL)) { break; } } if (target->LinkedAxisToXYZ == 0) target2 = item->XAxes + target->LinkedAxisToNum; else if (target->LinkedAxisToXYZ == 1) target2 = item->YAxes + target->LinkedAxisToNum; else target2 = item->ZAxes + target->LinkedAxisToNum; target = target2; } if (target->RangeFinalised) { break; } if (!target->linked) { break; } // proceed only if axis is linked if ((OriginalMode==0)&&(target->Mode0BackPropagated)) continue; target->Mode0BackPropagated = 1; if (mode==0) // MODE 0: Propagate HardMin, HardMax, HardUnit { if (target->linkusing != NULL) { if (source->HardMinSet && source->HardMaxSet) { source->MinFinal = source->HardMin; source->MaxFinal = source->HardMax; source->DataUnit = source->HardUnit; source->DataUnitSet = 1; mode=1; } else { target->HardMinSet = target->HardMaxSet = target->HardUnitSet = 0; } } else { target->HardMinSet = source->HardMinSet; target->HardMin = source->HardMin; target->HardMaxSet = source->HardMaxSet; target->HardMax = source->HardMax; target->HardUnitSet = source->HardUnitSet; target->HardUnit = source->HardUnit; target->HardAutoMinSet = source->HardAutoMinSet; target->HardAutoMaxSet = source->HardAutoMaxSet; } } if (mode==1) // MODE 1: Propagate finalised ranges { target->LogFinal = source->LogFinal; target->MinFinal = source->MinFinal; target->MaxFinal = source->MaxFinal; if (target->linkusing != NULL) { if (eps_plot_LinkedAxisLinkUsing(x, target, source)) break; } else { if (target->DataUnitSet && source->DataUnitSet && (!ppl_unitsDimEqual(&target->DataUnit , &source->DataUnit))) break; // If axes are dimensionally incompatible, stop target->DataUnit = source->DataUnit; target->DataUnitSet = source->DataUnitSet; target->AxisValueTurnings = source->AxisValueTurnings; target->AxisLinearInterpolation = source->AxisLinearInterpolation; target->AxisTurnings = source->AxisTurnings; } target->RangeFinalised = 1; eps_plot_ticking(x, target, x->current->settings.AxisUnitStyle, source); } source = target; } return; } int eps_plot_LinkedAxisLinkUsing(EPSComm *X, pplset_axis *out, pplset_axis *in) { const int stkLevelOld = X->c->stackPtr; int l,xrn=0,lOP; int oldsgn=-10,newsgn; double p,x; char *VarName; pplObj DummyTemp, *outVal, *VarVal; if (in->xyz==0) VarName = "x"; else if (in->xyz==1) VarName = "y"; else if (in->xyz==2) VarName = "z"; else VarName = "c"; // Look up variable in user space and get pointer to its value ppl_contextGetVarPointer(X->c, VarName, &VarVal, &DummyTemp); out->AxisLinearInterpolation = (double *)ppl_memAlloc(AXISLINEARINTERPOLATION_NPOINTS * sizeof(double)); out->AxisValueTurnings = 0; out->AxisTurnings = (int *)ppl_memAlloc((AXISLINEARINTERPOLATION_NPOINTS+2) * sizeof(int)); if ((out->AxisLinearInterpolation==NULL)||(out->AxisTurnings==NULL)) goto FAIL; out->AxisTurnings[xrn++] = 0; for (l=0; llinkusing; // Set value of x (or y/z) *VarVal = in->DataUnit; VarVal->imag = 0.0; VarVal->flagComplex = 0; VarVal->real = x; // Generate a sample from the axis linkage function outVal = ppl_expEval(X->c, olu, &lOP, 0, X->iterDepth+1); if (X->c->errStat.status) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s",olu->ascii); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, NULL); ppl_tbWrite(X->c); ppl_tbClear(X->c); goto FAIL; } if ((outVal->objType != PPLOBJ_NUM)&&(outVal->objType != PPLOBJ_DATE)&&(outVal->objType != PPLOBJ_BOOL)) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s\nObject was not a number but an object of type <%s>",olu->ascii,pplObjTypeNames[outVal->objType]); ppl_error(&X->c->errcontext, ERR_TYPE, -1, -1, NULL); goto FAIL; } if (outVal->flagComplex) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s",olu->ascii); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, NULL); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, "Received a complex number; axes must have strictly real values at all points."); goto FAIL; } if (!gsl_finite(outVal->real)) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s",olu->ascii); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, NULL); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, "Expression returned non-finite result."); goto FAIL; } if (!out->DataUnitSet) { out->DataUnit = *outVal; out->DataUnitSet = 1; } if (!ppl_unitsDimEqual(&out->DataUnit,outVal)) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s",olu->ascii); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, NULL); sprintf(X->c->errcontext.tempErrStr, "Axis linkage function produces axis values with dimensions of <%s> whilst data plotted on this axis has dimensions of <%s>.", ppl_printUnit(X->c,outVal,NULL,NULL,0,1,0), ppl_printUnit(X->c,&out->DataUnit,NULL,NULL,1,1,0)); ppl_error(&X->c->errcontext, ERR_GENERIC, -1, -1, NULL); goto FAIL; } out->AxisLinearInterpolation[l] = outVal->real; if (l>0) // Check for turning points { newsgn = ppl_sgn(out->AxisLinearInterpolation[l] - out->AxisLinearInterpolation[l-1]); if (newsgn==0) continue; if ((newsgn!=oldsgn) && (oldsgn>-10)) out->AxisTurnings[xrn++] = l-1; oldsgn = newsgn; } { EPSComm *x=X; EPS_STACK_POP; } } // Restore original value of x (or y/z) ppl_contextRestoreVarPointer(X->c, VarName, &DummyTemp); out->AxisTurnings[xrn--] = AXISLINEARINTERPOLATION_NPOINTS-1; out->AxisValueTurnings = xrn; return 0; FAIL: { EPSComm *x=X; EPS_STACK_POP; } ppl_contextRestoreVarPointer(X->c, VarName, &DummyTemp); out->AxisLinearInterpolation = NULL; out->AxisValueTurnings = 0; out->AxisTurnings = NULL; return 1; } // Routines for the back propagation of usage information along non-linear links typedef struct LAUComm { EPSComm *x; pplExpr *expr; char *VarName; pplObj *VarValue; int GoneNaN, mode, iter2; double norm; pplObj target; double WorstScore; int fail; } LAUComm; #define WORSTSCORE_INIT -(DBL_MAX/1e10) double eps_plot_LAUSlave(const gsl_vector *x, void *params) { int i, lOP; double output; pplObj *outVal; LAUComm *data = (LAUComm *)params; const int stkLevelOld = data->x->c->stackPtr; if (data->fail) return GSL_NAN; // We've previously had a serious error... so don't do any more work if (data->mode==0) data->VarValue->real = ppl_optimise_LogToReal(gsl_vector_get(x, 0) , data->iter2 , &data->norm); else data->VarValue->exponent[data->mode-1] = ppl_optimise_LogToReal(gsl_vector_get(x, 0) , data->iter2 , &data->norm); data->VarValue->dimensionless=1; for (i=0; iVarValue->exponent[i], 0) == 0) { data->VarValue->dimensionless=0; break; } outVal = ppl_expEval(data->x->c, data->expr, &lOP, 0, data->x->iterDepth+1); // If a numerical error happened; ignore it for now, but return NAN if (data->x->c->errStat.status) { sprintf(data->x->c->errcontext.tempErrStr, "An algebraic error was encountered at %s=%s:", data->VarName, ppl_unitsNumericDisplay(data->x->c, data->VarValue,0,0,0)); ppl_error(&data->x->c->errcontext,ERR_PREFORMED, -1, -1, NULL); ppl_tbWrite(data->x->c); ppl_tbClear(data->x->c); output=GSL_NAN; goto end; } if ((outVal->objType != PPLOBJ_NUM)&&(outVal->objType != PPLOBJ_DATE)&&(outVal->objType != PPLOBJ_BOOL)) { sprintf(data->x->c->errcontext.tempErrStr, "Error encountered whilst evaluating axis linkage expression: %s\nObject was not a number but an object of type <%s>",data->expr->ascii,pplObjTypeNames[outVal->objType]); ppl_error(&data->x->c->errcontext, ERR_TYPE, -1, -1, NULL); output=GSL_NAN; goto end; } #define TWINLOG(X) ((X>1e-200) ? log(X) : (2*log(1e-200) - log(2e-200-X))) if (data->mode==0) output = pow( TWINLOG(data->target.real ) - TWINLOG(outVal->real ) ,2); else output = pow( TWINLOG(data->target.exponent[data->mode-1]) - TWINLOG(outVal->exponent[data->mode-1] ) ,2); if ((!gsl_finite(output)) && (data->WorstScore > WORSTSCORE_INIT)) { data->WorstScore *= 1.1; return data->WorstScore; } if (( gsl_finite(output)) && (data->WorstScore < output) ) { data->WorstScore = output; } end: { EPSComm *x=data->x; EPS_STACK_POP; } return output; } void eps_plot_LAUFitter(LAUComm *commlink) { size_t iter = 0,iter2 = 0; int i, status=0; double size=0,sizelast=0,sizelast2=0,testval; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; // We don't use nmsimplex2 here because it was new in gsl 1.12 gsl_multimin_fminimizer *s; gsl_vector *x, *ss; gsl_multimin_function fn; fn.n = 1; fn.f = &eps_plot_LAUSlave; fn.params = (void *)commlink; x = gsl_vector_alloc( 1 ); ss = gsl_vector_alloc( 1 ); iter2=0; do { iter2++; if (commlink->mode!=0) iter2=999; commlink->iter2 = iter2; sizelast2 = size; gsl_vector_set(x , 0, ppl_optimise_RealToLog( (commlink->mode==0) ? commlink->VarValue->real : 1.0 , iter2, &commlink->norm)); gsl_vector_set(ss, 0, (fabs(gsl_vector_get(x,0))>1e-6) ? 0.1 * (gsl_vector_get(x,0)) : 0.1); s = gsl_multimin_fminimizer_alloc (T, fn.n); gsl_multimin_fminimizer_set (s, &fn, x, ss); // If initial value we are giving the minimiser produces an algebraic error, it's not worth continuing commlink->GoneNaN = 0; commlink->WorstScore = WORSTSCORE_INIT; testval = eps_plot_LAUSlave(x,(void *)commlink); if (!gsl_finite(testval)) { commlink->fail=1; return; } iter = 0; commlink->GoneNaN = 0; commlink->WorstScore = WORSTSCORE_INIT; do { iter++; for (i=0; i<4; i++) { status = gsl_multimin_fminimizer_iterate(s); if (status) break; } // Run optimiser four times for good luck if (status) break; sizelast = size; size = gsl_multimin_fminimizer_minimum(s); // Do this ten times, or up to 50, until fit stops improving } while ((iter < 10) || ((size < sizelast) && (iter < 50))); // Iterate 10 times, and then see whether size carries on getting smaller // Read off best-fit value from s->x if (commlink->mode==0) commlink->VarValue->real = ppl_optimise_LogToReal(gsl_vector_get(s->x, 0), iter2, &commlink->norm); else commlink->VarValue->exponent[commlink->mode-1] = ppl_optimise_LogToReal(gsl_vector_get(s->x, 0), iter2, &commlink->norm); gsl_multimin_fminimizer_free(s); if (iter2==999) { iter2=2; break; } } while ((iter2 < 4) || ((commlink->GoneNaN==0) && (!status) && (size < sizelast2) && (iter2 < 20))); // Iterate 2 times, and then see whether size carries on getting smaller if (iter2>=20) status=1; if (status) { commlink->fail=1; } gsl_vector_free(x); gsl_vector_free(ss); return; } void eps_plot_LinkUsingBackPropagate(EPSComm *x, double val, pplset_axis *target, pplset_axis *source) { LAUComm commlink; char *VarName; pplObj DummyTemp, *VarVal; if (target->HardMinSet && target->HardMaxSet) return; if (target->xyz==0) VarName = "x"; else if (target->xyz==1) VarName = "y"; else if (target->xyz==2) VarName = "z"; else VarName = "c"; // Look up xyz dummy variable in user space and get pointer to its value ppl_contextGetVarPointer(x->c, VarName, &VarVal, &DummyTemp); // Set up commlink structure to use in minimiser commlink.x = x; commlink.expr = (pplExpr *)source->linkusing; commlink.VarName = VarName; commlink.VarValue = VarVal; commlink.GoneNaN = commlink.mode = 0; commlink.WorstScore = WORSTSCORE_INIT; commlink.target = source->DataUnit; commlink.target.real = val; commlink.fail = 0; // First run minimiser to get numerical value of xyz. Then fit each dimension in turn. pplObjNum(VarVal,0,1,0); for (commlink.mode=0; commlink.modec->set->term_current.UnitAngleDimless == SW_ONOFF_ON)) continue; eps_plot_LAUFitter(&commlink); if (commlink.fail) break; } // If there was a problem, throw a warning and proceed no further if (commlink.fail) { sprintf(x->c->errcontext.tempErrStr, "Could not propagate axis range information from axis %c%d of plot %d to axis %c%d of plot %d using expression <%s>. Recommend setting an explicit range for axis %c%d of plot %d.", "xyzc"[source->xyz], source->axis_n, source->canvas_id, "xyzc"[target->xyz], target->axis_n, target->canvas_id, commlink.expr->ascii, "xyzc"[target->xyz], target->axis_n, target->canvas_id); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } else { int i; VarVal->dimensionless=1; // Cycle through powers of final value of xyz dummy value making things which are nearly ints into ints. for (i=0; iexponent[i]) - VarVal->exponent[i]) < 1e-12) VarVal->exponent[i] = floor(VarVal->exponent[i]); else if (fabs(ceil (VarVal->exponent[i]) - VarVal->exponent[i]) < 1e-12) VarVal->exponent[i] = ceil (VarVal->exponent[i]); if (VarVal->exponent[i] != 0) VarVal->dimensionless=0; } // Check that dimension of propagated value fits with existing unit of axis if ((target->HardUnitSet) && (!ppl_unitsDimEqual(&target->HardUnit, VarVal))) { sprintf(x->c->errcontext.tempErrStr, "Could not propagate axis range information from axis %c%d of plot %d to axis %c%d of plot %d using expression <%s>. Propagated axis range has units of <%s>, but axis %c%d of plot %d has a range set with units of <%s>.", "xyzc"[source->xyz], source->axis_n, source->canvas_id, "xyzc"[target->xyz], target->axis_n, target->canvas_id, commlink.expr->ascii, ppl_printUnit(x->c,VarVal,NULL,NULL,0,1,0), "xyzc"[target->xyz], target->axis_n, target->canvas_id, ppl_printUnit(x->c,&target->HardUnit,NULL,NULL,1,1,0)); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } else if ((target->DataUnitSet) && (!ppl_unitsDimEqual(&target->DataUnit, VarVal))) { sprintf(x->c->errcontext.tempErrStr, "Could not propagate axis range information from axis %c%d of plot %d to axis %c%d of plot %d using expression <%s>. Propagated axis range has units of <%s>, but axis %c%d of plot %d has data plotted against it with units of <%s>.", "xyzc"[source->xyz], source->axis_n, source->canvas_id, "xyzc"[target->xyz], target->axis_n, target->canvas_id, commlink.expr->ascii, ppl_printUnit(x->c,VarVal,NULL,NULL,0,1,0), "xyzc"[target->xyz], target->axis_n, target->canvas_id, ppl_printUnit(x->c,&target->DataUnit,NULL,NULL,1,1,0)); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } else if (VarVal->flagComplex) { sprintf(x->c->errcontext.tempErrStr, "Could not propagate axis range information from axis %c%d of plot %d to axis %c%d of plot %d using expression <%s>. Axis usage was a complex number.", "xyzc"[source->xyz], source->axis_n, source->canvas_id, "xyzc"[target->xyz], target->axis_n, target->canvas_id, commlink.expr->ascii); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } else if (!gsl_finite(VarVal->real)) { sprintf(x->c->errcontext.tempErrStr, "Could not propagate axis range information from axis %c%d of plot %d to axis %c%d of plot %d using expression <%s>. Axis usage was a non-finite number.", "xyzc"[source->xyz], source->axis_n, source->canvas_id, "xyzc"[target->xyz], target->axis_n, target->canvas_id, commlink.expr->ascii); ppl_warning(&x->c->errcontext, ERR_GENERIC, NULL); } else { if ((!target->MinUsedSet) || (target->MinUsed > VarVal->real)) { target->MinUsed=VarVal->real; target->MinUsedSet=1; } if ((!target->MaxUsedSet) || (target->MaxUsed < VarVal->real)) { target->MaxUsed=VarVal->real; target->MaxUsedSet=1; } if (source->DataUnitSet) { target->DataUnit = *VarVal; target->DataUnitSet = 1; } } } // Restore original value of x (or y/z) ppl_contextRestoreVarPointer(x->c, VarName, &DummyTemp); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_ticking.c0000664000175000017500000005003412026340554017665 0ustar dcf21dcf21// eps_plot_ticking.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains routines for working out the ranges of axes, and where to // put axis ticks along them #define _PPL_EPS_PLOT_TICKING_C 1 #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "stringTools/asciidouble.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_plot_ticking_auto.h" #include "epsMaker/eps_plot_ticking_auto2.h" #include "epsMaker/eps_plot_ticking_auto3.h" void eps_plot_ticking(EPSComm *x, pplset_axis *axis, int AxisUnitStyle, pplset_axis *linkedto) { int i,j,MajMin,N,xrn; const double logmin = 1e-10; double UnitMultiplier=1.0; char *UnitString=NULL; pplObj CentralValue; unsigned char AutoTicks[2] = {0,0}; if (!axis->FinalActive) { axis->RangeFinalised = 0; return; } // Axis is not in use // First of all, work out what axis range to use if (!axis->RangeFinalised) { // Work out axis range unsigned char MinSet=1; if (axis->HardMinSet) axis->MinFinal = axis->HardMin; else if (axis->MinUsedSet) axis->MinFinal = axis->MinUsed; else MinSet = 0; if (axis->HardMaxSet) axis->MaxFinal = axis->HardMax; else if (axis->MaxUsedSet) axis->MaxFinal = axis->MaxUsed; else if (MinSet) axis->MaxFinal = (axis->LogFinal == SW_BOOL_TRUE) ? axis->MinFinal * 100 : axis->MinFinal + 20; else axis->MaxFinal = (axis->LogFinal == SW_BOOL_TRUE) ? 10.0 : 10.0; // Check that log axes do not venture too close to zero if ((axis->LogFinal == SW_BOOL_TRUE) && (axis->MaxFinal <= 1e-200)) { axis->MaxFinal = logmin; sprintf(x->c->errcontext.tempErrStr, "Range for logarithmic axis %c%d set below zero; defaulting to 1e-10.", "xyzc"[axis->xyz], axis->axis_n); ppl_warning(&x->c->errcontext, ERR_NUMERICAL, NULL); } if (!MinSet) axis->MinFinal = (axis->LogFinal == SW_BOOL_TRUE) ? (axis->MaxFinal / 100) : (axis->MaxFinal - 20); if ((axis->LogFinal == SW_BOOL_TRUE) && (axis->MinFinal <= 1e-200)) { axis->MinFinal = logmin; sprintf(x->c->errcontext.tempErrStr, "Range for logarithmic axis %c%d set below zero; defaulting to 1e-10.", "xyzc"[axis->xyz], axis->axis_n); ppl_warning(&x->c->errcontext, ERR_NUMERICAL, NULL); } // If there's no spread of data on the axis, make a spread up if ( (fabs(axis->MinFinal-axis->MaxFinal) <= fabs(1e-14*axis->MinFinal)) || (fabs(axis->MinFinal-axis->MaxFinal) <= fabs(1e-14*axis->MaxFinal)) ) { if (axis->HardMinSet && axis->HardMaxSet) { sprintf(x->c->errcontext.tempErrStr, "Specified minimum and maximum range limits for axis %c%d are equal; reverting to alternative limits.", "xyzc"[axis->xyz], axis->axis_n); ppl_warning(&x->c->errcontext, ERR_NUMERICAL, NULL); } if (axis->LogFinal != SW_BOOL_TRUE) { double step = ppl_max(1.0,1e-3*fabs(axis->MinFinal)); axis->MinFinal -= step; axis->MaxFinal += step; } else { if (axis->MinFinal > 1e-300) axis->MinFinal /= 10.0; if (axis->MaxFinal < 1e300) axis->MaxFinal *= 10.0; } } } // Finalise the physical unit to be associated with data on this axis if (!axis->DataUnitSet) { if (axis->HardUnitSet) { axis->DataUnitSet=1; axis->DataUnit=axis->HardUnit; } else { pplObjNum(&axis->DataUnit,0,0,0); } } CentralValue = axis->DataUnit; CentralValue.flagComplex = 0; CentralValue.imag = 0.0; CentralValue.real = (axis->format==NULL) ? eps_plot_axis_InvGetPosition(0.5, axis) : 1.0; if (CentralValue.real==0.0) CentralValue.real = eps_plot_axis_InvGetPosition(0.25, axis); UnitString = ppl_printUnit(x->c,&CentralValue,&UnitMultiplier,NULL,0,0,SW_DISPLAY_L); UnitMultiplier /= CentralValue.real; if (!gsl_finite(UnitMultiplier)) UnitMultiplier=1.0; if (!axis->RangeFinalised) { double min_prelim, max_prelim, OoM; // If axis does not have a user-specified range, round it outwards towards a round endpoint min_prelim = axis->MinFinal * UnitMultiplier; max_prelim = axis->MaxFinal * UnitMultiplier; if (axis->LogFinal == SW_BOOL_TRUE) { min_prelim = log10(min_prelim); max_prelim = log10(max_prelim); } OoM = pow(10.0, floor(log10(fabs(max_prelim - min_prelim)/5))); min_prelim = floor(min_prelim / OoM) * OoM; max_prelim = ceil (max_prelim / OoM) * OoM; if (axis->LogFinal == SW_BOOL_TRUE) { min_prelim = pow(10.0,min_prelim); max_prelim = pow(10.0,max_prelim); } min_prelim /= UnitMultiplier; max_prelim /= UnitMultiplier; if (gsl_finite(min_prelim) && (!axis->HardMinSet) && ((axis->LogFinal!=SW_BOOL_TRUE)||(min_prelim>1e-300))) axis->MinFinal = min_prelim; if (gsl_finite(max_prelim) && (!axis->HardMaxSet) && ((axis->LogFinal!=SW_BOOL_TRUE)||(min_prelim>1e-300))) axis->MaxFinal = max_prelim; // Print out debugging report if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"Determined range for axis %c%d of plot %d. Usage was [", "xyzc"[axis->xyz], axis->axis_n, axis->canvas_id); i = strlen(x->c->errcontext.tempErrStr); if (axis->MinUsedSet) { sprintf(x->c->errcontext.tempErrStr+i, "%f", axis->MinUsed); i+=strlen(x->c->errcontext.tempErrStr+i); } else x->c->errcontext.tempErrStr[i++] = '*'; x->c->errcontext.tempErrStr[i++] = ':'; if (axis->MaxUsedSet) { sprintf(x->c->errcontext.tempErrStr+i, "%f", axis->MaxUsed); i+=strlen(x->c->errcontext.tempErrStr+i); } else x->c->errcontext.tempErrStr[i++] = '*'; sprintf(x->c->errcontext.tempErrStr+i,"]. Final range was [%f:%f].",axis->MinFinal,axis->MaxFinal); ppl_log(&x->c->errcontext,NULL); } // Flip axis range if it is reversed if (axis->RangeReversed) { double swap; swap=axis->MinFinal; axis->MinFinal=axis->MaxFinal; axis->MaxFinal=swap; } // Set flag to show that we have finalised the range of this axis axis->RangeFinalised = 1; } // Secondly, decide what ticks to place on this axis if (!axis->TickListFinalised) { int OutContext; // If ticks have been manually specified, check that units are right if ((!ppl_unitsDimEqual(&axis->unit,&axis->DataUnit)) && ((axis->tics.tickList!=NULL)||(((axis->log==SW_BOOL_TRUE)?(axis->tics.tickMinSet):(axis->tics.tickStepSet))!=0)||(axis->ticsM.tickList!=NULL)||(((axis->log==SW_BOOL_TRUE)?(axis->ticsM.tickMinSet):(axis->ticsM.tickStepSet))!=0))) { sprintf(x->c->errcontext.tempErrStr, "Cannot put any ticks on axis %c%d because their positions are specified in units of <%s> whilst the axis has units of <%s>.", "xyzc"[axis->xyz], axis->axis_n, ppl_printUnit(x->c,&axis->unit,NULL,NULL,0,1,0), ppl_printUnit(x->c,&axis->DataUnit,NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext,ERR_GENERIC,-1,-1,NULL); axis->TickListPositions = NULL; axis->TickListStrings = NULL; axis->TickListPositions = NULL; axis->TickListStrings = NULL; return; } OutContext = ppl_memAlloc_GetMemContext(); // Finalise the label to be placed on the axis, quoting a physical unit as necessary if ((axis->DataUnit.dimensionless) || (axis->format != NULL)) { axis->FinalAxisLabel = axis->label; } // No units to append else { i = 1024; if (axis->label != NULL) i+=strlen(axis->label); axis->FinalAxisLabel = (char *)ppl_memAlloc(i); if (axis->FinalAxisLabel==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (u)."); return; } if (AxisUnitStyle == SW_AXISUNITSTY_BRACKET) sprintf(axis->FinalAxisLabel, "%s ($%s$)", (axis->label != NULL)?axis->label:"", UnitString); else if (AxisUnitStyle == SW_AXISUNITSTY_RATIO) sprintf(axis->FinalAxisLabel, "%s / $%s$", (axis->label != NULL)?axis->label:"", UnitString); else sprintf(axis->FinalAxisLabel, "%s [$%s$]", (axis->label != NULL)?axis->label:"", UnitString); } // Minor ticks. Then major ticks. for (MajMin=0; MajMin<2; MajMin++) { double TickMax, TickMin, TickStep; unsigned char TickMaxSet, TickMinSet, TickStepSet; double *TickList; char **TickStrs; double **TickListPositions; char ***TickListStrings; if (MajMin==0) { TickMax = axis->ticsM.tickMax; TickMin = axis->ticsM.tickMin; TickStep = axis->ticsM.tickStep; TickMaxSet = axis->ticsM.tickMaxSet; TickMinSet = axis->ticsM.tickMinSet; TickStepSet = axis->ticsM.tickStepSet; TickList = axis->ticsM.tickList; TickStrs = axis->ticsM.tickStrs; TickListPositions = &axis->MTickListPositions; TickListStrings = &axis->MTickListStrings; } else { TickMax = axis->tics .tickMax; TickMin = axis->tics .tickMin; TickStep = axis->tics .tickStep; TickMaxSet = axis->tics .tickMaxSet; TickMinSet = axis->tics .tickMinSet; TickStepSet = axis->tics .tickStepSet; TickList = axis->tics .tickList; TickStrs = axis->tics .tickStrs; TickListPositions = &axis->TickListPositions; TickListStrings = &axis->TickListStrings; } if (TickList != NULL) // Ticks have been specified as an explicit list { for (N=0; TickStrs[N]!=NULL; N++); // Find length of list of ticks *TickListPositions = (double *)ppl_memAlloc((N+1) * (axis->AxisValueTurnings+1) * sizeof(double)); *TickListStrings = (char **)ppl_memAlloc((N+1) * (axis->AxisValueTurnings+1) * sizeof(char *)); if ((*TickListPositions==NULL) || (*TickListStrings==NULL)) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (v)."); *TickListPositions = NULL; *TickListStrings = NULL; return; } for (i=j=0; iAxisValueTurnings; xrn++) { (*TickListPositions)[j] = eps_plot_axis_GetPosition(TickList[i], axis, xrn, 0); if ( (!gsl_finite((*TickListPositions)[j])) || ((*TickListPositions)[j]<0.0) || ((*TickListPositions)[j]>1.0) ) continue; // Filter out ticks which are off the end of the axis if (TickStrs[i][0]!='\xFF') (*TickListStrings)[j] = TickStrs[i]; else if (MajMin==0) (*TickListStrings)[j] = ""; else if (axis->format == NULL) TickLabelAutoGen(x, &(*TickListStrings)[j], TickList[i] * UnitMultiplier, axis->tics.logBase , OutContext); else TickLabelFromFormat(x, &(*TickListStrings)[j], axis->format, TickList[i], &axis->DataUnit, axis->xyz, OutContext); j++; } (*TickListStrings)[j] = NULL; // null terminate list } else if (TickStepSet) { double TMin, TStep, TMax, tmp; unsigned char inverted=0; *TickListPositions = (double *)ppl_memAlloc(102 * (axis->AxisValueTurnings+1) * sizeof(double)); *TickListStrings = (char **)ppl_memAlloc(102 * (axis->AxisValueTurnings+1) * sizeof(char *)); if ((*TickListPositions==NULL) || (*TickListStrings==NULL)) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (w)."); *TickListPositions = NULL; *TickListStrings = NULL; return; } TStep= TickStep; if (TStep<0) { TStep=-TStep; inverted=1; } if (axis->LogFinal == SW_BOOL_TRUE) { if (TStep<1) { TStep=1/TStep; inverted=1; } else inverted=0; } for (xrn=j=0; xrn<=axis->AxisValueTurnings; xrn++) { if (axis->AxisLinearInterpolation!=NULL) { double RegionMin, RegionMax, first; first = axis->AxisLinearInterpolation[axis->AxisTurnings[0 ]]; RegionMin = axis->AxisLinearInterpolation[axis->AxisTurnings[xrn ]]; RegionMax = axis->AxisLinearInterpolation[axis->AxisTurnings[xrn+1]]; if (RegionMaxLogFinal == SW_BOOL_TRUE) TMin *= exp(ceil ((log(RegionMin / TMin))/log(TStep)) * log(TStep)); else TMin += ceil (( RegionMin - TMin )/ TStep ) * TStep ; } if (TMax > RegionMax) { if (axis->LogFinal == SW_BOOL_TRUE) TMax /= exp(floor((log(TMax / RegionMax))/log(TStep)) * log(TStep)); else TMax -= floor(( TMax - RegionMax )/ TStep ) * TStep ; } } else { if (!inverted) { TMin = TickMinSet ? TickMin : ppl_min(axis->MinFinal , axis->MaxFinal); TMax = TickMaxSet ? TickMax : ppl_max(axis->MinFinal , axis->MaxFinal); } else { TMin = TickMaxSet ? TickMax : ppl_min(axis->MinFinal , axis->MaxFinal); TMax = TickMinSet ? TickMin : ppl_max(axis->MinFinal , axis->MaxFinal); } if (TMin < ppl_min(axis->MinFinal , axis->MaxFinal)) { if (axis->LogFinal == SW_BOOL_TRUE) TMin *= exp(ceil ((log(axis->MinFinal / TMin))/log(TStep)) * log(TStep)); else TMin += ceil (( axis->MinFinal - TMin )/ TStep ) * TStep ; } if (TMax > ppl_max(axis->MinFinal , axis->MaxFinal)) { if (axis->LogFinal == SW_BOOL_TRUE) TMax /= exp(floor((log(TMax / axis->MaxFinal))/log(TStep)) * log(TStep)); else TMax -= floor(( TMax - axis->MaxFinal )/ TStep ) * TStep ; } } for (i=0; i<100; i++) { if (!inverted) { if (axis->LogFinal == SW_BOOL_TRUE) tmp = TMin * pow(TStep, i); else tmp = TMin + i*TStep; } else { if (axis->LogFinal == SW_BOOL_TRUE) tmp = TMax * pow(TStep,-i); else tmp = TMax - i*TStep; } if (((!inverted)&&(tmp>TMax)) || ((inverted)&&(tmpLogFinal != SW_BOOL_TRUE) && (fabs(tmp)1.0) ) continue; // Filter out ticks which are off the end of the axis if (MajMin==0) (*TickListStrings)[j] = ""; else if (axis->format == NULL) TickLabelAutoGen(x, &(*TickListStrings)[j], tmp * UnitMultiplier, axis->tics.logBase, OutContext); else TickLabelFromFormat(x, &(*TickListStrings)[j], axis->format, tmp, &axis->DataUnit, axis->xyz, OutContext); if ((*TickListStrings)[j]==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (x)."); *TickListPositions = NULL; *TickListStrings = NULL; return; } j++; } } (*TickListStrings)[j] = NULL; // null terminate list } else { AutoTicks[MajMin] = 1; } } // Do automatic ticking as required if (AutoTicks[1]) { if ((axis->format != NULL) || (axis->AxisLinearInterpolation != NULL)) eps_plot_ticking_auto(x, axis, UnitMultiplier, AutoTicks, linkedto); else { if (linkedto!=NULL) eps_plot_ticking_auto3(x, axis, UnitMultiplier, AutoTicks, linkedto); else eps_plot_ticking_auto2(x, axis, UnitMultiplier, AutoTicks, linkedto); } } // Set flag to show that we have finalised the ticking of this axis axis->TickListFinalised = 1; } return; } void TickLabelAutoGen(EPSComm *X, char **output, double x, double log_base, int OutContext) { int SF = X->c->set->term_current.SignificantFigures; double ApproxMargin; ApproxMargin = pow(10,-SF+1); if (ApproxMargin < 1e-15) ApproxMargin = 1e-15; if ((fabs(x)1e-3) && (fabs(x)<1e5))) { sprintf(X->c->errcontext.tempErrStr,"%s",ppl_numericDisplay(x,X->c->numdispBuff[0],SF,1)); } else { double e,m; unsigned char sgn=0; if (x<0) { sgn=1; x=-x; } e = floor(log(x)/log(log_base)); m = x / pow(log_base,e); if (fabs(m-log_base)c->errcontext.tempErrStr,"%s%d^{%s}",sgn?"-":"",(int)log_base,ppl_numericDisplay(e,X->c->numdispBuff[0],SF,1)); else sprintf(X->c->errcontext.tempErrStr,"%s%s\\times %d^{%s}",sgn?"-":"",ppl_numericDisplay(m,X->c->numdispBuff[0],SF,1),(int)log_base,ppl_numericDisplay(e,X->c->numdispBuff[1],SF,1)); } *output = (char *)ppl_memAlloc_incontext(strlen(X->c->errcontext.tempErrStr)+3, OutContext); if ((*output)==NULL) return; sprintf(*output,"$%s$",X->c->errcontext.tempErrStr); return; } void TickLabelFromFormat(EPSComm *X, char **output, pplExpr *FormatExp, double x, pplObj *xunit, int xyz, int OutContext) { int lOP, rc; const int stkLevelOld = X->c->stackPtr; pplObj *outval; char *VarName, *tmp_string; pplObj DummyTemp, *VarVal; if (xyz==0) VarName = "x"; else if (xyz==1) VarName = "y"; else if (xyz==2) VarName = "z"; else VarName = "c"; // Look up variable in user space and get pointer to its value ppl_contextGetVarPointer(X->c, VarName, &VarVal, &DummyTemp); // Set value of x (or y/z) rc = VarVal->refCount; *VarVal = *xunit; VarVal->refCount = rc; VarVal->imag = 0.0; VarVal->flagComplex = 0; VarVal->real = x; // Generate tick string outval = ppl_expEval(X->c, FormatExp, &lOP, 0, X->iterDepth+1); if (X->c->errStat.status) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst using format string: %s",FormatExp->ascii); ppl_error(&X->c->errcontext,ERR_PREFORMED, -1, -1, NULL); ppl_tbWrite(X->c); ppl_tbClear(X->c); tmp_string = "{\\bf ?}"; } else if (outval->objType != PPLOBJ_STR) { sprintf(X->c->errcontext.tempErrStr, "Error encountered whilst using format string: %s",FormatExp->ascii); ppl_error(&X->c->errcontext,ERR_PREFORMED, -1, -1, NULL); ppl_error(&X->c->errcontext,ERR_PREFORMED, -1, -1, "Tick label was not a string."); tmp_string = "{\\bf ?}"; } else { tmp_string = (char *)outval->auxil; } *output = (char *)ppl_memAlloc_incontext(strlen(tmp_string)+3, OutContext); if ((*output)==NULL) return; sprintf(*output,"%s",tmp_string); { EPSComm *x=X; EPS_STACK_POP; } // Restore original value of x (or y/z) ppl_contextRestoreVarPointer(X->c, VarName, &DummyTemp); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto2.c0000664000175000017500000003461412026340554021005 0ustar dcf21dcf21// eps_plot_ticking_auto2.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto2.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contain an algorithm for the automatic placement of ticks along axes. // METHOD 2: Pyxplot 0.7 automatic ticking. #define _PPL_EPS_PLOT_TICKING_AUTO2_C 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "mathsTools/dcfmath.h" #include "stringTools/asciidouble.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_plot_ticking_auto.h" #include "epsMaker/eps_plot_ticking_auto2.h" #define MAX_FACTORS 32 /* Maximum number of factors of LogBase which we consider */ #define FACTOR_MULTIPLY 2.0 /* Factorise LogBase**2, so that 0.00,0.25,0.50,0.75,1.00 is a valid factorisation */ #define TICKS_MAXIMUM 256 /* Maximum number of ticks allowed along any given axis */ typedef struct TickScheme { int mantissa[TICKS_MAXIMUM]; int Nmantissas; double ticksep; double offset; } TickScheme; // Print a ticking scheme for debugging purposes static void TickScheme2_sprintf(char *out, const int OutLen, const double UnitMultiplier, const double *TL, const double TL_len) { int i=0,j=0,k=0; out[j++]='('; for (i=0; ((i TICKS_MAXIMUM) return; for (i=0; i0)&&(TickSchemes[*NTickSchemes].mantissa[i-1]==TickSchemes[*NTickSchemes].mantissa[i])) stopping=1; } if (!stopping) { TickSchemes[*NTickSchemes].Nmantissas = divisor; TickSchemes[*NTickSchemes].ticksep = 1.0; TickSchemes[*NTickSchemes].offset = 0.0; (*NTickSchemes)++; } } if (*NTickSchemes < TICKS_MAXIMUM) { for (i=1; ((i0.09) && (OoMscan<0.11)) { GenerateLogTickSchemes(TickSchemes, NTickSchemes, LogBase); } else { for (i=NFactors-1; i>=0; i--) { double t; TickSchemes[*NTickSchemes].mantissa[0] = 1; TickSchemes[*NTickSchemes].Nmantissas = 1; TickSchemes[*NTickSchemes].ticksep = t = FactorsTen[i] * OoMscan / pow(10.0, FACTOR_MULTIPLY-1); TickSchemes[*NTickSchemes].offset = 0.0; if ((!IsLog) || (ppl_dblEqual(t,floor(t+0.5)))) (*NTickSchemes)++; // Fractional steps (i.e. sqrts) not allowed } } LevelDescend++; } return; } // Return up to a maximum of MaxFactors factors of in. Factors are returned to array out. static void factorise(int in, int *out, int MaxFactors, int FactorMax, int *NFactors) { int i,j=0,k,N=sqrt(in); for (i=2; i<=N; i++) if (in%i==0) { out[j]=i; out[MaxFactors-1-j]=in/i; j++; if (j>=MaxFactors/2) break; } for (i=MaxFactors-j; i<=MaxFactors-1; i++) { out[j] = out[i]; if (out[j]!=out[j-1]) j++; } for (i=0; iLogFinal == SW_BOOL_TRUE); int FactorsTen[MAX_FACTORS]; double OoM, axis_min, axis_max, axis_min_l, axis_max_l, outer_min, outer_max; int TL_best_len, TL_trial_len; double *TLP, *TL_best, *TL_trial; char **TLS; int NTickSchemes; TickScheme *TickSchemes; if (DEBUG) ppl_log(&x->c->errcontext,"Using eps_plot_ticking_auto2()"); // Make temporary rough workspace OutContext = ppl_memAlloc_GetMemContext(); ContextRough = ppl_memAlloc_DescendIntoNewContext(); // This ticking scheme does not work on axes with non-linear mappings if (axis->AxisLinearInterpolation != NULL) goto FAIL; // Work out factors of log base of axis. In fact, work out factors of log base ** 2, so that ten divides by four. LogBase = IsLog ? axis->tics.logBase : 10; factorise(pow(10.0,FACTOR_MULTIPLY), FactorsTen, MAX_FACTORS, axis->PhysicalLengthMinor, &NFactorsTen); // Work out order of magnitude of axis range axis_min = axis->MinFinal * UnitMultiplier; axis_max = axis->MaxFinal * UnitMultiplier; if (axis_min > axis_max) { double temp; temp = axis_min; axis_min = axis_max; axis_max = temp; } else if (axis_min == axis_max) { goto FAIL; } if (IsLog && (axis_max < 3*axis_min)) IsLog = 0; if (!IsLog) { OoM = pow(10.0, ceil(log10(axis_max - axis_min))); outer_min = floor(axis_min / OoM) * OoM; outer_max = ceil (axis_max / OoM) * OoM; } else { axis_min_l = log(axis_min) / log(LogBase); axis_max_l = log(axis_max) / log(LogBase); OoM = pow(10.0, ceil(log10(axis_max_l - axis_min_l))); outer_min = floor(axis_min_l / OoM) * OoM; outer_max = ceil (axis_max_l / OoM) * OoM; } // Malloc list of accepted ticks if (AutoTicks[1]) { axis-> TickListPositions = (double *)ppl_memAlloc_incontext((TICKS_MAXIMUM+1) * sizeof(double), OutContext); axis-> TickListStrings = (char **)ppl_memAlloc_incontext((TICKS_MAXIMUM+1) * sizeof(char *), OutContext); } if (AutoTicks[0]) { axis->MTickListPositions = (double *)ppl_memAlloc_incontext((TICKS_MAXIMUM+1) * sizeof(double), OutContext); axis->MTickListStrings = (char **)ppl_memAlloc_incontext((TICKS_MAXIMUM+1) * sizeof(char *), OutContext); } if ( ((AutoTicks[1]) && ((axis-> TickListPositions==NULL) || (axis-> TickListStrings==NULL))) || ((AutoTicks[0]) && ((axis->MTickListPositions==NULL) || (axis->MTickListStrings==NULL))) ) goto FAIL; // Malloc temporary lists of ticks TL_best = (double *)ppl_memAlloc((TICKS_MAXIMUM+1) * sizeof(double)); TL_trial = (double *)ppl_memAlloc((TICKS_MAXIMUM+1) * sizeof(double)); if ((TL_best==NULL)||(TL_trial==NULL)) goto FAIL; TL_best_len = 0; // Malloc list of tick schemes TickSchemes = (TickScheme *)ppl_memAlloc((TICKS_MAXIMUM+1) * sizeof(TickScheme)); if (TickSchemes==NULL) goto FAIL; // Deal with MAJOR ticks. Then MINOR ticks. for (major=1; major>=0; major--) if (AutoTicks[major]) { if (major) { TLP = axis-> TickListPositions; TLS = axis-> TickListStrings; } else { TLP = axis->MTickListPositions; TLS = axis->MTickListStrings; } // How many ticks can we fit onto this axis? number_ticks = (major ? axis->PhysicalLengthMajor : axis->PhysicalLengthMinor) + 1; if (number_ticks < 2) number_ticks = 2; // Minimum of two ticks along any given axis if (number_ticks > TICKS_MAXIMUM) number_ticks = TICKS_MAXIMUM; // Maximum number of ticks along any given axis // Generate list of potential tick schemes GenerateTickSchemes(TickSchemes, &NTickSchemes, OoM, IsLog, LogBase, FactorsTen, NFactorsTen); // Try each tick scheme in turn for (i=0; i=TICKS_MAXIMUM) break; for (k=0; k=TICKS_MAXIMUM) break; x = ts_min + j * TickSchemes[i].ticksep; if (fabs(x)<1e-6*TickSchemes[i].ticksep) x=0; if (IsLog) x = pow(LogBase, x); x *= TickSchemes[i].mantissa[k]; if ((xaxis_max)) continue; TL_trial[TL_trial_len] = x; TL_trial_len++; } } // If minor ticks, make sure that this tick scheme overlays major ticks OverlayMatch = 1; if (!major) { if (DEBUG) { int tmp; sprintf(x->c->errcontext.tempErrStr, "Trying minor tick scheme: "); tmp = strlen(x->c->errcontext.tempErrStr); TickScheme2_sprintf(x->c->errcontext.tempErrStr+tmp, LSTR_LENGTH-tmp, UnitMultiplier, TL_trial, TL_trial_len); ppl_log(&x->c->errcontext,NULL); } for (j=0; axis->TickListStrings[j]!=NULL; j++) { OverlayMatch = 0; for (k=0; kTickListPositions[j])>1e-4) continue; for (k++; kc->errcontext.tempErrStr, "FAIL: Did not overlay major tick at %g (axis pos %.3f)", eps_plot_axis_InvGetPosition(axis->TickListPositions[j],axis), axis->TickListPositions[j]); ppl_log(&x->c->errcontext,NULL); } if (!OverlayMatch) continue; if (DEBUG) ppl_log(&x->c->errcontext,"PASS"); } // See whether this tick scheme is better than previous if ((IsLog)&&(TickSchemes[i].Nmantissas>=LogBase-1)&&(!major)) { if (TL_trial_len > 3*number_ticks) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Minor tick scheme with %d mantissas rejected because it has too many ticks (%d when we wanted ** %d)", TickSchemes[i].Nmantissas, TL_trial_len, number_ticks); ppl_log(&x->c->errcontext,NULL); } break; } if (DEBUG) ppl_log(&x->c->errcontext,"Accepted minor tick scheme which marks every mantissa value"); TL_best_len = TL_trial_len; for (j=0; j1)&&(TL_trial_len>number_ticks)) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Tick scheme with %d mantissas rejected because it has too many ticks (%d when we wanted %d)", TickSchemes[i].Nmantissas, TL_trial_len, number_ticks); ppl_log(&x->c->errcontext,NULL); } continue; } else if (TL_trial_len > number_ticks) break; else if (TL_trial_len > TL_best_len ) { for (j=0; jformat==NULL) TickLabelAutoGen(x, &TLS[j], xtmp, LogBase, OutContext); else TickLabelFromFormat(x, &TLS[j], axis->format, xtmp/UnitMultiplier, &axis->DataUnit, axis->xyz, OutContext); } else { TLS[j] = ""; } j++; } TLS[j] = NULL; } // Finished goto CLEANUP; FAIL: if (DEBUG) ppl_log(&x->c->errcontext,"eps_plot_ticking_auto2() has failed"); // A very simple way of putting ticks on axes when clever logic fails N = 1 + axis->PhysicalLengthMajor; // Estimate how many ticks we want if (N< 3) N= 3; if (N>100) N=100; axis->TickListPositions = (double *)ppl_memAlloc_incontext((N+1) * sizeof(double), OutContext); axis->TickListStrings = (char **)ppl_memAlloc_incontext((N+1) * sizeof(char *), OutContext); if ((axis->TickListPositions==NULL) || (axis->TickListStrings==NULL)) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (s)."); axis->TickListPositions = NULL; axis->TickListStrings = NULL; goto CLEANUP; } for (i=0; iTickListPositions[i] = X; X = eps_plot_axis_InvGetPosition(X, axis); if (axis->format == NULL) TickLabelAutoGen(x, &axis->TickListStrings[i] , X * UnitMultiplier , axis->tics.logBase, OutContext); else TickLabelFromFormat(x, &axis->TickListStrings[i], axis->format, X, &axis->DataUnit, axis->xyz, OutContext); if (axis->TickListStrings[i]==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory (t)."); axis->TickListPositions = NULL; axis->TickListStrings = NULL; goto CLEANUP; } } axis->TickListStrings[i] = NULL; // null terminate list CLEANUP: // Delete rough workspace if (ContextRough>0) ppl_memAlloc_AscendOutOfContext(ContextRough); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_threedimbuff.h0000664000175000017500000000352412026340554020710 0ustar dcf21dcf21// eps_plot_threedimbuff.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_threedimbuff.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_THREEDIMBUFF_H #define _PPL_EPS_PLOT_THREEDIMBUFF_H 1 #include "epsMaker/eps_comm.h" typedef struct ThreeDimBufferItem { unsigned char FlagLineSegment, FirstLineSegment; int linetype; double linewidth, offset, pointsize; char *colstr, *psfrag; double depth, LineLength, x0,y0,x1,y1,x2,y2; long LineSegmentID; } ThreeDimBufferItem; #ifndef _PPL_EPS_PLOT_THREEDIMBUFF_C extern unsigned char ThreeDimBuffer_ACTIVE; #endif void ThreeDimBuffer_Reset(EPSComm *x); int ThreeDimBuffer_Activate(EPSComm *x); int ThreeDimBuffer_Deactivate(EPSComm *x); int ThreeDimBuffer_writeps(EPSComm *x, double z, int linetype, double linewidth, double offset, double pointsize, char *colstr, char *psfrag); int ThreeDimBuffer_linesegment(EPSComm *x, double z, int linetype, double linewidth, char *colstr, double x0, double y0, double x1, double y1, double x2, double y2, unsigned char FirstSegment, unsigned char broken, double LengthOffset); int ThreeDimBuffer_linepenup(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_axespaint.h0000664000175000017500000000264512026340554020243 0ustar dcf21dcf21// eps_plot_axespaint.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_axespaint.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_AXESPAINT_H #define _PPL_EPS_PLOT_AXESPAINT_H 1 #include "settings/settings.h" #include "settings/withWords.h" #include "epsMaker/eps_comm.h" void eps_plot_axispaint(EPSComm *x, withWords *ww, pplset_axis *a, const int xyz, const double CP2, const unsigned char Lr, const double x1, const double y1, const double *z1, const double x2, const double y2, const double *z2, const double theta_a, const double theta_b, double *OutputWidth, const unsigned char PrintLabels); void eps_plot_axespaint(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth, int pass); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_gridlines.h0000664000175000017500000000202512026340554020217 0ustar dcf21dcf21// eps_plot_gridlines.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_gridlines.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_GRIDLINES_H #define _PPL_EPS_PLOT_GRIDLINES_H 1 #include "epsMaker/eps_comm.h" void eps_plot_gridlines(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth); #endif pyxplot-0.9.2/src/epsMaker/dvi_interpreter.h0000664000175000017500000001051012026340554017535 0ustar dcf21dcf21// dvi_interpreter.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_interpreter.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_DVI_INTERPRETER_H #define _PPL_DVI_INTERPRETER_H 1 #include "coreUtils/errorReport.h" #include "epsMaker/dvi_read.h" // Postscript functions int dviPostscriptLineto (pplerr_context *ec, dviInterpreterState *interp); int dviPostscriptClosepathFill(pplerr_context *ec, dviInterpreterState *interp); int dviChngFnt (pplerr_context *ec, dviInterpreterState *interp, int fn); int dviSpecialColourCommand (pplerr_context *ec, dviInterpreterState *interp, char *command); int dviSpecialColourStackPush (pplerr_context *ec, dviInterpreterState *interp, char *psText); int dviSpecialColourStackPop (pplerr_context *ec, dviInterpreterState *interp); // Interpreter functions for various types of dvi operators int dviInOpChar (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpSet1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpSetRule (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPut1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPutRule (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpNop (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpBop (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpEop (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPush (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPop (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpRight1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpW0 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpW1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpX0 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpX1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpDown1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpY0 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpY1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpZ0 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpZ1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpFnt (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpFnt1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpSpecial1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpFntdef1234 (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPre (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPost (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviInOpPostPost (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); // Functions called by operator interpreter functions int dviSpecialChar (pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviSpecialImplement (pplerr_context *ec, dviInterpreterState *interp); int dviNonAsciiChar (pplerr_context *ec, dviInterpreterState *interp, int c, char move); int dviUpdateBoundingBox(pplerr_context *ec, dviInterpreterState *interp, double width, double height, double depth); #endif pyxplot-0.9.2/src/epsMaker/eps_text.c0000664000175000017500000000636412026340554016172 0ustar dcf21dcf21// eps_text.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_text.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_TEXT 1 #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_text.h" #include "epsMaker/eps_settings.h" void eps_text_YieldUpText(EPSComm *x) { CanvasTextItem *i; x->current->FirstTextID = x->NTextItems; if (x->current->text[0]=='\0') return; i = (CanvasTextItem *)ppl_memAlloc(sizeof(CanvasTextItem)); if (i==NULL) { ppl_error(&x->c->errcontext, ERR_MEMORY, -1, -1, "Out of memory"); *(x->status) = 1; return; } i->text = x->current->text; i->CanvasMultiplotID = x->current->id; ppl_listAppend(x->TextItems, i); x->NTextItems++; return; } void eps_text_RenderEPS(EPSComm *x) { withWords def, merged; double xgap, ygap, xgap2, ygap2; int pageno; pageno = x->LaTeXpageno = x->current->FirstTextID; x->LaTeXpageno++; if (x->current->text[0]=='\0') return; // Write header at top of postscript fprintf(x->epsbuffer, "%% Canvas item %d [text label]\n", x->current->id); // Work out text color ppl_withWordsZero(x->c , &def); def.color = x->current->settings.TextColor; def.color1 = x->current->settings.TextColor1; def.color2 = x->current->settings.TextColor2; def.color3 = x->current->settings.TextColor3; def.color4 = x->current->settings.TextColor4; def.Col1234Space = x->current->settings.TextCol1234Space; def.USEcolor = (def.color!=0); def.USEcolor1234 = (def.color==0); ppl_withWordsMerge(x->c , &merged, &x->current->with_data, &def, NULL, NULL, NULL, 1); eps_core_SetColor(x, &merged, 1); // Render text item to eps xgap = -(x->current->settings.TextHAlign - SW_HALIGN_CENT) * x->current->xpos2; ygap = (x->current->settings.TextVAlign - SW_VALIGN_CENT) * x->current->xpos2; xgap2 = xgap*cos(x->current->rotation) - ygap*sin(x->current->rotation); ygap2 = xgap*sin(x->current->rotation) + ygap*cos(x->current->rotation); canvas_EPSRenderTextItem(x, NULL, pageno, x->current->xpos + xgap2, x->current->ypos + ygap2, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, x->current->rotation, NULL, NULL); // Free with words ppl_withWordsDestroy(x->c, &merged); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_polygon.c0000664000175000017500000000660712026340554016675 0ustar dcf21dcf21// eps_polygon.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_polygon.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_ARROW 1 #include #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" void eps_polygon_RenderEPS(EPSComm *x) { int i; unsigned char filled=0, stroked=0; withWords ww; double lw, lw_scale; int lt; // Print label at top of postscript description of polygon fprintf(x->epsbuffer, "%% Canvas item %d [polygon]\n", x->current->id); eps_core_clear(x); // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(x->c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Set fill color of polygon eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); // Fill polygon IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n", x->current->polygonPoints[0]*M_TO_PS, x->current->polygonPoints[1]*M_TO_PS); for (i=0; icurrent->NpolygonPoints; i++) fprintf(x->epsbuffer, "%.2f %.2f lineto\n", x->current->polygonPoints[2*i]*M_TO_PS, x->current->polygonPoints[2*i+1]*M_TO_PS); fprintf(x->epsbuffer, "closepath\nfill\n"); filled=1; } // Set color of outline of polygon eps_core_SetColor(x, &ww, 1); // Set linewidth and linetype of outline if (ww.USElinewidth) lw_scale = ww.linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww.USElinetype) lt = ww.linetype; else lt = 1; IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); // Stroke outline of polygon IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n", x->current->polygonPoints[0]*M_TO_PS, x->current->polygonPoints[1]*M_TO_PS); for (i=0; icurrent->NpolygonPoints; i++) fprintf(x->epsbuffer, "%.2f %.2f lineto\n", x->current->polygonPoints[2*i]*M_TO_PS, x->current->polygonPoints[2*i+1]*M_TO_PS); fprintf(x->epsbuffer, "closepath\nstroke\n"); stroked=1; } // Factor four corners of box into EPS file's bounding box if (filled || stroked) for (i=0; icurrent->NpolygonPoints; i++) eps_core_BoundingBox(x, x->current->polygonPoints[2*i]*M_TO_PS, x->current->polygonPoints[2*i+1]*M_TO_PS, lw); // Free with words ppl_withWordsDestroy(x->c, &ww); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_eps.c0000664000175000017500000002700612026340554015771 0ustar dcf21dcf21// eps_eps.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_eps.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_EPS 1 #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_eps.h" #include "epsMaker/eps_settings.h" void eps_eps_RenderEPS(EPSComm *x) { FILE *inf; char filename[FNAME_LENGTH]; double bb_left=0.0, bb_right=0.0, bb_top=0.0, bb_bottom=0.0; double xscale, yscale, r; double xanchor=0, yanchor=0, xbotleft, ybotleft; unsigned char GotBBox; fprintf(x->epsbuffer, "%% Canvas item %d [eps image]\n", x->current->id); // Expand filename if it contains wildcards { wordexp_t wordExp; glob_t globData; char fName[FNAME_LENGTH]; { int j,k; for (j=k=0; ((x->current->text[j]!='\0')&&(kcurrent->text[j]==' ') fName[k++]='\\'; fName[k++]=x->current->text[j++]; } fName[k++]='\0'; } if ((wordexp(fName, &wordExp, 0) != 0) || (wordExp.we_wordc <= 0)) { sprintf(x->c->errcontext.tempErrStr, "Could not open file '%s'.", fName); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); return; } if ((glob(wordExp.we_wordv[0], 0, NULL, &globData) != 0) || (globData.gl_pathc <= 0)) { sprintf(x->c->errcontext.tempErrStr, "Could not open file '%s'.", fName); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); wordfree(&wordExp); return; } wordfree(&wordExp); snprintf(filename, FNAME_LENGTH, "%s", globData.gl_pathv[0]); filename[FNAME_LENGTH-1]='\0'; globfree(&globData); } // Work out bounding box of EPS image GotBBox = 0; if (!x->current->calcbbox) // Read bounding box from headers of EPS file { inf = fopen(filename, "r"); if (inf==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open EPS file '%s'.", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; return; } eps_eps_ExtractBBox(x, inf, &bb_left, &bb_bottom, &bb_right, &bb_top, &GotBBox); fclose(inf); if (!GotBBox) { sprintf(x->c->errcontext.tempErrStr, "Could not extract bounding box from EPS file '%s'. Will therefore process file in calcbbox mode, and attempt to determine its bounding box using ghostview.", filename); ppl_warning(&x->c->errcontext, ERR_GENERIC, x->c->errcontext.tempErrStr); } } if ((x->current->calcbbox) || (!GotBBox)) // Calculate bounding box for EPS file using ghostview { char command[LSTR_LENGTH], tmpdata[FNAME_LENGTH]; sprintf(tmpdata, "%s%s%s", x->c->errcontext.session_default.tempdir, PATHLINK, "bbox_in"); // Temporary file for gs to output bounding box into sprintf(command, "%s -dQUIET -dSAFER -dBATCH -dNOPAUSE -sDEVICE=bbox %s > %s 2> %s", GHOSTSCRIPT_COMMAND, filename, tmpdata, tmpdata); if (system(command)) if (DEBUG) { ppl_log(&x->c->errcontext, "Ghostscript returned non-zero return value."); } inf = fopen(tmpdata, "r"); if (inf==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open temporary file '%s'.", tmpdata); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; return; } eps_eps_ExtractBBox(x, inf, &bb_left, &bb_bottom, &bb_right, &bb_top, &GotBBox); fclose(inf); if (!GotBBox) { sprintf(x->c->errcontext.tempErrStr, "Could not calculate bounding box for EPS file '%s'.", filename); ppl_warning(&x->c->errcontext, ERR_GENERIC, x->c->errcontext.tempErrStr); } } // Work out scaling factor to apply to EPS image if (GotBBox && (x->current->xpos2set) && (x->current->ypos2set)) // Both width and height have been specified { xscale = x->current->xpos2 * M_TO_PS / (bb_right - bb_left ); yscale = x->current->ypos2 * M_TO_PS / (bb_top - bb_bottom); } else if (GotBBox && x->current->xpos2set) // Only width has been set { xscale = x->current->xpos2 * M_TO_PS / (bb_right - bb_left ); yscale = x->current->xpos2 * M_TO_PS / (bb_right - bb_left ); } else if (GotBBox && x->current->ypos2set) // Only height has been set { xscale = x->current->ypos2 * M_TO_PS / (bb_top - bb_bottom); yscale = x->current->ypos2 * M_TO_PS / (bb_top - bb_bottom); } else // Neither height nor width has been set; EPS file should be drawn at its natural size { xscale = 1.0; yscale = 1.0; } // Work out position of bottom-left corner r = x->current->rotation; if (x->current->settings.TextHAlign == SW_HALIGN_LEFT ) xanchor = 0; else if (x->current->settings.TextHAlign == SW_HALIGN_CENT ) xanchor = (xscale)/2; else if (x->current->settings.TextHAlign == SW_HALIGN_RIGHT) xanchor = (xscale); if (x->current->settings.TextVAlign == SW_VALIGN_TOP ) yanchor = (yscale); else if (x->current->settings.TextVAlign == SW_VALIGN_CENT ) yanchor = (yscale)/2; else if (x->current->settings.TextVAlign == SW_VALIGN_BOT ) yanchor = 0; xanchor *= (bb_right - bb_left ); yanchor *= (bb_top - bb_bottom); xbotleft = x->current->xpos*M_TO_PS-(xanchor*cos(r)-yanchor*sin(r)); ybotleft = x->current->ypos*M_TO_PS-(xanchor*sin(r)+yanchor*cos(r)); // Begin encapsulation of EPS file fprintf(x->epsbuffer, "BeginEPSF\n"); fprintf(x->epsbuffer, "%.2f %.2f translate %% Position the EPS file\n", xbotleft, ybotleft); fprintf(x->epsbuffer, "%.2f rotate %% Rotation of EPS graphic\n", x->current->rotation * 180 / M_PI); fprintf(x->epsbuffer, "%f %f scale %% Scale to desired size\n", xscale, yscale); fprintf(x->epsbuffer, "%f %f translate %% Move to lower left of the EPS\n", -bb_left, -bb_bottom); // Clip EPS to bounding box if requested if ((x->current->clip) && (GotBBox)) { fprintf(x->epsbuffer, "newpath\n%f %f moveto %f %f lineto %f %f lineto %f %f lineto closepath\n", bb_left, bb_bottom, bb_right, bb_bottom, bb_right, bb_top, bb_left, bb_top); fprintf(x->epsbuffer, "clip newpath %% Set clipping path around bounding box\n"); } // Copy contents of EPS into output postscript file fprintf(x->epsbuffer, "%% ---- Beginning of included EPS graphic ----\n%%%%BeginDocument: epsfile.eps\n"); inf = fopen(filename, "r"); if (inf==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open EPS file '%s'.", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; return; } while (fgets(x->c->errcontext.tempErrStr, FNAME_LENGTH, inf) != NULL) if (fputs(x->c->errcontext.tempErrStr, x->epsbuffer) == EOF) { sprintf(x->c->errcontext.tempErrStr, "Error while reading EPS file '%s'.", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status)=1; fclose(inf); return; } fclose(inf); // Finish off encapsulation of EPS file fprintf(x->epsbuffer, "%%%%EOF\n%%%%EndDocument\n\n%% ---- End of included EPS graphic ----\nEndEPSF\n"); // Update postscript bounding box xscale *= (bb_right - bb_left); // Multiply scaling factors by width and height to give total size of resulting image in points yscale *= (bb_top - bb_bottom); eps_core_BoundingBox(x, xbotleft , ybotleft , 0); eps_core_BoundingBox(x, xbotleft + xscale*cos(r) , ybotleft + xscale*sin(r) , 0); eps_core_BoundingBox(x, xbotleft + yscale*-sin(r) , ybotleft + yscale*cos(r) , 0); eps_core_BoundingBox(x, xbotleft + xscale*cos(r) + yscale*-sin(r) , ybotleft + xscale*sin(r) + yscale*cos(r) , 0); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } void eps_eps_ExtractBBox(EPSComm *x, FILE *in, double *bl, double *bb, double *br, double *bt, unsigned char *GotBox) { const char BBoxStr [] = "%%BoundingBox:"; const char HRBBoxStr[] = "%%HiResBoundingBox:"; int bbox_i=0, hrbbox_i=0, j, bbox_len, hrbbox_len, i; double blt, bbt, brt, btt; // Temporary bounding box values bbox_len = strlen(BBoxStr ); hrbbox_len = strlen(HRBBoxStr); *GotBox = 0; while ((j=fgetc(in))!=EOF) // Search input file for bounding box strings { if (BBoxStr [bbox_i ] == j) { bbox_i ++; } else { bbox_i = 0; } if (HRBBoxStr[hrbbox_i] == j) { hrbbox_i++; } else { hrbbox_i = 0; } if (bbox_i == bbox_len) { bbox_i = 0; if (fgets(x->c->errcontext.tempErrStr, FNAME_LENGTH, in) != NULL) // Read %%BoundingBox: . . . . { i=0; while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; blt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; bbt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; brt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; btt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box *bl = blt; *bb = bbt; *br = brt; *bt = btt; // Carry on looping to see if we can find a high resolution bounding box *GotBox = 1; } } if (hrbbox_i == hrbbox_len) { hrbbox_i = 0; if (fgets(x->c->errcontext.tempErrStr, FNAME_LENGTH, in) != NULL) // Read %%HiResBoundingBox: . . . . { i=0; while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; blt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; bbt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; brt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box while ((x->c->errcontext.tempErrStr[i]<=' ') && (x->c->errcontext.tempErrStr[i]!='\0')) i++; btt = ppl_getFloat(x->c->errcontext.tempErrStr+i, &j); if (j<=0) continue; else i+=j; // If j<=0, bad bounding box *bl = blt; *bb = bbt; *br = brt; *bt = btt; *GotBox = 1; return; // A high resolution bounding box is better than a low resolution bounding box, so we've got all we need } } } return; } pyxplot-0.9.2/src/epsMaker/bmp_a85.c0000664000175000017500000000557512026340554015575 0ustar dcf21dcf21// bmp_a85.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_a85.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It efficiently encodes a string of raw image data into // postscript's ASCII 85 data format, making use of all of the printable ASCII // characters. #define _PPL_BMP_A85_C 1 #include #include #include "coreUtils/errorReport.h" // Number of raw bytes to encode per line. Note actual line length will be // 1.25x this. Sane values are 56 (70 characters) or 60 (75 chars). Must be a // multiple of 4. #define LINELEN 56 unsigned int ppl_bmp_A85(pplerr_context *ec, FILE* fout, unsigned char* in, int len) { int i, j; unsigned int tmp, t, line, length=0; unsigned int pow85[] = {52200625,614125,7225,85,1}; // powers of 85 unsigned char out[LINELEN/4*5+4], *outp; while (len>0) { line = (len>LINELEN) ? LINELEN : len; len = len-line; outp = out; for (i=0; i<(line&0xfffc); i+=4) // encode groups of four bytes { tmp=0; for(j=0; j<4; j++) { tmp = tmp<<8; tmp += *(in++); } if (tmp) { for (j=0; j<4; j++) { t = tmp/pow85[j]; tmp -= t*pow85[j]; *(outp++) = t+'!'; } *(outp++)=tmp+'!'; } else *(outp++)='z'; // zero is encoded as "z", not "!" } if (line&0x3) // Deal with any final group of <4 bytes { i = line&0xfffc; tmp = 0; for (j=0; j<4; j++) { tmp = tmp<<8; if ((i+j)\n"); return length; } pyxplot-0.9.2/src/epsMaker/dvi_read.c0000664000175000017500000002564512026340554016117 0ustar dcf21dcf21// dvi_read.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_read.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating dvi files #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "epsMaker/dvi_read.h" #include "epsMaker/dvi_font.h" // The following is useful for output sometimes const char *dviops[58] = { "set1", "set2", "set3", "set4", "setrule", "put1", "put2", "put3", "put4", "putrule", "nop", "bop", "eop", "push", "pop", "right1", "right2", "right3", "right4", "w0", "w1", "w2", "w3", "w4", "x0", "x1", "x2", "x3", "x4", "down1", "down2", "down3", "down4", "y0", "y1", "y2", "y3", "y4", "z0", "z1", "z2", "z3", "z4", // Big hole in the labels here... "fnt1", "fnt2", "fnt3", "fnt4", "special1", "special2", "special3", "special4", "fntdef1", "fntdef2", "fntdef3", "fntdef4", "pre", "post", "postpost" }; dviInterpreterState *ReadDviFile(pplerr_context *ec, char *filename, int *status) { FILE *fp; DVIOperator op; int i; dviInterpreterState *interpreter; int POST=0; int err; op.s[0] = NULL; op.s[1] = NULL; // Set up the interpreter interpreter = dviNewInterpreter(ec); fp = fopen(filename, "r"); if (fp==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"dvi file does not exist!"); *status = 1; return NULL; } // This is the main loop for the dvi parser while (!feof(fp)) { // Read the next operator from the dvi file if ((err=GetDVIOperator(ec, &op, fp))!=0) { if (err) { *status=err; fclose(fp); return NULL; } else { continue; } } if (DEBUG) DisplayDVIOperator(ec, &op); // Producing debugging output // A slightly more sophisticated interpreter that makes some postscript if (!POST) { err = dviInterpretOperator(ec, interpreter, &op); if (err) { *status=err; fclose(fp); return NULL; } } for (i=0; i<2; i++) { if (op.s[i]!=NULL) { //free(op.s[i]); op.s[i] = NULL; } } // If we've hit the post then we can break out if (op.op==DVI_POST) { POST = 1; break; } } fclose(fp); return interpreter; } // Read in a DVI Operator and any additional data that it comes with // A useful reference for the meaning and size of the additional data is // http://www-users.math.umd.edu/~asnowden/comp-cont/dvi.html int GetDVIOperator(pplerr_context *ec, DVIOperator *op, FILE *fp) { int i, v, err; // First read in the opcode if ((err=ReadUChar(ec, fp,&v))!=0) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Error reading dvi operator from disk"); return err; } op->op = v; // Now work out what it represents and get any extra data if needed if (v < DVI_CHARMIN) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Illegal opcode whilst parsing DVI file"); return 1; } else if (v >= DVI_CHARMIN && v <= DVI_CHARMAX) { return 0; } else if (v < DVI_SET1234+4) { int Ndata; Ndata = v - DVI_SET1234 + 1; if ((err=ReadLongInt(ec, fp, op->ul, Ndata))!=0) return err; // Set to DVI_SET1234 for convenience later (we don't need to know whether it's 1, 2, 3 or 4) // op->op = DVI_SET1234; return 0; } else if (v == DVI_SETRULE) { if ((err = ReadSignedInt(ec, fp, op->sl, 4))!=0) return err; if ((err = ReadSignedInt(ec, fp, op->sl+1, 4))!=0) return err; return 0; } else if (v < DVI_PUT1234+4) { int Ndata; Ndata = v - DVI_PUT1234 + 1; if ((err=ReadLongInt(ec, fp, op->ul, Ndata))!=0) return err; return 0; } else if (v == DVI_PUTRULE) { if ((err = ReadSignedInt(ec, fp, op->sl, 4))!=0) return err; if ((err = ReadSignedInt(ec, fp, op->sl+1, 4))!=0) return err; return 0; } else if (v == DVI_NOP) { return 0; } else if (v == DVI_BOP) { for (i=0; i<10; i++) { if ((err = ReadLongInt(ec, fp, op->ul+i, 4))!=0) return err; } if ((err= ReadSignedInt(ec, fp, op->sl, 4))!=0) return err; return 0; } else if (v >= DVI_EOP && v <= DVI_POP) { return 0; } else if (v < DVI_RIGHT1234 + 4) { int Ndata; Ndata = v - DVI_RIGHT1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; // Set to DVI_RIGHT1234 for convenience later (we don't need to know whether it's 1, 2, 3 or 4) // op->op = DVI_RIGHT1234; return 0; } else if (v == DVI_W0) { return 0; } else if (v < DVI_W1234 + 4) { int Ndata; Ndata = v - DVI_W1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; return 0; } else if (v == DVI_X0) { return 0; } else if (v < DVI_X1234 + 4) { int Ndata; Ndata = v - DVI_X1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; return 0; } else if (v < DVI_DOWN1234 + 4) { int Ndata; Ndata = v - DVI_DOWN1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; return 0; } else if (v == DVI_Y0) { return 0; } else if (v < DVI_Y1234 + 4) { int Ndata; Ndata = v - DVI_Y1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; return 0; } else if (v == DVI_Z0) { return 0; } else if (v < DVI_Z1234 + 4) { int Ndata; Ndata = v - DVI_Z1234 + 1; if ((err=ReadSignedInt(ec, fp, op->sl, Ndata))!=0) return err; return 0; } else if (v >= DVI_FNTNUMMIN && v <= DVI_FNTNUMMAX) { return 0; } else if (v <= DVI_FNT1234) { int Ndata; Ndata = v - DVI_FNT1234 + 1; if ((err=ReadLongInt(ec, fp, op->ul, Ndata))!=0) return err; return 0; } else if (v <= DVI_SPECIAL1234) { int Ndata; Ndata = v - DVI_SPECIAL1234 + 1; if ((err=ReadLongInt(ec, fp, op->ul, Ndata))!=0) return err; return 0; } else if (v <= DVI_FNTDEF1234) { int i, Ndata; Ndata = v - DVI_FNTDEF1234 + 1; if ((err=ReadLongInt(ec, fp, op->ul, Ndata))!=0) return err; for (i=1; i<4; i++) { if ((err=ReadLongInt(ec, fp, op->ul+i, 4))!=0) return err; } for (i=4; i<6; i++) { if ((err=ReadLongInt(ec, fp, op->ul+i, 1))!=0) return err; } Ndata = op->ul[4] + op->ul[5]; op->s[0] = (char *)ppl_memAlloc(Ndata+1); if (op->s[0]==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } op->s[0][Ndata] = '\0'; for (i=0; is[0][i] = (char) j; } return 0; } else if (v == DVI_PRE) { int i, v1; if ((err=ReadUChar(ec, fp, &v1))!=0) return err; op->ul[0] = v1; for (i=1; i<4; i++) { if ((err=ReadLongInt(ec, fp, op->ul+i, 4))!=0) return err; } if ((err=ReadUChar(ec, fp,&v1))!=0) return err; // Throw away the DVI comment for (i=v1; i>0; i--) { if ((err=ReadUChar(ec, fp,&v1))!=0) return err; } return 0; } else if (v == DVI_POST) { for (i=0; i<6; i++) { if ((err=ReadLongInt(ec, fp, op->ul+i,4))!=0) return err; } for (i=6; i<8; i++) { if ((err=ReadLongInt(ec, fp, op->ul+i,2))!=0) return err; } return 0; } else if (v == DVI_POSTPOST) { int v1; if ((err=ReadLongInt(ec, fp, op->ul,4))!=0) return err; if ((err=ReadUChar(ec, fp,&v1))!=0) return err; op->ul[1] = v1; // Mop up all the 223s // while (!feof(fp)) // { // if ((err=ReadUChar(ec, fp,&v1))!=0) return err; // if (v1 != 223) return v1; // } return 0; } else { ppl_error(ec, ERR_INTERNAL, -1, -1,"Unidentified opcode in dvi file"); return 1; } // Once we've got an operator we return, so we should never get here ppl_error(ec, ERR_INTERNAL, -1, -1, "GetDVIOperator: flow control has gone wrong"); return 1; } // Read an unsigned char from a dvi file int ReadUChar(pplerr_context *ec, FILE *fp, int *uc) { int i; i = getc(fp); if (i==EOF) { ppl_error(ec, ERR_INTERNAL, -1, -1, "Unexpected EOF in dvi file"); return 1; } *uc = i; return 0; } // Read a long int from a dvi file (using the DVI long int format) int ReadLongInt(pplerr_context *ec, FILE *fp, unsigned long int *uli, int n) { int err,v,i; unsigned long int fv; if ((err=ReadUChar(ec, fp, &v))!=0) return err; fv = v; for (i=0; iop <= DVI_CHARMAX) { int i; i=op->op; if ((i>=31) && (i<=126)) snprintf(s2, 128, "DVI: Read character %d %c", i, i); else snprintf(s2, 128, "DVI: Read character %d", i); s = s2; } else if (op->op == DVI_PRE) // Special cases { snprintf(s2, 128, "DVI: Read %s %lu %lu %lu %lu", "pre", *(op->ul), *(op->ul+1), *(op->ul+2), *(op->ul+3)); s=s2; } else if (op->op == DVI_FNTDEF1234) { snprintf(s2, 128, "DVI: Read %s N=%lu d=%lu n=%s", "fnt def", *(op->ul), *(op->ul+4), (op->s[0])); s=s2; } else if (op->op < DVI_FNTNUMMIN) { s = (char *)dviops[op->op-DVI_CHARMAX-1]; if (strlen(s)==2 && (char)s[1]>'0') { snprintf(s2, 128, "DVI: Read %s %lu", dviops[op->op-DVI_CHARMAX-1], *(op->ul)); s=s2; } else { snprintf(s2, 128, "DVI: Read %s", s); s=s2; } } else if (op->op <= DVI_FNTNUMMAX) { snprintf(s2, 128, "DVI: Read font number %d", op->op-DVI_FNTNUMMIN); s=s2; } else if (op->op <= DVI_POSTPOST) { int i; i = op->op-DVI_CHARMAX-1-(DVI_FNTNUMMAX-DVI_FNTNUMMIN+1); snprintf(s2, 128, "DVI: Read %s", (char *)dviops[i]); s=s2; //s = (char *)dviops[i]; } else { snprintf(s2, 128, "DVI: dvi error"); s=s2; } ppl_log(ec, s); return 0; } pyxplot-0.9.2/src/epsMaker/eps_style.h0000664000175000017500000000220712026340554016343 0ustar dcf21dcf21// eps_style.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_style.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_STYLE_H #define _PPL_EPS_STYLE_H 1 #define N_POINTTYPES 44 #define N_STARTYPES 9 char *eps_LineType(int lt, double lw, double offset); #ifndef _PPL_EPS_STYLE_C extern char *eps_PointTypes[]; extern double eps_PointSize []; extern char *eps_StarTypes []; extern double eps_StarSize []; extern char *eps_StarCore; #endif #endif pyxplot-0.9.2/src/epsMaker/eps_eps.h0000664000175000017500000000202112026340554015764 0ustar dcf21dcf21// eps_eps.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_eps.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_EPS_H #define _PPL_EPS_EPS_H 1 #include "epsMaker/eps_comm.h" void eps_eps_RenderEPS(EPSComm *x); void eps_eps_ExtractBBox(EPSComm *x, FILE *in, double *bl, double *bb, double *br, double *bt, unsigned char *GotBox); #endif pyxplot-0.9.2/src/epsMaker/eps_arrow.h0000664000175000017500000000214312026340554016334 0ustar dcf21dcf21// eps_arrow.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_arrow.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_ARROW_H #define _PPL_EPS_ARROW_H 1 #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" void eps_arrow_RenderEPS(EPSComm *x); void eps_primitive_arrow(EPSComm *x, int ArrowType, double x1, double y1, const double *z1, double x2, double y2, const double *z2, withWords *with_data); #endif pyxplot-0.9.2/src/epsMaker/eps_comm.h0000664000175000017500000000327012026340554016137 0ustar dcf21dcf21// eps_comm.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_comm.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_COMM_H #define _PPL_EPS_COMM_H 1 #include #include "coreUtils/list.h" #include "epsMaker/dvi_read.h" #include "epsMaker/eps_style.h" #include "userspace/context.h" #include "canvasItems.h" typedef struct CanvasTextItem { char *text; int CanvasMultiplotID; int LaTeXstartline, LaTeXendline; } CanvasTextItem; typedef struct EPSComm { ppl_context *c; int iterDepth; canvas_itemlist *itemlist; canvas_item *current; double bb_left, bb_right, bb_top, bb_bottom; unsigned char bb_set; unsigned char PointTypesUsed[N_POINTTYPES], StarTypesUsed[N_STARTYPES]; list *TextItems; int NTextItems; dviInterpreterState *dvi; char *EPSFilename, *TeXFilename, *FinalFilename, *title; char LastPSColor[256], CurrentColor[256], CurrentFillColor[256]; double LastLinewidth; int LastLinetype; FILE *epsbuffer; int *status, termtype, LaTeXpageno; } EPSComm; #endif pyxplot-0.9.2/src/epsMaker/eps_piechart.c0000664000175000017500000006150612026340554017004 0ustar dcf21dcf21// eps_piechart.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_piechart.c 1276 2012-07-25 22:50:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PIECHART 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "expressions/expEval.h" #include "mathsTools/dcfmath.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_piechart.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_plot_styles.h" #include "epsMaker/eps_settings.h" #include "datafile.h" #include "datafile_rasters.h" #define COUNTERR_BEGIN if (errCount> 0) { errCount--; #define COUNTERR_END if (errCount==0) { sprintf(c->errcontext.tempErrStr, "Too many errors: no more errors will be shown."); \ ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { ppl_warning(&c->errcontext,ERR_STACKED,"Stack forward reference detected."); } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } void eps_pie_ReadAccessibleData(EPSComm *x) { ppl_context *c = x->c; int j, status=0, errCount=DATAFILE_NERRS, NExpect=1, Ncolumns; canvas_plotdesc *pd=x->current->plotitems; pplExpr *LabelExpr; pplExpr **UsingList; unsigned char autoUsingList=0; int NUsing; int nObjs=0; withWords ww_default; double *ordinate_raster, acc; dataBlock *blk; if (pd==NULL) return; NUsing=pd->NUsing; UsingList = (pplExpr **)ppl_memAlloc( (USING_ITEMS_MAX+8) * sizeof(pplExpr *) ); if (UsingList == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (A)"); *(x->status) = 1; return; } memcpy(UsingList, pd->UsingList, NUsing*sizeof(pplExpr *)); // Malloc pointer to data table where data to be plotted will be stored x->current->plotdata = (dataTable **)ppl_memAlloc(1 * sizeof(dataTable *)); x->current->DatasetTextID = (int *)ppl_memAlloc(1 * sizeof(int)); if (x->current->plotdata == NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (B)"); *(x->status) = 1; return; } // Merge together with words to form a final set eps_withwords_default(x, &ww_default, &x->current->settings, 1, 0, 0, 0, c->set->term_current.color==SW_ONOFF_ON); ppl_withWordsDestroy(c, &pd->ww_final); ppl_withWordsMerge(c, &pd->ww_final, &pd->ww, &x->current->settings.funcStyle, &ww_default, NULL, NULL, 1); pd->ww_final.linespoints = SW_STYLE_LINES; // In case FuncStyle is something bonkers like contourplot // Make raster on which to evaluate parametric functions ordinate_raster = (double *)ppl_memAlloc(x->current->settings.samples * sizeof(double)); if (x->current->settings.Tlog == SW_BOOL_TRUE) ppl_logRaster(ordinate_raster, x->current->settings.Tmin.real, x->current->settings.Tmax.real, x->current->settings.samples); else ppl_linRaster(ordinate_raster, x->current->settings.Tmin.real, x->current->settings.Tmax.real, x->current->settings.samples); // Work out what label string to use if (pd->label != NULL) { LabelExpr = pd->label; } else { int end=0,ep=0,es=0; char ascii[] = "\"Item %d\"%($0)"; pplExpr *exptmp=NULL; ppl_expCompile(c,0,0,"",ascii,&end,1,0,0,&exptmp,&ep,&es,c->errcontext.tempErrStr); if (es || c->errStat.status) { ppl_tbClear(c); ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (C)"); *(x->status) = 1; return; } LabelExpr = pplExpr_tmpcpy(exptmp); pplExpr_free(exptmp); if (LabelExpr==NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (D)"); *(x->status) = 1; return; } } if (eps_plot_AddUsingItemsForWithWords(c, &pd->ww_final, &NExpect, &autoUsingList, &UsingList, &NUsing, &nObjs, c->errcontext.tempErrStr)) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, NULL); *(x->status) = 1; return; } // Add extra using items for, e.g. "linewidth $3". if (pd->filename != NULL) // Read data from file { if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from file '%s' for piechart item %d", pd->filename, x->current->id); ppl_log(&c->errcontext,NULL); } if (pd->PersistentDataTable==NULL) ppldata_fromFile(c, x->current->plotdata, pd->filename, 0, NULL, NULL, pd->index, UsingList, autoUsingList, NExpect, nObjs, LabelExpr, pd->SelectCriterion, NULL, pd->UsingRowCols, pd->EveryList, pd->continuity, 0, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); else x->current->plotdata[0] = pd->PersistentDataTable; } else if (pd->vectors != NULL) { if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from vectors for piechart item %d", x->current->id); ppl_log(&c->errcontext,NULL); } ppldata_fromVectors(c, x->current->plotdata, pd->vectors, pd->NFunctions, UsingList, autoUsingList, NExpect, nObjs, LabelExpr, pd->SelectCriterion, NULL, pd->continuity, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); } else { double *rX = ordinate_raster; int rXl= x->current->settings.samples; pplObj *uX = &x->current->settings.Tmin; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Reading data from functions for piechart item %d", x->current->id); ppl_log(&c->errcontext,NULL); } ppldata_fromFuncs_checkSpecialRaster(c, pd->functions, pd->NFunctions, "t", &x->current->settings.Tmin.real, &x->current->settings.Tmax.real, uX, &rX, &rXl); ppldata_fromFuncs(c, x->current->plotdata, pd->functions, pd->NFunctions, rX, rXl, 1, uX, NULL, 0, NULL, UsingList, autoUsingList, NExpect, nObjs, LabelExpr, pd->SelectCriterion, NULL, pd->continuity, &status, c->errcontext.tempErrStr, &errCount, x->iterDepth+1); } if (status) { ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, NULL); x->current->plotdata[0]=NULL; } // Work out sum of all pie segment sizes if (x->current->plotdata[0]==NULL) return; Ncolumns = x->current->plotdata[0]->Ncolumns_real; blk = x->current->plotdata[0]->first; acc = 0.0; while (blk != NULL) { for (j=0; jblockPosition; j++) { acc += fabs(blk->data_real[0 + Ncolumns*j]); } blk=blk->next; } if ((!gsl_finite(acc))||(acc<=0.0)) { sprintf(c->errcontext.tempErrStr, "Sum of sizes of all pie wedges is not a finite number."); ppl_error(&c->errcontext,ERR_GENERIC, -1, -1,NULL); x->current->plotdata[0]=NULL; acc=1; *(x->status) = 1; } if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Sum of sizes of all pie wedges = %e", acc); ppl_log(&c->errcontext,NULL); } pd->PieChart_total = acc; return; } void eps_pie_YieldUpText(EPSComm *x) { ppl_context *c = x->c; int j, Ncolumns, errCount=DATAFILE_NERRS; pplExpr *formatExpr; canvas_plotdesc *pd; dataBlock *blk; pplObj DummyTemp_l, DummyTemp_p, DummyTemp_w; pplObj *var_l , *var_p , *var_w; if ((pd=x->current->plotitems)==NULL) return; if (x->current->plotdata[0]==NULL) return; x->current->FirstTextID = x->NTextItems; // Work out what format string to use if (x->current->format!=NULL) { formatExpr = x->current->format; } else { char ascii[]="\"%.0f\\%% %s\"%(percentage,label)"; int end=0,ep=0,es=0; pplExpr *exptmp=NULL; ppl_expCompile(c,0,0,"",ascii,&end,1,0,0,&exptmp,&ep,&es,c->errcontext.tempErrStr); if (es || c->errStat.status) { ppl_tbClear(c); ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (E)"); *(x->status) = 1; return; } formatExpr = pplExpr_tmpcpy(exptmp); pplExpr_free(exptmp); if (formatExpr==NULL) { ppl_error(&c->errcontext,ERR_MEMORY, -1, -1,"Out of memory. (F)"); *(x->status) = 1; return; } } // Labels of pie wedges Ncolumns = x->current->plotdata[0]->Ncolumns_real; blk = x->current->plotdata[0]->first; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Set values of variables [percentage, label, wedgesize] for this wedge const int stkLevelOld = c->stackPtr; int lOp=0; char *tmp; pplObj *o; // Get pointers to the variables [percentage, label, wedgesize] ppl_contextGetVarPointer(c, "label" , &var_l, &DummyTemp_l); ppl_contextGetVarPointer(c, "percentage", &var_p, &DummyTemp_p); ppl_contextGetVarPointer(c, "wedgesize" , &var_w, &DummyTemp_w); pplObjStr(var_l,0,0,blk->text[j]); *var_w = x->current->plotdata[0]->firstEntries[0]; var_w->amMalloced = var_w->auxilMalloced = 0; var_w->real = blk->data_real[0 + Ncolumns*j]; pplObjNum(var_p,0,var_w->real / pd->PieChart_total * 100.0,0); o = ppl_expEval(c, formatExpr, &lOp, 1, x->iterDepth+1); if (c->errStat.status || (c->dollarStat.warntxt[0]!='\0') || (o==NULL)) { COUNTERR_BEGIN; char *errt = NULL; if (c->dollarStat.warntxt[0]!='\0') errt=c->dollarStat.warntxt; else if (c->errStat.errMsgExpr[0]!='\0') errt=c->errStat.errMsgExpr; else if (c->errStat.errMsgCmd [0]!='\0') errt=c->errStat.errMsgCmd; else errt="Fail occurred."; sprintf(c->errcontext.tempErrStr, "Error in format expression <%s>: %s", formatExpr->ascii, errt); ppl_warning(&c->errcontext,ERR_TYPE,c->errcontext.tempErrStr); COUNTERR_END; ppl_tbClear(c); tmp="?"; } else if (o->objType != PPLOBJ_STR) { COUNTERR_BEGIN; sprintf(c->errcontext.tempErrStr, "Format expression <%s> did not evaluate to a string, but to an object of type <%s>.", formatExpr->ascii, pplObjTypeNames[o->objType]); ppl_warning(&c->errcontext,ERR_TYPE,c->errcontext.tempErrStr); COUNTERR_END; tmp=NULL; } else { tmp = (char *)o->auxil; } if ((tmp==NULL)||(tmp[0]=='\0')) blk->text[j]=NULL; YIELD_TEXTITEM_CPY(tmp); // Restore values of the variables [percentage, label, wedgesize] ppl_contextRestoreVarPointer(c, "label" , &DummyTemp_l); ppl_contextRestoreVarPointer(c, "percentage", &DummyTemp_p); ppl_contextRestoreVarPointer(c, "wedgesize" , &DummyTemp_w); STACK_CLEAN; } blk=blk->next; } // Title of piechart x->current->TitleTextID = x->NTextItems; YIELD_TEXTITEM(x->current->settings.title); return; } void eps_pie_RenderEPS(EPSComm *x) { ppl_context *c = x->c; int j, Ncolumns, lt, WedgeNumber, l, m; double xpos,ypos,rad,angle,size,vtitle; canvas_plotdesc *pd; dataBlock *blk; double lw, lw_scale; withWords ww, ww_txt; if ((pd=x->current->plotitems)==NULL) return; if (x->current->plotdata[0]==NULL) return; x->LaTeXpageno = x->current->FirstTextID; // Print label at top of postscript description of box fprintf(x->epsbuffer, "%% Canvas item %d [piechart]\n", x->current->id); eps_core_clear(x); // Calculate position of centre of piechart, and its radius xpos = x->current->settings.OriginX.real * M_TO_PS; ypos = x->current->settings.OriginX.real * M_TO_PS; rad = x->current->settings.width .real * M_TO_PS / 2; vtitle = ypos+rad; // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Fill piechart segments Ncolumns = x->current->plotdata[0]->Ncolumns_real; blk = x->current->plotdata[0]->first; angle = 0.0; WedgeNumber = 0; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out what fillcolor to use for (l=0; lset->palette_current[l]==-1) break; // l now contains length of palette m = WedgeNumber % l; // m is now the palette color number to use while (m<0) m+=l; if (c->set->palette_current[m] > 0) { ww.fillcolor = c->set->palette_current[m]; ww.USEfillcolor = 1; ww.USEfillcolor1234 = 0; } else { ww.FillCol1234Space = c->set->paletteS_current[m]; ww.fillcolor1 = c->set->palette1_current[m]; ww.fillcolor2 = c->set->palette2_current[m]; ww.fillcolor3 = c->set->palette3_current[m]; ww.fillcolor4 = c->set->palette4_current[m]; ww.USEfillcolor = 0; ww.USEfillcolor1234 = 1; } // Work out size of wedge and fill it size = fabs(blk->data_real[0 + Ncolumns*j]) / pd->PieChart_total * 360.0; eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); IF_NOT_INVISIBLE fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f %.2f %.2f arc\n%.2f %.2f lineto\nclosepath\nfill\n",xpos,ypos,rad,90-angle-size,90-angle,xpos,ypos); angle += size; WedgeNumber++; } blk=blk->next; } // Set color of outline of piechart eps_core_SetColor(x, &ww, 1); // Set linewidth and linetype of outline if (ww.USElinewidth) lw_scale = ww.linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww.USElinetype) lt = ww.linetype; else lt = 1; IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); // Draw circumference of piechart IF_NOT_INVISIBLE fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f 0 360 arc\nclosepath\nstroke\n", xpos,ypos,rad); // Draw pie wedges one-by-one Ncolumns = x->current->plotdata[0]->Ncolumns_real; blk = x->current->plotdata[0]->first; angle = 0.0; while (blk != NULL) { for (j=0; jblockPosition; j++) { size = fabs(blk->data_real[0 + Ncolumns*j]) / pd->PieChart_total * 360.0; IF_NOT_INVISIBLE fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\nclosepath\nstroke\n",xpos,ypos,xpos+rad*sin(angle*M_PI/180),ypos+rad*cos(angle*M_PI/180)); angle += size; } blk=blk->next; } // Update bounding box eps_core_BoundingBox(x, xpos-rad, ypos-rad, lw); eps_core_BoundingBox(x, xpos+rad, ypos-rad, lw); eps_core_BoundingBox(x, xpos-rad, ypos+rad, lw); eps_core_BoundingBox(x, xpos+rad, ypos+rad, lw); // Write text on piechart ppl_withWordsZero(c, &ww_txt); if (x->current->settings.TextColor > 0) { ww_txt.color = x->current->settings.TextColor; ww_txt.USEcolor = 1; } else { ww_txt.Col1234Space = x->current->settings.TextCol1234Space; ww_txt.color1 = x->current->settings.TextColor1; ww_txt.color2 = x->current->settings.TextColor2; ww_txt.color3 = x->current->settings.TextColor3; ww_txt.color4 = x->current->settings.TextColor4; ww_txt.USEcolor1234 = 1; } eps_core_SetColor(x, &ww_txt, 1); IF_NOT_INVISIBLE { int ItemNo=0; double *TextWidth, *TextHeight, TotalHeight=0.0; double height1,height2,bb_top,bb_bottom,ab_left,ab_right,ab_top,ab_bottom; double label_rpos, best_label_rpos, best_label_margin, min_margin, key_vpos=0.0; postscriptPage *dviPage; // Calculate dimensions of text items TextWidth = (double *)ppl_memAlloc(x->current->plotdata[0]->Nrows * sizeof(double)); TextHeight = (double *)ppl_memAlloc(x->current->plotdata[0]->Nrows * sizeof(double)); if ((TextWidth==NULL)||(TextHeight==NULL)) goto END_LABEL_PRINTING; blk = x->current->plotdata[0]->first; while (blk != NULL) { for (j=0; jblockPosition; j++) { dviPage = (postscriptPage *)ppl_listGetItem(x->dvi->output->pages, x->LaTeXpageno+ItemNo); if (dviPage== NULL) { ItemNo++; continue; } // Such doom will trigger errors later //bb_left = dviPage->boundingBox[0]; bb_bottom = dviPage->boundingBox[1]; //bb_right= dviPage->boundingBox[2]; bb_top = dviPage->boundingBox[3]; ab_left = dviPage->textSizeBox[0]; ab_bottom = dviPage->textSizeBox[1]; ab_right = dviPage->textSizeBox[2]; ab_top = dviPage->textSizeBox[3]; height1 = fabs(ab_top - ab_bottom) * AB_ENLARGE_FACTOR; height2 = fabs(bb_top - bb_bottom) * BB_ENLARGE_FACTOR; TextWidth [ItemNo] = ((ab_right - ab_left) + MARGIN_HSIZE ) * x->current->settings.FontSize; TextHeight[ItemNo] = ((height2current->settings.FontSize; TotalHeight += TextHeight[ItemNo]; ItemNo++; } blk=blk->next; } // Labels of pie wedges Ncolumns = x->current->plotdata[0]->Ncolumns_real; blk = x->current->plotdata[0]->first; angle = 0.0; ItemNo = 0; while (blk != NULL) { for (j=0; jblockPosition; j++) { size = fabs(blk->data_real[0 + Ncolumns*j]) / pd->PieChart_total * 2 * M_PI; // Angular size of wedge if (blk->text[j]!=NULL) { int ArrowType; double a = angle+size/2; // Central angle of wedge // Test different radii where label can be placed best_label_rpos = 0.7; best_label_margin = -1e10; for (label_rpos=0.7; label_rpos>=0.3; label_rpos-=0.05) { double r,theta,t; min_margin = 1e10; #define CHECK_POSITION(X,Y) \ r = hypot(X,Y); \ theta = fmod(atan2(X,Y) - a, 2*M_PI); if (theta<-M_PI) theta+=2*M_PI; if (theta>M_PI) theta-=2*M_PI; \ t = theta + size/2; \ if (t < min_margin) min_margin = t; \ t = size/2 - theta; \ if (t < min_margin) min_margin = t; \ t = r / rad; \ if (t < min_margin) min_margin = t; \ t = (rad-r) / rad; \ if (t < min_margin) min_margin = t; \ CHECK_POSITION( rad*sin(a)*label_rpos-TextWidth[ItemNo]/2 , rad*cos(a)*label_rpos-TextHeight[ItemNo]/2 ); CHECK_POSITION( rad*sin(a)*label_rpos-TextWidth[ItemNo]/2 , rad*cos(a)*label_rpos+TextHeight[ItemNo]/2 ); CHECK_POSITION( rad*sin(a)*label_rpos+TextWidth[ItemNo]/2 , rad*cos(a)*label_rpos-TextHeight[ItemNo]/2 ); CHECK_POSITION( rad*sin(a)*label_rpos+TextWidth[ItemNo]/2 , rad*cos(a)*label_rpos+TextHeight[ItemNo]/2 ); if (min_margin>best_label_margin) { best_label_margin = min_margin; best_label_rpos = label_rpos; } } // Work out whether label will go inside, outside or in a key ArrowType = x->current->ArrowType; if (ArrowType==SW_PIEKEYPOS_AUTO) ArrowType = (best_label_margin<0.0) ? SW_PIEKEYPOS_OUTSIDE : SW_PIEKEYPOS_INSIDE; if (ArrowType==SW_PIEKEYPOS_INSIDE) { // Labelling pie wedges inside pie int pageno = x->LaTeXpageno++; eps_core_SetColor(x, &ww_txt, 1); canvas_EPSRenderTextItem(x, NULL, pageno, (xpos+rad*sin(a)*best_label_rpos)/M_TO_PS, (ypos+rad*cos(a)*best_label_rpos)/M_TO_PS, SW_HALIGN_CENT, SW_VALIGN_CENT, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } else if (ArrowType==SW_PIEKEYPOS_OUTSIDE) { // Labelling pie wedges around edge of pie int hal, val, pageno = x->LaTeXpageno++; double vtop; if (a < 5*M_PI/180) { hal=SW_HALIGN_CENT ; val=SW_VALIGN_BOT; } else if (a < 30*M_PI/180) { hal=SW_HALIGN_LEFT ; val=SW_VALIGN_BOT; } else if (a < 150*M_PI/180) { hal=SW_HALIGN_LEFT ; val=SW_VALIGN_CENT; } else if (a < 175*M_PI/180) { hal=SW_HALIGN_LEFT ; val=SW_VALIGN_TOP; } else if (a < 185*M_PI/180) { hal=SW_HALIGN_CENT ; val=SW_VALIGN_TOP; } else if (a < 210*M_PI/180) { hal=SW_HALIGN_RIGHT; val=SW_VALIGN_TOP; } else if (a < 330*M_PI/180) { hal=SW_HALIGN_RIGHT; val=SW_VALIGN_CENT; } else if (a < 355*M_PI/180) { hal=SW_HALIGN_RIGHT; val=SW_VALIGN_BOT; } else { hal=SW_HALIGN_CENT ; val=SW_VALIGN_BOT; } if (val == SW_VALIGN_BOT ) vtop = ypos+rad*cos(a)*1.08 + TextHeight[ItemNo]; else if (val == SW_VALIGN_CENT) vtop = ypos+rad*cos(a)*1.08 + TextHeight[ItemNo]/2; else vtop = ypos+rad*cos(a)*1.08; if (vtop > vtitle) vtitle=vtop; eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\nclosepath\nstroke\n",xpos+rad*sin(a),ypos+rad*cos(a),xpos+rad*sin(a)*1.05,ypos+rad*cos(a)*1.05); eps_core_SetColor(x, &ww_txt, 1); canvas_EPSRenderTextItem(x, NULL, pageno, (xpos+rad*sin(a)*1.08)/M_TO_PS, (ypos+rad*cos(a)*1.08)/M_TO_PS, hal, val, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } else // Labelling pie wedges in a key { int pageno = x->LaTeXpageno++; double h = xpos + rad*1.2; // Position of left of key double v = ypos + TotalHeight/2 - key_vpos - TextHeight[ItemNo]/2; // Vertical position of centre of key item double s = MARGIN_HSIZE_LEFT*0.45/3; // Controls size of filled square which appears next to wedge label double st= MARGIN_HSIZE_LEFT*0.67; // Work out what fillcolor to use for (l=0; lset->palette_current[l]==-1) break; // l now contains length of palette m = ItemNo % l; // m is now the palette color number to use while (m<0) m+=l; if (c->set->palette_current[m] > 0) { ww.fillcolor = c->set->palette_current[m]; ww.USEfillcolor = 1; ww.USEfillcolor1234 = 0; } else { ww.FillCol1234Space = c->set->paletteS_current[m]; ww.fillcolor1 = c->set->palette1_current[m]; ww.fillcolor2 = c->set->palette2_current[m]; ww.fillcolor3 = c->set->palette3_current[m]; ww.fillcolor4 = c->set->palette4_current[m]; ww.USEfillcolor = 0; ww.USEfillcolor1234 = 1; } // Fill icon eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath fill\n", h, v-s, h, v+s, h+2*s, v+s, h+2*s, v-s); eps_core_BoundingBox(x, h , v-s, 0); eps_core_BoundingBox(x, h , v+s, 0); eps_core_BoundingBox(x, h+2*s, v-s, 0); eps_core_BoundingBox(x, h+2*s, v+s, 0); } // Stroke icon eps_core_SetColor(x, &ww, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * ww.linewidth, ww.USElinetype ? ww.linetype : 1, 0); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath stroke\n", h, v-s, h, v+s, h+2*s, v+s, h+2*s, v-s); eps_core_BoundingBox(x, h , v-s, ww.linewidth); eps_core_BoundingBox(x, h , v+s, ww.linewidth); eps_core_BoundingBox(x, h+2*s, v-s, ww.linewidth); eps_core_BoundingBox(x, h+2*s, v+s, ww.linewidth); } // Write text next to icon eps_core_SetColor(x, &ww_txt, 1); canvas_EPSRenderTextItem(x, NULL, pageno, (h+st)/M_TO_PS, v/M_TO_PS, SW_HALIGN_LEFT, SW_VALIGN_CENT, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); key_vpos += TextHeight[ItemNo]; } } angle += size; ItemNo++; } blk=blk->next; } END_LABEL_PRINTING: // Title of piechart x->LaTeXpageno = x->current->TitleTextID; if ((x->current->settings.title != NULL) && (x->current->settings.title[0] != '\0')) { int pageno = x->LaTeXpageno++; canvas_EPSRenderTextItem(x, NULL, pageno, xpos/M_TO_PS, (vtitle+8)/M_TO_PS, SW_HALIGN_CENT, SW_VALIGN_BOT, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } } // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_contourmap.h0000664000175000017500000000236312026340554020433 0ustar dcf21dcf21// eps_plot_contourmap.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_contourmap.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_CONTOURMAP_H #define _PPL_EPS_PLOT_CONTOURMAP_H 1 #include "settings/settings.h" void eps_plot_contourmap_YieldText(EPSComm *x, dataTable *data, pplset_graph *sg, canvas_plotdesc *pd); int eps_plot_contourmap(EPSComm *x, dataTable *data, unsigned char ThreeDim, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, int pdn, double origin_x, double origin_y, double width, double height, double zdepth); #endif pyxplot-0.9.2/src/epsMaker/eps_settings.c0000664000175000017500000000374312026340554017044 0ustar dcf21dcf21// eps_settings.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_settings.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains various numerical constants which are used by the eps // generation routines #define _PPL_EPS_SETTINGS_C 1 #include #include #include "epsMaker/eps_settings.h" // Constant to convert between millimetres and 72nds of an inch double M_TO_PS = 1.0 / (GSL_CONST_MKSA_INCH / 72.0); double EPS_DEFAULT_LINEWIDTH = 1.0 * EPS_BASE_DEFAULT_LINEWIDTH; double EPS_DEFAULT_PS = 1.0 * EPS_BASE_DEFAULT_PS; double EPS_ARROW_ANGLE = 1.0 * EPS_BASE_ARROW_ANGLE; double EPS_ARROW_CONSTRICT = 1.0 * EPS_BASE_ARROW_CONSTRICT; double EPS_ARROW_HEADSIZE = 1.0 * EPS_BASE_ARROW_HEADSIZE; double EPS_AXES_LINEWIDTH = 1.0 * EPS_BASE_AXES_LINEWIDTH; double EPS_AXES_MAJTICKLEN = 1.0 * EPS_BASE_AXES_MAJTICKLEN; double EPS_AXES_MINTICKLEN = 1.0 * EPS_BASE_AXES_MINTICKLEN; double EPS_AXES_SEPARATION = 1.0 * EPS_BASE_AXES_SEPARATION; double EPS_AXES_TEXTGAP = 1.0 * EPS_BASE_AXES_TEXTGAP; double EPS_COLORSCALE_MARGIN = 1.0 * EPS_BASE_COLORSCALE_MARG; double EPS_COLORSCALE_WIDTH = 1.0 * EPS_BASE_COLORSCALE_WIDTH; double EPS_GRID_MAJLINEWIDTH = 1.0 * EPS_BASE_GRID_MAJLINEWIDTH; double EPS_GRID_MINLINEWIDTH = 1.0 * EPS_BASE_GRID_MINLINEWIDTH; pyxplot-0.9.2/src/epsMaker/eps_plot_linkedaxes.h0000664000175000017500000000243312026340554020371 0ustar dcf21dcf21// eps_plot_linkedaxes.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_linkedaxes.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_LINKEDAXES_H #define _PPL_EPS_PLOT_LINKEDAXES_H 1 #include "settings/settings.h" #include "epsMaker/eps_comm.h" void eps_plot_LinkedAxisBackPropagate(EPSComm *x, pplset_axis *source); int eps_plot_LinkedAxisLinkUsing(EPSComm *x, pplset_axis *out, pplset_axis *in); void eps_plot_LinkedAxisForwardPropagate(EPSComm *x, pplset_axis *axis, int mode); void eps_plot_LinkUsingBackPropagate(EPSComm *x, double val, pplset_axis *target, pplset_axis *source); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_colormap.c0000664000175000017500000007644412026340554020066 0ustar dcf21dcf21// eps_plot_colormap.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_colormap.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_COLORMAP_C 1 #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "canvasItems.h" #include "coreUtils/errorReport.h" #include "expressions/traceback_fns.h" #include "expressions/expEval.h" #include "settings/colors.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" #include "userspace/pplObj_fns.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/bmp_a85.h" #include "epsMaker/bmp_optimise.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "settings/epsColors.h" #include "epsMaker/eps_image.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_axespaint.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_colormap.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_settings.h" #include "epsMaker/eps_style.h" // Random shade of purple to use as mask color #define TRANS_R 35 #define TRANS_G 2 #define TRANS_B 20 #define CLIP_COMPS \ comp[0] = (comp[0] < 0.0) ? 0.0 : ((comp[0]>1.0) ? 1.0 : comp[0] ); \ comp[1] = (comp[1] < 0.0) ? 0.0 : ((comp[1]>1.0) ? 1.0 : comp[1] ); \ comp[2] = (comp[2] < 0.0) ? 0.0 : ((comp[2]>1.0) ? 1.0 : comp[2] ); \ comp[3] = (comp[3] < 0.0) ? 0.0 : ((comp[3]>1.0) ? 1.0 : comp[3] ); // Yield up text items which label color scale of a colormap void eps_plot_colormap_YieldText(EPSComm *x, dataTable *data, pplset_graph *sg, canvas_plotdesc *pd) { dataBlock *blk; int XSize = pd->GridXSize; int YSize = pd->GridYSize; int i, j, k, l, Ncol; double CMin, CMax, PhysicalLength, PhysicalLengthMajor, PhysicalLengthMinor; double origin_x, origin_y, width, height, zdepth; double xmin, xmax, ymin, ymax; unsigned char CMinAuto, CMinSet, CMaxAuto, CMaxSet, CLog, horizontal; // Check that we have some data if ((data==NULL) || (data->Nrows<1)) return; // No data present Ncol = data->Ncolumns_real; blk = data->first; // Calculate positions of the four corners of graph origin_x = x->current->settings.OriginX.real * M_TO_PS; origin_y = x->current->settings.OriginY.real * M_TO_PS; width = x->current->settings.width .real * M_TO_PS; if (x->current->settings.AutoAspect == SW_ONOFF_ON) height = width * 2.0/(1.0+sqrt(5)); else height = width * x->current->settings.aspect; if (x->current->settings.AutoZAspect == SW_ONOFF_ON) zdepth = width * 2.0/(1.0+sqrt(5)); else zdepth = width * x->current->settings.zaspect; // Work out normalisation of variable c1 CMinAuto = (sg->Cminauto[0]==SW_BOOL_TRUE); CMinSet = !CMinAuto; CMin = sg->Cmin[0].real; CMaxAuto = (sg->Cmaxauto[0]==SW_BOOL_TRUE); CMaxSet = !CMaxAuto; CMax = sg->Cmax[0].real; CLog = (sg->Clog[0]==SW_BOOL_TRUE); // Find extremal values if (CMinAuto || CMaxAuto) for (j=0; jdata_real[2 + Ncol*(i+XSize*j)]; if (!gsl_finite(val)) continue; if ((CMinAuto) && ((!CMinSet) || (CMin>val)) && ((!CLog)||(val>0.0))) { CMin=val; CMinSet=1; } if ((CMaxAuto) && ((!CMaxSet) || (CMax0.0))) { CMax=val; CMaxSet=1; } } // If no data present, stop now if ((!CMinSet)||(!CMaxSet)) return; // If log spacing, make sure range is strictly positive if (CLog && (CMin<1e-200)) CMin=1e-200; if (CLog && (CMax<1e-200)) CMax=1e-200; // Estimate length of color key if (!x->current->ThreeDim) { xmin = origin_x; xmax = origin_x + width; ymin = origin_y; ymax = origin_y + height; } else { xmin = xmax = origin_x; ymin = ymax = origin_y; for (k=0; k<8; k++) { double x0,y0,z0; eps_plot_ThreeDimProject((k&1),(k&2)!=0,(k&4)!=0,sg,origin_x,origin_y,width,height,zdepth,&x0,&y0,&z0); if (x0xmax) xmax=x0; if (y0ymax) ymax=y0; } } horizontal = ((sg->ColKeyPos==SW_COLKEYPOS_T)||(sg->ColKeyPos==SW_COLKEYPOS_B)); PhysicalLength = fabs( horizontal ? (xmax-xmin) : (ymax-ymin) ) / M_TO_PS; PhysicalLengthMinor = PhysicalLength / 0.004; PhysicalLengthMajor = PhysicalLength / (horizontal ? 0.025 : 0.015); // Set up axis object pd->C1Axis = x->c->set->axis_default; pd->C1Axis.label = sg->c1label; pd->C1Axis.LabelRotate = sg->c1LabelRotate; pd->C1Axis.format = sg->c1formatset ? sg->c1format : NULL; pd->C1Axis.tics = sg->ticsC; pd->C1Axis.ticsM = sg->ticsCM; pd->C1Axis.TickLabelRotation = sg->c1TickLabelRotation; pd->C1Axis.TickLabelRotate = sg->c1TickLabelRotate; pd->C1Axis.enabled = pd->C1Axis.FinalActive = pd->C1Axis.RangeFinalised = 1; pd->C1Axis.TickListFinalised = 0; pd->C1Axis.topbottom = (sg->ColKeyPos==SW_COLKEYPOS_T)||(sg->ColKeyPos==SW_COLKEYPOS_R); pd->C1Axis.log = pd->C1Axis.LogFinal = CLog ? SW_BOOL_TRUE : SW_BOOL_FALSE; pd->C1Axis.MinSet = pd->C1Axis.MaxSet = SW_BOOL_TRUE; pd->C1Axis.HardMinSet = pd->C1Axis.HardMaxSet = 1; pd->C1Axis.min = pd->C1Axis.MinFinal = pd->C1Axis.HardMin = CMin; pd->C1Axis.max = pd->C1Axis.MaxFinal = pd->C1Axis.HardMax = CMax; pd->C1Axis.DataUnitSet = pd->C1Axis.HardUnitSet = 1; pd->C1Axis.DataUnit = pd->C1Axis.HardUnit = pd->C1Axis.unit = data->firstEntries[2]; pd->C1Axis.AxisValueTurnings = 0; pd->C1Axis.AxisLinearInterpolation = NULL; pd->C1Axis.CrossedAtZero = 0; pd->C1Axis.MinUsedSet = pd->C1Axis.MaxUsedSet = 0; pd->C1Axis.MinUsed = pd->C1Axis.MaxUsed = 0.0; pd->C1Axis.HardAutoMinSet = pd->C1Axis.HardAutoMaxSet = 0; pd->C1Axis.Mode0BackPropagated = 0; pd->C1Axis.OrdinateRasterLen = 0; pd->C1Axis.OrdinateRaster = NULL; pd->C1Axis.FinalAxisLabel = NULL; pd->C1Axis.PhysicalLengthMajor = PhysicalLengthMajor; pd->C1Axis.PhysicalLengthMinor = PhysicalLengthMinor; pd->C1Axis.xyz = 3; pd->C1Axis.axis_n = 1; pd->C1Axis.canvas_id = x->current->id; // Make tick labels along this axis eps_plot_ticking(x, &pd->C1Axis, SW_AXISUNITSTY_RATIO, NULL); // Submit axis labels for color key pd->C1Axis.FirstTextID = x->NTextItems; if (pd->C1Axis.TickListStrings!=NULL) for (l=0; pd->C1Axis.TickListStrings[l]!=NULL; l++) { YIELD_TEXTITEM(pd->C1Axis.TickListStrings[l]); } YIELD_TEXTITEM(pd->C1Axis.FinalAxisLabel); // If we have three columns of data, consider drawing a color scale bar if ((Ncol==3)&&(sg->ColKey==SW_ONOFF_ON)) { pd->CRangeDisplay = 1; pd->CMinFinal = CMin; pd->CMaxFinal = CMax; pd->CRangeUnit = data->firstEntries[2]; } return; } // Render a colormap to postscript int eps_plot_colormap(EPSComm *x, dataTable *data, unsigned char ThreeDim, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, int pdn, double origin_x, double origin_y, double width, double height, double zdepth) { double scale_x, scale_y, scale_z; dataBlock *blk; int XSize = pd->GridXSize; int YSize = pd->GridYSize; int i, j, c, cmax, Ncol_real, Ncol_obj, NcolsData; long p; double xo, yo, Lx, Ly, ThetaX, ThetaY, CMin[4], CMax[4]; pplObj *CVar[4], *C1Var, CDummy[4]; uLongf zlen; // Length of buffer passed to zlib unsigned char *imagez, CMinAuto[4], CMinSet[4], CMaxAuto[4], CMaxSet[4], CLog[4]; char *errtext; unsigned char component_r, component_g, component_b, transparent[3] = {TRANS_R, TRANS_G, TRANS_B}; bitmap_data img; if ((data==NULL) || (data->Nrows<1)) return 0; // No data present Ncol_real = data->Ncolumns_real; Ncol_obj = data->Ncolumns_obj; if (eps_plot_WithWordsCheckUsingItemsDimLess(x->c, &pd->ww_final, data->firstEntries, Ncol_real, Ncol_obj, &NcolsData)) return 1; if (!ThreeDim) { scale_x=width; scale_y=height; scale_z=1.0; } else { scale_x=width; scale_y=height; scale_z=zdepth; } blk = data->first; errtext = ppl_memAlloc(LSTR_LENGTH); if (errtext==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY,-1,-1,"Out of memory (k)."); return 1; } // Work out orientation of colormap if (!ThreeDim) { xo = origin_x; yo = origin_y; Lx = scale_x; Ly = scale_y; ThetaX = M_PI/2; ThetaY = 0.0; if (xn!=0) { double t1=Lx, t2=ThetaX; Lx=Ly; ThetaX=ThetaY; Ly=t1; ThetaY=t2; } } else // 3D case: put color map on back face of cuboid { double ap[3]={0.5,0.5,0.0}, xtmp, ytmp, z0tmp, z1tmp; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); ap[2]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z1tmp); ap[2]=(z1tmp>z0tmp)?1.0:0.0; // Determine whether zap=0 or zap=1 represents back of cuboid ap[0]=ap[1]=0.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xo, &yo, &z0tmp); ap[0]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); Lx = hypot(xtmp-xo, ytmp-yo); ThetaX = atan2(xtmp-xo, ytmp-yo); if (!gsl_finite(ThetaX)) ThetaX = 0.0; ap[0]=0.0; ap[1]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); Ly = hypot(xtmp-xo, ytmp-yo); ThetaY = atan2(xtmp-xo, ytmp-yo); if (!gsl_finite(ThetaY)) ThetaY = 0.0; } // Update bounding box eps_core_BoundingBox(x, xo , yo , 0); eps_core_BoundingBox(x, xo + Lx*sin(ThetaX) , yo + Lx*cos(ThetaX) , 0); eps_core_BoundingBox(x, xo + Ly*sin(ThetaY) , yo + Ly*cos(ThetaY) , 0); eps_core_BoundingBox(x, xo + Lx*sin(ThetaX) + Ly*sin(ThetaY) , yo + Lx*cos(ThetaX) + Ly*cos(ThetaY) , 0); // Populate bitmap image decriptor img.type = BMP_COLOUR_BMP; img.colour = BMP_COLOUR_RGB; img.pal_len = 0; img.palette = NULL; img.trans = transparent; img.height = YSize; img.width = XSize; img.depth = 24; img.data_len = 3*XSize*YSize; img.TargetCompression = BMP_ENCODING_FLATE; BMP_ALLOC(img.data , 3*XSize*YSize); if (img.data==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (l)."); return 1; } // Get pointer to variable c in the user's variable space for (i=0; i<4; i++) { char v[3]={'c','1'+i,'\0'}; ppl_contextGetVarPointer(x->c, v, CVar+i, CDummy+i); if ((iCrenorm[i]==SW_BOOL_FALSE)) { *CVar[i] = data->firstEntries[i+2]; CVar[i]->flagComplex=0; CVar[i]->imag=0.0; } else pplObjNum(CVar[i],0,0,0); // c1...c4 are dimensionless numbers in range 0-1, regardless of units of input data } // Work out normalisation of variables c1...c4 for (c=0; ((c<4)&&(cCminauto[c]==SW_BOOL_TRUE); CMinSet [c] = !CMinAuto[c]; CMin [c] = sg->Cmin[c].real; CMaxAuto[c] = (sg->Cmaxauto[c]==SW_BOOL_TRUE); CMaxSet [c] = !CMaxAuto[c]; CMax [c] = sg->Cmax[c].real; CLog [c] = (sg->Clog[c]==SW_BOOL_TRUE); // Find extremal values if (CMinAuto[c] || CMaxAuto[c]) for (j=0; jdata_real[c+2 + Ncol_real*(i+XSize*j)]; if (!gsl_finite(val)) continue; if ((CMinAuto[c]) && ((!CMinSet[c]) || (CMin[c]>val)) && ((!CLog[c])||(val>0.0))) { CMin[c]=val; CMinSet[c]=1; } if ((CMaxAuto[c]) && ((!CMaxSet[c]) || (CMax[c]0.0))) { CMax[c]=val; CMaxSet[c]=1; } } // If log spacing, make sure range is strictly positive if (CLog[c] && (CMin[c]<1e-200)) CMin[c]=1e-200; if (CLog[c] && (CMax[c]<1e-200)) CMax[c]=1e-200; // Reverse range of color scale if requested if (sg->Creverse[c]==SW_BOOL_TRUE) { double td=CMin[c]; unsigned char tc=CMinSet[c], tc2=CMinAuto[c]; CMinAuto[c] = CMaxAuto[c]; CMinSet [c] = CMaxSet [c]; CMin [c] = CMax [c]; CMaxAuto[c] = tc2; CMaxSet [c] = tc; CMax [c] = td; } // If no data present, stop now if ((!CMinSet[c])||(!CMaxSet[c])) { sprintf(x->c->errcontext.tempErrStr, "No data supplied to determine range for variable c%d", c+1); ppl_log(&x->c->errcontext,NULL); for (i=0; i<4; i++) { char v[3]={'c','1'+i,'\0'}; ppl_contextRestoreVarPointer(x->c, v, CDummy+i); } return 0; } // Output result to debugging output if (DEBUG) { int SF = x->c->set->term_current.SignificantFigures; sprintf(x->c->errcontext.tempErrStr, "Range for variable c%d is [%s:%s]", c+1, ppl_numericDisplay(CMin[c],x->c->numdispBuff[0],SF,0), ppl_numericDisplay(CMax[c],x->c->numdispBuff[1],SF,0)); ppl_log(&x->c->errcontext,NULL); } } cmax = c-1; // Check that variables c1...c4 has appropriate units for (c=0; c<=cmax; c++) if ( ((!CMinAuto[c])||(!CMaxAuto[c])) && (!ppl_unitsDimEqual(CVar[c] , (sg->Cminauto[c]==SW_BOOL_TRUE)?(&sg->Cmax[c]):(&sg->Cmin[c]))) ) { sprintf(x->c->errcontext.tempErrStr, "Column %d of data supplied to the colormap plot style has conflicting units with those set in the 'set crange' command. The former has units of <%s> whilst the latter has units of <%s>.", c+3, ppl_printUnit(x->c,CVar[c], NULL, NULL, 0, 1, 0), ppl_printUnit(x->c,(sg->Cminauto[c]==SW_BOOL_TRUE)?(&sg->Cmax[c]):(&sg->Cmin[c]), NULL, NULL, 1, 1, 0)); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); return 1; } // Populate bitmap data array for (p=0, j=YSize-1; j>=0; j--) // Postscript images are top-first. Data block is bottom-first. for (i=0; icmax) /* No c */ { *CVar[c] = CDummy[c]; } else if (sg->Crenorm[c]==SW_BOOL_FALSE) { CVar[c]->real = blk->data_real[c+2 + Ncol_real*(i+XSize*j)]; } // No renormalisation else if (CMax[c]==CMin[c]) /* Ooops */ { CVar[c]->real = (gsl_finite(blk->data_real[c+2 + Ncol_real*(i+XSize*j)]))?0.5:(GSL_NAN); } else if (!CLog[c]) /* Linear */ { CVar[c]->real = (blk->data_real[c+2 + Ncol_real*(i+XSize*j)] - CMin[c]) / (CMax[c] - CMin[c]); } else /* Logarithmic */ { CVar[c]->real = log(blk->data_real[c+2 + Ncol_real*(i+XSize*j)] / CMin[c]) / log(CMax[c] / CMin[c]); } #define SET_RGB_COLOR \ /* Check if mask criterion is satisfied */ \ { \ int colspace; \ double comp[4]={0,0,0,0}; \ const int stkLevelOld = x->c->stackPtr; \ if (sg->MaskExpr!=NULL) \ { \ pplObj *v; \ int lOP; \ v = ppl_expEval(x->c, (pplExpr *)sg->MaskExpr, &lOP, 1, x->iterDepth+1); \ if (x->c->errStat.status) { sprintf(x->c->errcontext.tempErrStr, "Could not evaluate mask expression <%s>.", ((pplExpr *)sg->MaskExpr)->ascii); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); ppl_tbWrite(x->c); ppl_tbClear(x->c); return 1; } \ if (v->real==0) { component_r = TRANS_R; component_g = TRANS_G; component_b = TRANS_B; goto write_rgb; } \ } \ \ /* Compute RGB, HSB or CMYK components */ \ if (sg->ColMapExpr == NULL) \ { \ colspace = SW_COLSPACE_RGB; \ comp[0] = comp[1] = comp[2] = C1Var->real; \ } \ else \ { \ pplObj *v; \ int lOP, outcol; \ unsigned char d1, d2; \ v = ppl_expEval(x->c, (pplExpr *)sg->ColMapExpr, &lOP, 1, x->iterDepth+1); \ if (x->c->errStat.status) { sprintf(x->c->errcontext.tempErrStr, "Could not evaluate color expression <%s>.", ((pplExpr *)sg->ColMapExpr)->ascii); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); ppl_tbWrite(x->c); ppl_tbClear(x->c); return 1; } \ lOP = ppl_colorFromObj(x->c, v, &outcol, &colspace, NULL, comp, comp+1, comp+2, comp+3, &d1, &d2); \ if (lOP) { ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); return 1; } \ if (outcol!=0) \ { \ colspace = SW_COLSPACE_CMYK; \ comp[0] = *(double *)ppl_fetchSettingName(&x->c->errcontext, outcol, SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)); \ comp[1] = *(double *)ppl_fetchSettingName(&x->c->errcontext, outcol, SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)); \ comp[2] = *(double *)ppl_fetchSettingName(&x->c->errcontext, outcol, SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)); \ comp[3] = *(double *)ppl_fetchSettingName(&x->c->errcontext, outcol, SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)); \ } \ if ((!gsl_finite(comp[0]))||(!gsl_finite(comp[1]))||(!gsl_finite(comp[2]))||(!gsl_finite(comp[3]))) \ { component_r = TRANS_R; component_g = TRANS_G; component_b = TRANS_B; goto write_rgb; } \ } \ \ /* Convert to RGB */ \ switch (colspace) \ { \ case SW_COLSPACE_RGB: /* Convert RGB --> RGB */ \ break; \ case SW_COLSPACE_HSB: /* Convert HSB --> RGB */ \ { \ double h2, ch, x, m; int h2i; \ CLIP_COMPS; \ ch = comp[1]*comp[2]; \ h2i = (int)(h2 = comp[0] * 6); \ x = ch*(1.0-fabs(fmod(h2,2)-1.0)); \ m = comp[2] - ch; \ switch (h2i) \ { \ case 0 : comp[0]=ch; comp[1]=x ; comp[2]=0 ; break; \ case 1 : comp[0]=x ; comp[1]=ch; comp[2]=0 ; break; \ case 2 : comp[0]=0 ; comp[1]=ch; comp[2]=x ; break; \ case 3 : comp[0]=0 ; comp[1]=x ; comp[2]=ch; break; \ case 4 : comp[0]=x ; comp[1]=0 ; comp[2]=ch; break; \ case 5 : \ case 6 : comp[0]=ch; comp[1]=0 ; comp[2]=x ; break; /* case 6 is for hue=1.0 only */ \ default: comp[0]=0 ; comp[1]=0 ; comp[2]=0 ; break; \ } \ comp[0]+=m; comp[1]+=m; comp[2]+=m; \ break; \ } \ case SW_COLSPACE_CMYK: /* Convert CMYK --> RGB */ \ comp[0] = 1.0 - (comp[0]+comp[3]); \ comp[1] = 1.0 - (comp[1]+comp[3]); \ comp[2] = 1.0 - (comp[2]+comp[3]); \ break; \ default: /* Unknown color space */ \ comp[0] = comp[1] = comp[2] = 0.0; \ break; \ } \ CLIP_COMPS; \ \ /* Store RGB components */ \ component_r = (unsigned char)floor(comp[0] * 255.99); \ component_g = (unsigned char)floor(comp[1] * 255.99); \ component_b = (unsigned char)floor(comp[2] * 255.99); \ if ((component_r==TRANS_R)&&(component_g==TRANS_G)&&(component_b==TRANS_B)) component_b++; \ \ write_rgb: \ img.data[p++] = component_r; \ img.data[p++] = component_g; \ img.data[p++] = component_b; \ EPS_STACK_POP; \ } C1Var = CVar[0]; SET_RGB_COLOR; } // Restore variables c1...c4 in the user's variable space for (i=0; i<4; i++) { char v[3]={'c','1'+i,'\0'}; ppl_contextRestoreVarPointer(x->c, v, CDummy+i); } #define COMPRESS_POSTSCRIPT_IMAGE \ /* Consider converting RGB data into a paletted image */ \ if ((img.depth == 24) && (img.type==BMP_COLOUR_BMP )) ppl_bmp_colour_count(&x->c->errcontext,&img); /* Check full color image to ensure more than 256 colors */ \ if ((img.depth == 8) && (img.type==BMP_COLOUR_PALETTE)) ppl_bmp_grey_check(&x->c->errcontext,&img); /* Check paletted images for greyscale conversion */ \ if ((img.type == BMP_COLOUR_PALETTE) && (img.pal_len <= 16) && (img.depth == 8)) ppl_bmp_compact(&x->c->errcontext,&img); /* Compact images with few palette entries */ \ \ /* Apply compression to image data */ \ switch (img.TargetCompression) \ { \ case BMP_ENCODING_FLATE: \ zlen = img.data_len*1.01+12; /* Nasty guess at size of buffer needed. */ \ imagez = (unsigned char *)ppl_memAlloc(zlen); \ if (imagez == NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (m)."); img.TargetCompression = BMP_ENCODING_NULL; break; } \ if (DEBUG) { ppl_log(&x->c->errcontext,"Calling zlib to compress image data."); } \ j = compress2(imagez,&zlen,img.data,img.data_len,9); /* Call zlib to do deflation */ \ \ if (j!=0) \ { \ if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "zlib returned error code %d\n",j); ppl_log(&x->c->errcontext,NULL); } \ img.TargetCompression = BMP_ENCODING_NULL; /* Give up trying to compress data */ \ break; \ } \ if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "zlib has completed compression. Before flate: %ld bytes. After flate: %ld bytes.", img.data_len, (long)zlen); ppl_log(&x->c->errcontext,NULL); } \ if (zlen >= img.data_len) \ { \ if (DEBUG) { ppl_log(&x->c->errcontext,"Using original uncompressed data since zlib made it bigger than it was to start with."); } \ img.TargetCompression = BMP_ENCODING_NULL; /* Give up trying to compress data; result was larger than original data size */ \ break; \ } \ img.data = imagez; /* Replace old data with new compressed data */ \ img.data_len = zlen; \ break; \ } \ #ifdef FLATE_DISABLE if (img.TargetCompression==BMP_ENCODING_FLATE) img.TargetCompression=BMP_ENCODING_NULL; #endif COMPRESS_POSTSCRIPT_IMAGE; // Write out postscript image fprintf(x->epsbuffer, "gsave\n"); fprintf(x->epsbuffer, "[ %.2f %.2f %.2f %.2f %.2f %.2f ] concat\n", Lx*sin(ThetaX), Lx*cos(ThetaX), Ly*sin(ThetaY), Ly*cos(ThetaY), xo, yo); #define WRITE_POSTSCRIPT_IMAGE \ if (img.colour == BMP_COLOUR_RGB ) fprintf(x->epsbuffer, "/DeviceRGB setcolorspace\n"); /* RGB palette */ \ else if (img.colour == BMP_COLOUR_GREY) fprintf(x->epsbuffer, "/DeviceGray setcolorspace\n"); /* Greyscale palette */ \ else if (img.colour == BMP_COLOUR_PALETTE) /* Indexed palette */ \ { \ fprintf(x->epsbuffer, "[/Indexed /DeviceRGB %d <~\n", img.pal_len-1); \ ppl_bmp_A85(&x->c->errcontext, x->epsbuffer, img.palette, 3*img.pal_len); \ fprintf(x->epsbuffer, "] setcolorspace\n\n"); \ } \ \ fprintf(x->epsbuffer, "<<\n /ImageType %d\n /Width %d\n /Height %d\n /ImageMatrix [%d 0 0 %d 0 %d]\n", (img.trans==NULL)?1:4, img.width, img.height, img.width, -img.height, img.height); \ fprintf(x->epsbuffer, " /DataSource currentfile /ASCII85Decode filter"); /* Image data is stored in currentfile, but need to apply filters to decode it */ \ if (img.TargetCompression == BMP_ENCODING_FLATE) fprintf(x->epsbuffer, " /FlateDecode filter"); \ fprintf(x->epsbuffer, "\n /BitsPerComponent %d\n /Decode [0 %d%s]\n", (img.colour==BMP_COLOUR_RGB)?(img.depth/3):(img.depth), \ (img.type==BMP_COLOUR_PALETTE)?((1<epsbuffer," /MaskColor ["); \ if (img.colour == BMP_COLOUR_RGB) fprintf(x->epsbuffer, "%d %d %d]\n",(int)img.trans[0], (int)img.trans[1], (int)img.trans[2]); \ else fprintf(x->epsbuffer, "%d]\n" ,(int)img.trans[0]); \ } \ fprintf(x->epsbuffer, ">> image\n"); \ ppl_bmp_A85(&x->c->errcontext, x->epsbuffer, img.data, img.data_len); \ WRITE_POSTSCRIPT_IMAGE; fprintf(x->epsbuffer, "grestore\n"); return 0; } int eps_plot_colormap_DrawScales(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth) { int i, j, k; long p; double xmin,xmax,ymin,ymax; char *errtext; canvas_plotdesc *pd; pplset_graph *sg= &x->current->settings; withWords ww; errtext = ppl_memAlloc(LSTR_LENGTH); if (errtext==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY,-1,-1,"Out of memory (n)."); return 1; } // Set color for painting axes ppl_withWordsZero(x->c, &ww); if (x->current->settings.AxesColor > 0) { ww.color = x->current->settings.AxesColor; ww.USEcolor = 1; } else { ww.Col1234Space = x->current->settings.AxesCol1234Space; ww.color1 = x->current->settings.AxesColor1; ww.color2 = x->current->settings.AxesColor2; ww.color3 = x->current->settings.AxesColor3; ww.color4 = x->current->settings.AxesColor4; ww.USEcolor1234 = 1; } ww.linewidth = EPS_AXES_LINEWIDTH; ww.USElinewidth = 1; ww.linetype = 1; ww.USElinetype = 1; eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE eps_core_SetLinewidth(x, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1, 0.0); else return 0; // Find extrema of box filled by graph canvas if (!x->current->ThreeDim) { xmin = origin_x; xmax = origin_x + width; ymin = origin_y; ymax = origin_y + height; } else { xmin = xmax = origin_x; ymin = ymax = origin_y; for (k=0; k<8; k++) { double x0,y0,z0; eps_plot_ThreeDimProject((k&1),(k&2)!=0,(k&4)!=0,sg,origin_x,origin_y,width,height,zdepth,&x0,&y0,&z0); if (x0xmax) xmax=x0; if (y0ymax) ymax=y0; } } // Loop over all datasets pd = x->current->plotitems; k = 0; while (pd != NULL) // loop over all datasets { dataTable *data = x->current->plotdata[k]; if (pd->CRangeDisplay) { double XSize = 1024, YSize = 1; // Dimensions of bitmap image unsigned char component_r, component_g, component_b, transparent[3] = {TRANS_R, TRANS_G, TRANS_B}; char v[3]="c1"; double x1,y1,x2,y2 , x3,y3,x4,y4 , theta,dummy , CMin,CMax; double Lx, Ly, ThetaX, ThetaY; unsigned char CLog; const double MARGIN = EPS_COLORSCALE_MARGIN * M_TO_PS; const double WIDTH = EPS_COLORSCALE_WIDTH * M_TO_PS; const unsigned char Lr = (sg->ColKeyPos==SW_COLKEYPOS_B)||(sg->ColKeyPos==SW_COLKEYPOS_R); uLongf zlen; // Length of buffer passed to zlib unsigned char *imagez; bitmap_data img; pplObj *CVar=NULL, *C1Var, CDummy; if (sg->ColKeyPos==SW_COLKEYPOS_T) { x1 = xmin; x2 = xmax; y1 = y2 = x->current->PlotTopMargin +MARGIN; } else if (sg->ColKeyPos==SW_COLKEYPOS_B) { x1 = xmin; x2 = xmax; y1 = y2 = x->current->PlotBottomMargin-MARGIN; } else if (sg->ColKeyPos==SW_COLKEYPOS_L) { y1 = ymin; y2 = ymax; x1 = x2 = x->current->PlotLeftMargin -MARGIN; } else if (sg->ColKeyPos==SW_COLKEYPOS_R) { y1 = ymin; y2 = ymax; x1 = x2 = x->current->PlotRightMargin +MARGIN; } else { continue; } if (sg->ColKeyPos==SW_COLKEYPOS_T) { x3 = x1; x4 = x2; y3 = y4 = y1 + WIDTH; } else if (sg->ColKeyPos==SW_COLKEYPOS_B) { x3 = x1; x4 = x2; y3 = y4 = y1 - WIDTH; } else if (sg->ColKeyPos==SW_COLKEYPOS_L) { y3 = y1; y4 = y2; x3 = x4 = x1 - WIDTH; } else if (sg->ColKeyPos==SW_COLKEYPOS_R) { y3 = y1; y4 = y2; x3 = x4 = x1 + WIDTH; } else { continue; } if (sg->ColKeyPos==SW_COLKEYPOS_T) { Lx = xmax-xmin; Ly = WIDTH; ThetaX = M_PI/2; ThetaY = M_PI ; } else if (sg->ColKeyPos==SW_COLKEYPOS_B) { Lx = xmax-xmin; Ly = WIDTH; ThetaX = M_PI/2; ThetaY = 0 ; } else if (sg->ColKeyPos==SW_COLKEYPOS_L) { Lx = ymax-ymin; Ly = WIDTH; ThetaX = 0 ; ThetaY = M_PI/2; } else if (sg->ColKeyPos==SW_COLKEYPOS_R) { Lx = ymax-ymin; Ly = WIDTH; ThetaX = 0 ; ThetaY = 3*M_PI/2; } else { continue; } // Paint bitmap image portion of colorscale img.type = BMP_COLOUR_BMP; img.colour = BMP_COLOUR_RGB; img.pal_len = 0; img.palette = NULL; img.trans = transparent; img.height = YSize; img.width = XSize; img.depth = 24; img.data_len = 3*XSize*YSize; img.data = ppl_memAlloc(3*XSize*YSize); img.TargetCompression = BMP_ENCODING_FLATE; if (img.data==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1,"Out of memory (o)."); goto POST_BITMAP; } // Set CMin, CMax CMin = pd->CMinFinal; CMax = pd->CMaxFinal; CLog = (sg->Clog[0]==SW_BOOL_TRUE); // Get pointer to variable c1 in the user's variable space ppl_contextGetVarPointer(x->c, v, &CVar, &CDummy); if (sg->Crenorm[0]==SW_BOOL_FALSE) { *CVar = data->firstEntries[2]; CVar->flagComplex=0; CVar->imag=0.0; } else pplObjNum(CVar,0,0,0); // c1...c4 are dimensionless numbers in range 0-1, regardless of units of input data // Populate bitmap data array for (p=0, j=YSize-1; j>=0; j--) // Postscript images are top-first. Data block is bottom-first. for (i=0; iCrenorm[0]==SW_BOOL_FALSE) { if (!CLog) CVar->real = CMin+(CMax-CMin)*((double)i)/(XSize-1); else CVar->real = CMin*pow(CMax/CMin,((double)i)/(XSize-1)); } else CVar->real = ((double)i)/(XSize-1); C1Var = CVar; SET_RGB_COLOR; } #ifdef FLATE_DISABLE if (img.TargetCompression==BMP_ENCODING_FLATE) img.TargetCompression=BMP_ENCODING_NULL; #endif COMPRESS_POSTSCRIPT_IMAGE; // Write postscript image fprintf(x->epsbuffer, "gsave\n"); fprintf(x->epsbuffer, "[ %.2f %.2f %.2f %.2f %.2f %.2f ] concat\n", Lx*sin(ThetaX), Lx*cos(ThetaX), Ly*sin(ThetaY), Ly*cos(ThetaY), x3, y3); WRITE_POSTSCRIPT_IMAGE; fprintf(x->epsbuffer, "grestore\n"); POST_BITMAP: // Restore variable c1 in the user's variable space if (CVar!=NULL) { char v[3]="c1"; ppl_contextRestoreVarPointer(x->c, v, &CDummy); } // Paint inner-facing scale theta = ((sg->ColKeyPos==SW_COLKEYPOS_T)||(sg->ColKeyPos==SW_COLKEYPOS_B))?M_PI:(M_PI/2); if (Lr) theta=theta+M_PI; eps_plot_axispaint(x, &ww, &pd->C1Axis, 0, GSL_NAN, Lr, x1, y1, NULL, x2, y2, NULL, theta, theta, &dummy, 0); // Paint lines at top/bottom of scale eps_core_SetLinewidth(x, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1, 0.0); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", x1, y1, x3, y3); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", x2, y2, x4, y4); // Paint outer-facing scale eps_plot_axispaint(x, &ww, &pd->C1Axis, 0, GSL_NAN, !Lr, x3, y3, NULL, x4, y4, NULL, theta+M_PI, theta+M_PI, &dummy, 1); } pd=pd->next; k++; } return 0; } pyxplot-0.9.2/src/epsMaker/eps_circle.c0000664000175000017500000001020512026340554016434 0ustar dcf21dcf21// eps_circle.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_circle.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_CIRCLE 1 #include #include #include #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_circle.h" #include "epsMaker/eps_settings.h" void eps_circ_RenderEPS(EPSComm *x) { int lt; unsigned char filled=0, stroked=0; double lw, lw_scale, xpos, ypos, r, start=0, end=360, theta; withWords ww; // Print label at top of postscript description of circle fprintf(x->epsbuffer, "%% Canvas item %d [%s]\n", x->current->id, x->current->xfset ? "arc" : "circle"); eps_core_clear(x); // Calculate position of centre of circle and its radius in TeX points xpos = x->current->xpos * M_TO_PS; ypos = x->current->ypos * M_TO_PS; r = x->current->xpos2 * M_TO_PS; // If this is an arc, set start and end points if (x->current->xfset) { start = fmod(M_PI/2 - x->current->yf, 2*M_PI); end = fmod(M_PI/2 - x->current->xf, 2*M_PI); while (start < 0.0) start += 2*M_PI; while (end < 0.0) end += 2*M_PI; if ((x->current->yf < x->current->xf) && (start <= end)) start += 2*M_PI; // Make sure that arc is stroked clockwise from start to end else if ((x->current->yf > x->current->xf) && (start >= end)) end += 2*M_PI; } // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(x->c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Set fill color of circle eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); // Fill circle IF_NOT_INVISIBLE { if (!x->current->xfset) fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f 0 360 arc\nclosepath\nfill\n", xpos,ypos,r); else fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f %.2f %.2f arc\n%.2f %.2f lineto\nclosepath\nfill\n", xpos,ypos,r,start*180/M_PI,end*180/M_PI,xpos,ypos); eps_core_BoundingBox(x, xpos, ypos, 0); // Filled arcs extend to the centre of the circle filled=1; } // Set color of outline of circle eps_core_SetColor(x, &ww, 1); // Set linewidth and linetype of outline if (ww.USElinewidth) lw_scale = ww.linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww.USElinetype) lt = ww.linetype; else lt = 1; IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); // Stroke outline of circle IF_NOT_INVISIBLE { if (!x->current->xfset) fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f 0 360 arc\nclosepath\nstroke\n", xpos,ypos,r); else fprintf(x->epsbuffer, "newpath\n%.2f %.2f %.2f %.2f %.2f arc\nstroke\n", xpos,ypos,r,start*180/M_PI,end*180/M_PI); stroked=1; } // Factor circle into EPS file's bounding box if (filled || stroked) { if (!x->current->xfset) { eps_core_BoundingBox(x, xpos-r, ypos , lw); eps_core_BoundingBox(x, xpos+r, ypos , lw); eps_core_BoundingBox(x, xpos , ypos-r, lw); eps_core_BoundingBox(x, xpos , ypos+r, lw); } else { if (endc, &ww); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/bmp_gifread.h0000664000175000017500000000276012026340554016577 0ustar dcf21dcf21// bmp_gifread.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_gifread.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from GIF files. #ifndef _PPL_BMP_GIFREAD_H #define _PPL_BMP_GIFREAD_H 1 #include #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" void ppl_bmp_gifread (pplerr_context *ec, FILE *in, bitmap_data *image); int ppl_bmp_de_gifinterlace(pplerr_context *ec, bitmap_data *image); unsigned long ppl_bmp_de_lzw (pplerr_context *ec, unsigned char *buff, unsigned char *out, unsigned long len, int cs); unsigned int ppl_bmp_de_lzw_bits (pplerr_context *ec, unsigned char *c,int st, int len); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_threedimbuff.c0000664000175000017500000002162212026340554020702 0ustar dcf21dcf21// eps_plot_threedimbuff.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_threedimbuff.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_THREEDIMBUFF_C 1 #include #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" // Internal state variables unsigned char ThreeDimBuffer_ACTIVE = 0; static long ThreeDimBuffer_LineSegmentID = 0; static double ThreeDimBuffer_LineLength = 0.0; static list *ThreeDimBuffer_buffer = NULL; static int linetype_old ; static int linetype_old_SET ; static double linewidth_old ; static int linewidth_old_SET ; static double pointsize_old ; static int pointsize_old_SET ; static char *colstr_old; void ThreeDimBuffer_Reset(EPSComm *x) { ThreeDimBuffer_ACTIVE = 0; ThreeDimBuffer_LineSegmentID = 0; ThreeDimBuffer_LineLength = 0.0; ThreeDimBuffer_buffer = NULL; linetype_old_SET = linewidth_old_SET = pointsize_old_SET = 0; colstr_old = NULL; return; } int ThreeDimBuffer_Activate(EPSComm *x) { ThreeDimBuffer_Deactivate(x); ThreeDimBuffer_ACTIVE = 1; ThreeDimBuffer_LineSegmentID = 0; ThreeDimBuffer_LineLength = 0.0; ThreeDimBuffer_buffer = ppl_listInit(0); linetype_old_SET = linewidth_old_SET = pointsize_old_SET = 0; colstr_old = NULL; return (ThreeDimBuffer_buffer != NULL); } struct DepthArrayEntry { double depth; void *item; }; static int ThreeDimBuffer_qsort_slave(const void *x, const void *y) { const struct DepthArrayEntry *x1 = (const struct DepthArrayEntry *)x; const struct DepthArrayEntry *y1 = (const struct DepthArrayEntry *)y; if (x1->depth > y1->depth) return -1.0; else if (x1->depth < y1->depth) return 1.0; else return 0.0; } int ThreeDimBuffer_Deactivate(EPSComm *x) { int Nitems, i, j; struct DepthArrayEntry *DepthArray; ThreeDimBufferItem *item; listIterator *ListIter; if (!ThreeDimBuffer_ACTIVE) { ThreeDimBuffer_Reset(x); return 0; } Nitems = ppl_listLen(ThreeDimBuffer_buffer); ThreeDimBuffer_ACTIVE = 0; if (Nitems > 0) { eps_core_WritePSColor(x); // Display all items in 3D display buffer, from back to front DepthArray = (struct DepthArrayEntry *)ppl_memAlloc(Nitems * sizeof(struct DepthArrayEntry)); i=0; ListIter = ppl_listIterateInit(ThreeDimBuffer_buffer); while (ListIter != NULL) { DepthArray[i].item = ListIter->data; DepthArray[i].depth = ((ThreeDimBufferItem *)(ListIter->data))->depth; i++; ppl_listIterate(&ListIter); } qsort((void *)DepthArray, i, sizeof(struct DepthArrayEntry), ThreeDimBuffer_qsort_slave); ThreeDimBuffer_LineSegmentID = -5; for (j=0; jFlagLineSegment) { ThreeDimBuffer_linesegment(x, item->depth, item->linetype, item->linewidth, item->colstr, item->x0, item->y0, item->x1, item->y1, item->x2, item->y2, item->FirstLineSegment, (ThreeDimBuffer_LineSegmentID!=(item->LineSegmentID-1)), item->LineLength); ThreeDimBuffer_LineSegmentID = item->LineSegmentID; } else { ThreeDimBuffer_linepenup(x); ThreeDimBuffer_writeps(x, item->depth, item->linetype, item->linewidth, item->offset, item->pointsize, item->colstr, item->psfrag); } } } ThreeDimBuffer_linepenup(x); ThreeDimBuffer_Reset(x); return 0; } int ThreeDimBuffer_writeps(EPSComm *x, double z, int linetype, double linewidth, double offset, double pointsize, char *colstr, char *psfrag) { ThreeDimBufferItem *item; char *tempstr; if (!ThreeDimBuffer_ACTIVE) { if ((!pointsize_old_SET) || (pointsize_old != pointsize)) { pointsize_old_SET=1; pointsize_old=pointsize; fprintf(x->epsbuffer, "/ps { %f } def\n", pointsize * EPS_DEFAULT_PS); } colstr_old = colstr; strcpy(x->CurrentColor, colstr); eps_core_WritePSColor(x); eps_core_SetLinewidth(x, linewidth * EPS_DEFAULT_LINEWIDTH, linetype, offset); fprintf(x->epsbuffer, "%s\n", psfrag); } else { item = (ThreeDimBufferItem *)ppl_memAlloc(sizeof(ThreeDimBufferItem)); tempstr = (char *)ppl_memAlloc(strlen(psfrag)+1); if ((item == NULL) || (tempstr == NULL)) return 1; strcpy(tempstr, psfrag); item->FlagLineSegment = item->FirstLineSegment = 0; item->linetype = linetype; item->linewidth = linewidth; item->offset = offset; item->pointsize = pointsize; item->colstr = colstr; item->psfrag = tempstr; item->depth = z; ppl_listAppend(ThreeDimBuffer_buffer, (void *)item); } return 0; } int ThreeDimBuffer_linesegment(EPSComm *x, double z, int linetype, double linewidth, char *colstr, double x0, double y0, double x1, double y1, double x2, double y2, unsigned char FirstSegment, unsigned char broken, double LengthOffset) { ThreeDimBufferItem *item; if (!ThreeDimBuffer_ACTIVE) { if (FirstSegment && (ThreeDimBuffer_LineSegmentID > 0)) ThreeDimBuffer_linepenup(x); // If first segment of new line, finish old line if (broken || (!linetype_old_SET) || (linetype_old != linetype) || (!linewidth_old_SET) || (linewidth_old != linewidth) || (colstr_old == NULL) || (strcmp(colstr_old, colstr)!=0)) { // Start line 0.1 linewidths along in the direction of x0 to get correct linecap if ((!FirstSegment) && ((x0!=x1) || (y0!=y1))) { double theta = atan2(x0-x1,y0-y1); x0 = x1 + 0.1 * sin(theta) * linewidth * EPS_DEFAULT_LINEWIDTH; y0 = y1 + 0.1 * cos(theta) * linewidth * EPS_DEFAULT_LINEWIDTH; } else { x0 = x1; y0 = y1; } ThreeDimBuffer_linepenup(x); linetype_old_SET = linewidth_old_SET = 1; linetype_old = linetype; linewidth_old = linewidth; eps_core_SetLinewidth(x, linewidth * EPS_DEFAULT_LINEWIDTH, linetype, broken ? (LengthOffset-hypot(x1-x0,y1-y0)) : 0.0); if ((colstr_old == NULL) || (strcmp(colstr_old, colstr)!=0)) { colstr_old = colstr; strcpy(x->CurrentColor, colstr); eps_core_WritePSColor(x); } if (FirstSegment) fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n", x1, y1, x2, y2); else fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n", x0, y0, x1, y1, x2, y2); eps_core_BoundingBox(x, x1, y1, linewidth * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x2, y2, linewidth * EPS_DEFAULT_LINEWIDTH); } else { if (FirstSegment) fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n", x1, y1, x2, y2); else fprintf(x->epsbuffer, "%.2f %.2f lineto\n", x2, y2); eps_core_BoundingBox(x, x1, y1, linewidth * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x2, y2, linewidth * EPS_DEFAULT_LINEWIDTH); } ThreeDimBuffer_LineSegmentID = 1; } else { if (FirstSegment) ThreeDimBuffer_LineLength = 0.0; if ((!linetype_old_SET) || (linetype_old != linetype)) { ThreeDimBuffer_LineLength = 0.0; linetype_old_SET = 1; linetype_old = linetype; } item = (ThreeDimBufferItem *)ppl_memAlloc(sizeof(ThreeDimBufferItem)); if (item == NULL) return 1; item->FlagLineSegment = 1; item->LineSegmentID = ThreeDimBuffer_LineSegmentID++; item->LineLength = ThreeDimBuffer_LineLength; item->FirstLineSegment = FirstSegment; item->linetype = linetype; item->linewidth = linewidth; item->colstr = colstr; item->depth = z; item->x0 = x0; item->y0 = y0; item->x1 = x1; item->y1 = y1; item->x2 = x2; item->y2 = y2; ppl_listAppend(ThreeDimBuffer_buffer, (void *)item); ThreeDimBuffer_LineLength += hypot(x2-x1,y2-y1); } return 0; } int ThreeDimBuffer_linepenup(EPSComm *x) { if (!ThreeDimBuffer_ACTIVE) { if (ThreeDimBuffer_LineSegmentID >= 0) fprintf(x->epsbuffer, "stroke\n"); ThreeDimBuffer_LineSegmentID = -5; } return 0; } pyxplot-0.9.2/src/epsMaker/eps_polygon.h0000664000175000017500000000172212026340554016673 0ustar dcf21dcf21// eps_polygon.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_polygon.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_POLYGON_H #define _PPL_EPS_POLYGON_H 1 #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" void eps_polygon_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/bmp_a85.h0000664000175000017500000000240512026340554015567 0ustar dcf21dcf21// bmp_a85.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_a85.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It efficiently encodes a string of raw image data into // postscript's ASCII 85 data format, making use of all of the printable ASCII // characters. #ifndef _PPL_BMP_A85_H #define _PPL_BMP_A85_H 1 #include #include "coreUtils/errorReport.h" unsigned int ppl_bmp_A85(pplerr_context *ec, FILE* fout, unsigned char* in, int len); #endif pyxplot-0.9.2/src/epsMaker/bmp_optimise.h0000664000175000017500000000301312026340554017017 0ustar dcf21dcf21// bmp_optimise.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_optimise.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It checks paletted images for possible optimisations of the // palette size if there are unused entries, and checks RGB images to see if // they can efficiently be reduced to paletted images. #ifndef _PPL_BMP_OPTIMISE_H #define _PPL_BMP_OPTIMISE_H 1 #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" void ppl_bmp_colour_count (pplerr_context *ec, bitmap_data *image); void ppl_bmp_palette_check(pplerr_context *ec, bitmap_data *image); void ppl_bmp_grey_check (pplerr_context *ec, bitmap_data *image); void ppl_bmp_compact (pplerr_context *ec, bitmap_data *image); #endif pyxplot-0.9.2/src/epsMaker/bmp_image.h0000664000175000017500000000267712026340554016267 0ustar dcf21dcf21// bmp_image.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: bmp_image.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _BMP_IMAGE_H #define _BMP_IMAGE_H 1 // Colour channel configurations #define BMP_COLOUR_BMP 1001 #define BMP_COLOUR_PALETTE 1002 #define BMP_COLOUR_GREY 1003 #define BMP_COLOUR_RGB 1004 // Image compression types #define BMP_ENCODING_NULL 1100 #define BMP_ENCODING_LZW 1101 #define BMP_ENCODING_FLATE 1102 #define BMP_ENCODING_DCT 1103 #define BMP_ALLOC(X,Y) { X = (unsigned char *)ppl_memAlloc(Y); } typedef struct bitmap_data { unsigned char *data, *palette, *trans; unsigned long data_len; int pal_len, width, height, depth, type, colour, TargetCompression, flags; double XDPI, YDPI; } bitmap_data; #endif pyxplot-0.9.2/src/epsMaker/eps_core.c0000664000175000017500000002055412026340554016133 0ustar dcf21dcf21// eps_core.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_core.c 1299 2012-08-31 23:32:22Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains various numerical constants which are used by the eps // generation routines #define _PPL_EPS_CORE_C 1 #include #include #include #include #include "coreUtils/errorReport.h" #include "settings/epsColors.h" #include "settings/settingTypes.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_style.h" #include "userspace/context.h" // Clear EPS state information to ensure that we restate the linewidth, color, etc we are using for the next item void eps_core_clear(EPSComm *x) { x->LastLinewidth = -1; strcpy(x->LastPSColor, ""); strcpy(x->CurrentColor, ""); strcpy(x->CurrentFillColor, ""); x->LastLinetype = 0; return; } // Write CurrentColor to postscript void eps_core_WritePSColor(EPSComm *x) { if ((strcmp(x->CurrentColor, x->LastPSColor) != 0) && (x->CurrentColor[0]!='\0')) { strcpy(x->LastPSColor, x->CurrentColor); fprintf(x->epsbuffer, "%s\n", x->LastPSColor); } return; } // Set the color of the EPS we are painting void eps_core_SetColor(EPSComm *x, withWords *ww, unsigned char WritePS) { // Color may be specified as a named color, or as RGB components, or may not be specified at all, in which case we use black if (ww->USEcolor1234) { if ( (!gsl_finite(ww->color1)) || (!gsl_finite(ww->color2)) || (!gsl_finite(ww->color3)) ) { sprintf(x->CurrentColor, "0 0 0 setrgbcolor"); } else if ( (ww->Col1234Space==SW_COLSPACE_CMYK) && (!gsl_finite(ww->color4)) ) { sprintf(x->CurrentColor, "0 0 0 setrgbcolor"); } else if (ww->Col1234Space==SW_COLSPACE_RGB ) sprintf(x->CurrentColor, "%.3f %.3f %.3f setrgbcolor", ww->color1, ww->color2, ww->color3); else if (ww->Col1234Space==SW_COLSPACE_HSB ) sprintf(x->CurrentColor, "%.3f %.3f %.3f sethsbcolor", ww->color1, ww->color2, ww->color3); else if (ww->Col1234Space==SW_COLSPACE_CMYK) sprintf(x->CurrentColor, "%.3f %.3f %.3f %.3f setcmykcolor", ww->color1, ww->color2, ww->color3, ww->color4); else ppl_error(&x->c->errcontext,ERR_INTERNAL,-1,-1,"Illegal setting for color space switch."); } else if((ww->USEcolor ) && ((ww->color==COLOR_NULL)||(ww->color==COLOR_INVISIBLE)||(ww->color==COLOR_TRANSPARENT))) strcpy (x->CurrentColor, ""); // This is code to tell us we're writing in invisible ink else if (ww->USEcolor ) sprintf(x->CurrentColor, "%.3f %.3f %.3f %.3f setcmykcolor", *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->color, SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->color, SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->color, SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->color, SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)) ); else sprintf(x->CurrentColor, "0 0 0 setrgbcolor"); // Only change postscript color if the color we want isn't the one we are already using if ((strcmp(x->CurrentColor, x->LastPSColor) != 0) && WritePS && (x->CurrentColor[0]!='\0')) eps_core_WritePSColor(x); return; } void eps_core_SetFillColor(EPSComm *x, withWords *ww) { // Color may be specified as a named color, or as RGB components, or may not be specified at all, in which case we use black if (ww->USEfillcolor1234) { if (ww->FillCol1234Space==SW_COLSPACE_RGB ) sprintf(x->CurrentFillColor, "%.3f %.3f %.3f setrgbcolor", ww->fillcolor1, ww->fillcolor2, ww->fillcolor3); else if (ww->FillCol1234Space==SW_COLSPACE_HSB ) sprintf(x->CurrentFillColor, "%.3f %.3f %.3f sethsbcolor", ww->fillcolor1, ww->fillcolor2, ww->fillcolor3); else if (ww->FillCol1234Space==SW_COLSPACE_CMYK) sprintf(x->CurrentFillColor, "%.3f %.3f %.3f %.3f setcmykcolor", ww->fillcolor1, ww->fillcolor2, ww->fillcolor3, ww->fillcolor4); else ppl_error(&x->c->errcontext,ERR_INTERNAL,-1,-1,"Illegal setting for color space switch."); } else if((ww->USEfillcolor ) && ((ww->fillcolor==COLOR_NULL)||(ww->fillcolor==COLOR_INVISIBLE)||(ww->fillcolor==COLOR_TRANSPARENT))) strcpy (x->CurrentFillColor, ""); // This is code to tell us we're writing in invisible ink else if (ww->USEfillcolor ) sprintf(x->CurrentFillColor, "%.3f %.3f %.3f %.3f setcmykcolor", *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->fillcolor, SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->fillcolor, SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->fillcolor, SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)), *(double *)ppl_fetchSettingName(&x->c->errcontext, ww->fillcolor, SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)) ); else strcpy (x->CurrentFillColor, ""); // If no fill color is specified, we don't fill return; } static char TempColor[256]; void eps_core_SwitchTo_FillColor(EPSComm *x, unsigned char WritePS) { strcpy(TempColor , x->CurrentColor); // Buffer the color we're stroking with so we can restore it in eps_core_SwitchFrom_FillColor if ((strcmp(x->CurrentFillColor, x->LastPSColor) != 0) && WritePS && (x->CurrentFillColor[0]!='\0')) { strcpy(x->LastPSColor, x->CurrentFillColor); fprintf(x->epsbuffer, "%s\n", x->LastPSColor); } strcpy(x->CurrentColor , x->CurrentFillColor); // This make the supression of invisible ink work... return; } void eps_core_SwitchFrom_FillColor(EPSComm *x, unsigned char WritePS) { if ((strcmp(TempColor, x->LastPSColor) != 0) && WritePS && (TempColor[0]!='\0')) { strcpy(x->LastPSColor, TempColor); fprintf(x->epsbuffer, "%s\n", x->LastPSColor); } strcpy(x->CurrentColor, TempColor); // Restore the color we're stroking with return; } // Set the linewidth of the EPS we are painting void eps_core_SetLinewidth(EPSComm *x, double lw, int lt, double offset) { if ((lw == x->LastLinewidth) && (lt == x->LastLinetype) && (offset==0.0)) return; if (lw != x->LastLinewidth) fprintf(x->epsbuffer, "%f setlinewidth\n", lw); fprintf(x->epsbuffer, "%s\n", eps_LineType(lt, lw, offset)); x->LastLinewidth = lw; x->LastLinetype = lt; return; } // Update the EPS bounding box void eps_core_BoundingBox(EPSComm *x, double xpos, double ypos, double lw) { if ((!x->bb_set) || (x->bb_left > (xpos-lw/2))) x->bb_left = (xpos-lw/2); if ((!x->bb_set) || (x->bb_right < (xpos+lw/2))) x->bb_right = (xpos+lw/2); if ((!x->bb_set) || (x->bb_bottom > (ypos-lw/2))) x->bb_bottom = (ypos-lw/2); if ((!x->bb_set) || (x->bb_top < (ypos+lw/2))) x->bb_top = (ypos+lw/2); x->bb_set = 1; return; } // Update plot item bounding box void eps_core_PlotBoundingBox(EPSComm *x, double xpos, double ypos, double lw, unsigned char UpdatePsBB) { if (x->current->PlotLeftMargin > (xpos-lw/2)) x->current->PlotLeftMargin = (xpos-lw/2); if (x->current->PlotRightMargin < (xpos+lw/2)) x->current->PlotRightMargin = (xpos+lw/2); if (x->current->PlotBottomMargin > (ypos-lw/2)) x->current->PlotBottomMargin = (ypos-lw/2); if (x->current->PlotTopMargin < (ypos+lw/2)) x->current->PlotTopMargin = (ypos+lw/2); if (UpdatePsBB) eps_core_BoundingBox(x, xpos, ypos, lw); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_styles.c0000664000175000017500000024155212026340554017567 0ustar dcf21dcf21// eps_plot_styles.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_styles.c 1301 2012-09-02 15:42:16Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_STYLES_C 1 #include #include #include #include #include "coreUtils/memAlloc.h" #include "epsMaker/canvasDraw.h" #include "canvasItems.h" #include "coreUtils/errorReport.h" #include "mathsTools/dcfmath.h" #include "settings/epsColors.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_filledregion.h" #include "epsMaker/eps_plot_linedraw.h" #include "epsMaker/eps_plot_styles.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" #include "epsMaker/eps_style.h" // Work out the default set of with words for a plot item void eps_withwords_default(EPSComm *x, withWords *output, pplset_graph *sg, unsigned char functions, int Ccounter, int LTcounter, int PTcounter, unsigned char color) { int i,j; ppl_withWordsZero(x->c, output); if (!color) { output->color = COLOR_BLACK; output->USEcolor = 1; } else { for (j=0; jc->set->palette_current[j]==-1) break; // j now contains length of palette i = Ccounter % j; // i is now the palette color number to use while (i<0) i+=j; if (x->c->set->palette_current[i] > 0) { output->color = x->c->set->palette_current[i]; output->USEcolor = 1; } else { output->Col1234Space = x->c->set->paletteS_current[i]; output->color1 = x->c->set->palette1_current[i]; output->color2 = x->c->set->palette2_current[i]; output->color3 = x->c->set->palette3_current[i]; output->color4 = x->c->set->palette4_current[i]; output->USEcolor1234 = 1; } output->AUTOcolor = Ccounter+5; } output->linespoints = (functions ? SW_STYLE_LINES : SW_STYLE_POINTS); output->USElinespoints = 1; output->fillcolor = COLOR_NULL; output->USEfillcolor = 1; output->linetype = color ? 1 : LTcounter+1; output->pointtype = PTcounter+1; output->USElinetype = output->USEpointtype = 1; output->AUTOlinetype = !color; output->AUTOpointtype = PTcounter+6; output->linewidth = sg->LineWidth; output->pointlinewidth = sg->PointLineWidth; output->pointsize = sg->PointSize; output->USElinewidth = output->USEpointlinewidth = output->USEpointsize = 1; return; } void eps_withwords_default_counterinc(EPSComm *x, int *Ccounter, int *LTcounter, int *PTcounter, unsigned char color, withWords *ww_final, pplset_graph *sg) { int style = ww_final->linespoints; if (ww_final->AUTOcolor && (style!=SW_STYLE_COLORMAP) && (style!=SW_STYLE_CONTOURMAP)) { (*Ccounter)++; } if (ww_final->AUTOlinetype && ((style==SW_STYLE_ARROWS_HEAD)||(style==SW_STYLE_ARROWS_NOHEAD)||(style==SW_STYLE_ARROWS_TWOHEAD)||(style==SW_STYLE_BOXES)||(style==SW_STYLE_FILLEDREGION)||(style==SW_STYLE_FSTEPS)||(style==SW_STYLE_HISTEPS)||(style==SW_STYLE_IMPULSES)||(style==SW_STYLE_LINES)||(style==SW_STYLE_LINESPOINTS)||(style==SW_STYLE_STEPS)||(style==SW_STYLE_SURFACE)||(style==SW_STYLE_WBOXES)||(style==SW_STYLE_XERRORBARS)||(style==SW_STYLE_XERRORRANGE)||(style==SW_STYLE_XYERRORBARS)||(style==SW_STYLE_XYERRORRANGE)||(style==SW_STYLE_XYZERRORBARS)||(style==SW_STYLE_XYZERRORRANGE)||(style==SW_STYLE_YERRORBARS)||(style==SW_STYLE_YERRORRANGE)||(style==SW_STYLE_YZERRORBARS)||(style==SW_STYLE_YZERRORRANGE)||(style==SW_STYLE_ZERRORBARS)||(style==SW_STYLE_ZERRORRANGE))) { (*LTcounter)++; } if (ww_final->AUTOpointtype && ((style==SW_STYLE_LINESPOINTS)||(style==SW_STYLE_POINTS)||(style==SW_STYLE_STARS))) { (*PTcounter)++; } if (style==SW_STYLE_CONTOURMAP) { int Ncontours = (sg->ContoursListLen>=0) ? sg->ContoursListLen : sg->ContoursN; if (ww_final->AUTOcolor) { (*Ccounter )+=Ncontours; } if (ww_final->AUTOlinetype) { (*LTcounter)+=Ncontours; } } return; } // Return the number of columns of data which are required to plot in any given plot style int eps_plot_styles_NDataColumns(pplerr_context *ec, int style, unsigned char ThreeDim) { if (style == SW_STYLE_POINTS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_LINES ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_LINESPOINTS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_XERRORBARS ) return 3 + (ThreeDim!=0); else if (style == SW_STYLE_YERRORBARS ) return 3 + (ThreeDim!=0); else if (style == SW_STYLE_ZERRORBARS ) return 3 + 1; else if (style == SW_STYLE_XYERRORBARS ) return 4 + (ThreeDim!=0); else if (style == SW_STYLE_XZERRORBARS ) return 4 + 1; else if (style == SW_STYLE_YZERRORBARS ) return 4 + 1; else if (style == SW_STYLE_XYZERRORBARS ) return 5 + 1; else if (style == SW_STYLE_XERRORRANGE ) return 4 + (ThreeDim!=0); else if (style == SW_STYLE_YERRORRANGE ) return 4 + (ThreeDim!=0); else if (style == SW_STYLE_ZERRORRANGE ) return 4 + 1; else if (style == SW_STYLE_XYERRORRANGE ) return 6 + (ThreeDim!=0); else if (style == SW_STYLE_XZERRORRANGE ) return 6 + 1; else if (style == SW_STYLE_YZERRORRANGE ) return 6 + 1; else if (style == SW_STYLE_XYZERRORRANGE ) return 8 + 1; else if (style == SW_STYLE_FILLEDREGION ) return 2; else if (style == SW_STYLE_YERRORSHADED ) return 3; else if (style == SW_STYLE_UPPERLIMITS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_LOWERLIMITS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_DOTS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_IMPULSES ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_BOXES ) return 2; else if (style == SW_STYLE_WBOXES ) return 3; else if (style == SW_STYLE_STEPS ) return 2; else if (style == SW_STYLE_FSTEPS ) return 2; else if (style == SW_STYLE_HISTEPS ) return 2; else if (style == SW_STYLE_STARS ) return 2 + (ThreeDim!=0); else if (style == SW_STYLE_ARROWS_HEAD ) return 4 + 2*(ThreeDim!=0); else if (style == SW_STYLE_ARROWS_NOHEAD ) return 4 + 2*(ThreeDim!=0); else if (style == SW_STYLE_ARROWS_TWOHEAD ) return 4 + 2*(ThreeDim!=0); else if (style == SW_STYLE_SURFACE ) return 3; else if (style == SW_STYLE_COLORMAP ) return 3; else if (style == SW_STYLE_CONTOURMAP ) return 3; ppl_fatal(ec,__FILE__,__LINE__,"Unrecognised style type passed to eps_plot_styles_NDataColumns()"); return -1; } // UpdateUsage... get content of row X from data table #define UUR(X) blk->data_real[X + Ncolumns*j] // UpdateUsage... check whether position is within range of axis #define UUC(X,Y) \ { \ if (InRange && (!eps_plot_axis_InRange(X,Y))) InRange=0; \ } // Memory recall on within-range flag, adding previous flag to ORed list of points to be checked #define UUD(X,Y) \ { \ PartiallyInRange = PartiallyInRange || InRange; \ InRange = InRangeMemory; \ UUC(X,Y); \ } // Store current within-range flag to memory #define UUE(X,Y) \ { \ InRangeMemory = InRange; \ UUC(X,Y); \ } // Simultaneously update usage with UUU and check whether position is within range #define UUF(X,Y) \ { \ UUC(X,logaxis?exp(Y):(Y)) \ UUU(X,logaxis?exp(Y):(Y)) \ } // Reset flags used to test whether a datapoint is within range before using it to update ranges of other axes #define UUC_RESET \ { \ InRange=1; PartiallyInRange=0; InRangeMemory=1; \ } // UpdateUsage... update axis X with ordinate value Y #define UUU(X,Y) \ { \ if (InRange || PartiallyInRange) \ { \ z = Y; \ if ( (gsl_finite(z)) && ((!X->MinUsedSet) || (X->MinUsed > z)) && ((X->LogFinal != SW_BOOL_TRUE) || (z>0.0)) ) { X->MinUsedSet=1; X->MinUsed=z; } \ if ( (gsl_finite(z)) && ((!X->MaxUsedSet) || (X->MaxUsed < z)) && ((X->LogFinal != SW_BOOL_TRUE) || (z>0.0)) ) { X->MaxUsedSet=1; X->MaxUsed=z; } \ } \ } // UpdateUsage... update axis X to include value of BoxFrom #define UUUBF(X) \ { \ if (!(X->DataUnitSet && (!ppl_unitsDimEqual(&sg->BoxFrom, &X->DataUnit)))) UUU(X,sg->BoxFrom.real); \ } // UpdateUsage... get physical unit of row X from data table #define UURU(X) data->firstEntries[X] // UpdateUsage... assert that axis X should be dimensionally compatible with unit Y #define UUAU(XYZ,XYZN,X,Y) \ if ((X->HardUnitSet) && (!ppl_unitsDimEqual(&X->HardUnit , &(Y)))) { sprintf(x->c->errcontext.tempErrStr, "Axis %c%d on plot %d has data plotted against it with conflicting physical units of <%s> as compared to range of axis, which has units of <%s>.", "xyzc"[XYZ], XYZN, id, ppl_printUnit(x->c,&(Y),NULL,NULL,0,1,0), ppl_printUnit(x->c,&X->HardUnit,NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1, NULL); return 1; } \ if ((X->DataUnitSet) && (!ppl_unitsDimEqual(&X->DataUnit , &(Y)))) { sprintf(x->c->errcontext.tempErrStr, "Axis %c%d on plot %d has data plotted against it with conflicting physical units of <%s> and <%s>.", "xyzc"[XYZ], XYZN, id, ppl_printUnit(x->c,&X->DataUnit,NULL,NULL,0,1,0), ppl_printUnit(x->c,&(Y),NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1, NULL); return 1; } \ if (!X->DataUnitSet) \ { \ X->DataUnitSet = 1; \ X->DataUnit = Y; \ } // Update the usage of axes to include data from a particular data table, plotted in a particular style int eps_plot_styles_UpdateUsage(EPSComm *x, dataTable *data, int style, unsigned char ThreeDim, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, pplset_graph *sg, int xyz1, int xyz2, int xyz3, int n1, int n2, int n3, int id) { int i, j, Ncolumns; double z; double ptAx, ptBx=0, ptCx=0, lasty=0; unsigned char ptAset=0, ptBset=0, ptCset=0; unsigned char InRange, PartiallyInRange, InRangeMemory; dataBlock *blk; if ((data==NULL) || (data->Nrows<1)) return 0; // No data present // Cycle through data table acting upon the physical units of all of the columns if (style == SW_STYLE_POINTS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_LINES ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_LINESPOINTS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_XERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_YERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz2,n2,a2,UURU(2+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_ZERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz3,n3,a3,UURU(3)); } else if (style == SW_STYLE_XYERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz2,n2,a2,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_XZERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz1,n1,a1,UURU(3)); UUAU(xyz3,n3,a3,UURU(4)); } else if (style == SW_STYLE_YZERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz2,n2,a2,UURU(3)); UUAU(xyz3,n3,a3,UURU(4)); } else if (style == SW_STYLE_XYZERRORBARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz1,n1,a1,UURU(3)); UUAU(xyz2,n2,a2,UURU(4)); UUAU(xyz3,n3,a3,UURU(5)); } else if (style == SW_STYLE_XERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz1,n1,a1,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_YERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz2,n2,a2,UURU(2+ThreeDim)); UUAU(xyz2,n2,a2,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_ZERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz3,n3,a3,UURU(3)); UUAU(xyz3,n3,a3,UURU(4)); } else if (style == SW_STYLE_XYERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz1,n1,a1,UURU(3+ThreeDim)); UUAU(xyz2,n2,a2,UURU(4+ThreeDim)); UUAU(xyz2,n2,a2,UURU(5+ThreeDim)); if (ThreeDim) UUAU(xyz3,n3,a3,UURU(2)); } else if (style == SW_STYLE_XZERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz1,n1,a1,UURU(3)); UUAU(xyz1,n1,a1,UURU(4)); UUAU(xyz3,n3,a3,UURU(5)); UUAU(xyz3,n3,a3,UURU(6)); } else if (style == SW_STYLE_YZERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz2,n2,a2,UURU(3)); UUAU(xyz2,n2,a2,UURU(4)); UUAU(xyz3,n3,a3,UURU(5)); UUAU(xyz3,n3,a3,UURU(6)); } else if (style == SW_STYLE_XYZERRORRANGE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz1,n1,a1,UURU(3)); UUAU(xyz1,n1,a1,UURU(4)); UUAU(xyz2,n2,a2,UURU(5)); UUAU(xyz2,n2,a2,UURU(6)); UUAU(xyz3,n3,a3,UURU(7)); UUAU(xyz3,n3,a3,UURU(8)); } else if (style == SW_STYLE_FILLEDREGION ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_YERRORSHADED ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz2,n2,a2,UURU(2)); } else if (style == SW_STYLE_UPPERLIMITS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_LOWERLIMITS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_DOTS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_IMPULSES ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_BOXES ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_WBOXES ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2)); } else if (style == SW_STYLE_STEPS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_FSTEPS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_HISTEPS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_STARS ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_ARROWS_HEAD ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz2,n2,a2,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz3,n3,a3,UURU(5)); } } else if (style == SW_STYLE_ARROWS_NOHEAD ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz2,n2,a2,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz3,n3,a3,UURU(5)); } } else if (style == SW_STYLE_ARROWS_TWOHEAD ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); UUAU(xyz1,n1,a1,UURU(2+ThreeDim)); UUAU(xyz2,n2,a2,UURU(3+ThreeDim)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); UUAU(xyz3,n3,a3,UURU(5)); } } else if (style == SW_STYLE_SURFACE ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); if (ThreeDim) { UUAU(xyz3,n3,a3,UURU(2)); } } else if (style == SW_STYLE_COLORMAP ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } else if (style == SW_STYLE_CONTOURMAP ) { UUAU(xyz1,n1,a1,UURU(0)); UUAU(xyz2,n2,a2,UURU(1)); } // Cycle through data table, ensuring that axis ranges are sufficient to include all data Ncolumns = data->Ncolumns_real; blk = data->first; i=0; while (blk != NULL) { for (j=0; jblockPosition; j++) { UUC_RESET; if (style == SW_STYLE_POINTS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_LINES ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_LINESPOINTS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_XERRORBARS ) { UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUE(a1, UUR(0)-UUR(2+ThreeDim)); UUD(a1, UUR(0) ); UUD(a1, UUR(0)+UUR(2+ThreeDim)); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(2+ThreeDim)); UUU(a1, UUR(0)+UUR(2+ThreeDim)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_YERRORBARS ) { UUC(a1, UUR(0)); if (ThreeDim) UUC(a3, UUR(2)); UUE(a2, UUR(1)-UUR(2+ThreeDim)); UUD(a2, UUR(1) ); UUD(a2, UUR(1)+UUR(2+ThreeDim)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a2, UUR(1)-UUR(2+ThreeDim)); UUU(a2, UUR(1)+UUR(2+ThreeDim)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_ZERRORBARS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUE(a3, UUR(2)); UUD(a3, UUR(2)-UUR(3)); UUD(a3, UUR(2)+UUR(3)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a3, UUR(2)); UUU(a3, UUR(2)-UUR(3)); UUU(a3, UUR(2)+UUR(3)); } else if (style == SW_STYLE_XYERRORBARS ) { if (ThreeDim) UUC(a3, UUR(2)); UUE(a1, UUR(0) ); UUC(a2, UUR(1)-UUR(3+ThreeDim)); UUD(a1, UUR(0) ); UUC(a2, UUR(1) ); UUD(a1, UUR(0) ); UUC(a2, UUR(1)+UUR(3+ThreeDim)); UUD(a1, UUR(0)-UUR(2+ThreeDim)); UUC(a2, UUR(1) ); UUD(a1, UUR(0)+UUR(2+ThreeDim)); UUC(a2, UUR(1) ); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(2+ThreeDim)); UUU(a1, UUR(0)+UUR(2+ThreeDim)); UUU(a2, UUR(1)); UUU(a2, UUR(1)-UUR(3+ThreeDim)); UUU(a2, UUR(1)+UUR(3+ThreeDim)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_XZERRORBARS ) { UUC(a2, UUR(1)); UUE(a1, UUR(0) ); UUC(a3, UUR(2)-UUR(4)); UUD(a1, UUR(0) ); UUC(a3, UUR(2) ); UUD(a1, UUR(0) ); UUC(a3, UUR(2)+UUR(4)); UUD(a1, UUR(0)-UUR(3)); UUC(a3, UUR(2) ); UUD(a1, UUR(0)+UUR(3)); UUC(a3, UUR(2) ); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(3)); UUU(a1, UUR(0)+UUR(3)); UUU(a2, UUR(1)); UUU(a3, UUR(2)); UUU(a3, UUR(2)-UUR(4)); UUU(a3, UUR(2)+UUR(4)); } else if (style == SW_STYLE_YZERRORBARS ) { UUC(a1, UUR(0)); UUE(a2, UUR(1) ); UUC(a3, UUR(2)-UUR(4)); UUD(a2, UUR(1) ); UUC(a3, UUR(2) ); UUD(a2, UUR(1) ); UUC(a3, UUR(2)+UUR(4)); UUD(a2, UUR(1)-UUR(3)); UUC(a3, UUR(2) ); UUD(a2, UUR(1)+UUR(3)); UUC(a3, UUR(2) ); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a2, UUR(1)-UUR(3)); UUU(a2, UUR(1)+UUR(3)); UUU(a3, UUR(2)); UUU(a3, UUR(2)-UUR(4)); UUU(a3, UUR(2)+UUR(4)); } else if (style == SW_STYLE_XYZERRORBARS ) { UUC(a1, UUR(0) ); UUC(a2, UUR(1) ); UUC(a3, UUR(2)-UUR(5)); UUD(a1, UUR(0) ); UUC(a2, UUR(1) ); UUC(a3, UUR(2) ); UUD(a1, UUR(0) ); UUC(a2, UUR(1) ); UUC(a3, UUR(2)+UUR(5)); UUD(a1, UUR(0) ); UUC(a2, UUR(1)-UUR(4)); UUC(a3, UUR(2) ); UUD(a1, UUR(0) ); UUC(a2, UUR(1)+UUR(4)); UUC(a3, UUR(2) ); UUD(a1, UUR(0)-UUR(3)); UUC(a2, UUR(1) ); UUC(a3, UUR(2) ); UUD(a1, UUR(0)+UUR(3)); UUC(a2, UUR(1) ); UUC(a3, UUR(2) ); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(3)); UUU(a1, UUR(0)+UUR(3)); UUU(a2, UUR(1)); UUU(a2, UUR(1)-UUR(4)); UUU(a2, UUR(1)+UUR(4)); UUU(a3, UUR(2)); UUU(a3, UUR(2)-UUR(5)); UUU(a3, UUR(2)+UUR(5)); } else if (style == SW_STYLE_XERRORRANGE ) { UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUE(a1, UUR(2+ThreeDim)); UUD(a1, UUR(0) ); UUD(a1, UUR(3+ThreeDim)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a1, UUR(2+ThreeDim)); UUU(a1, UUR(3+ThreeDim)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_YERRORRANGE ) { UUC(a1, UUR(0)); if (ThreeDim) UUC(a3, UUR(2)); UUE(a2, UUR(2+ThreeDim)); UUD(a2, UUR(1) ); UUD(a2, UUR(3+ThreeDim)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a2, UUR(2+ThreeDim)); UUU(a2, UUR(3+ThreeDim)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_ZERRORRANGE ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUE(a3, UUR(2)); UUD(a3, UUR(3)); UUD(a3, UUR(4)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a3, UUR(2)); UUU(a3, UUR(3)); UUU(a3, UUR(4)); } else if (style == SW_STYLE_XYERRORRANGE ) { if (ThreeDim) UUC(a3, UUR(2)); UUE(a1, UUR(0) ); UUC(a2, UUR(4+ThreeDim)); UUD(a1, UUR(0) ); UUC(a2, UUR(1) ); UUD(a1, UUR(0) ); UUC(a2, UUR(5+ThreeDim)); UUD(a1, UUR(2+ThreeDim)); UUC(a2, UUR(1) ); UUD(a1, UUR(3+ThreeDim)); UUC(a2, UUR(1) ); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a1, UUR(2+ThreeDim)); UUU(a1, UUR(3+ThreeDim)); UUU(a2, UUR(4+ThreeDim)); UUU(a2, UUR(5+ThreeDim)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_XZERRORRANGE ) { UUC(a2, UUR(1)); UUE(a1, UUR(0)); UUC(a3, UUR(5)); UUD(a1, UUR(0)); UUC(a3, UUR(2)); UUD(a1, UUR(0)); UUC(a3, UUR(6)); UUD(a1, UUR(3)); UUC(a3, UUR(2)); UUD(a1, UUR(4)); UUC(a3, UUR(2)); UUU(a2, UUR(1)); UUU(a1, UUR(0)); UUU(a1, UUR(3)); UUU(a1, UUR(4)); UUU(a3, UUR(2)); UUU(a3, UUR(5)); UUU(a3, UUR(6)); } else if (style == SW_STYLE_YZERRORRANGE ) { UUC(a1, UUR(0)); UUE(a2, UUR(1)); UUC(a3, UUR(5)); UUD(a2, UUR(1)); UUC(a3, UUR(2)); UUD(a2, UUR(1)); UUC(a3, UUR(6)); UUD(a2, UUR(3)); UUC(a3, UUR(2)); UUD(a2, UUR(4)); UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a1, UUR(3)); UUU(a1, UUR(4)); UUU(a2, UUR(1)); UUU(a2, UUR(5)); UUU(a2, UUR(6)); UUU(a3, UUR(2)); UUU(a3, UUR(7)); UUU(a3, UUR(8)); } else if (style == SW_STYLE_XYZERRORRANGE ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUC(a3, UUR(7)); UUD(a1, UUR(0)); UUC(a2, UUR(1)); UUC(a3, UUR(2)); UUD(a1, UUR(0)); UUC(a2, UUR(1)); UUC(a3, UUR(8)); UUD(a1, UUR(0)); UUC(a2, UUR(5)); UUC(a3, UUR(2)); UUD(a1, UUR(0)); UUC(a2, UUR(6)); UUC(a3, UUR(2)); UUD(a1, UUR(3)); UUC(a2, UUR(1)); UUC(a3, UUR(2)); UUD(a1, UUR(4)); UUC(a2, UUR(1)); UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(3)); UUU(a1, UUR(0)+UUR(3)); UUU(a2, UUR(1)); UUU(a2, UUR(1)-UUR(4)); UUU(a2, UUR(1)+UUR(4)); UUU(a3, UUR(2)); UUU(a3, UUR(2)-UUR(5)); UUU(a3, UUR(2)+UUR(5)); } else if (style == SW_STYLE_FILLEDREGION ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); } else if (style == SW_STYLE_YERRORSHADED ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUC(a2, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a2, UUR(2)); } else if (style == SW_STYLE_LOWERLIMITS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_UPPERLIMITS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_DOTS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if (style == SW_STYLE_IMPULSES ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); UUUBF(a2); } else if (style == SW_STYLE_WBOXES ) { UUC(a2, UUR(1)); UUE(a1, UUR(0)); UUD(a1, UUR(0)-UUR(2)); UUD(a1, UUR(0)+UUR(2)); UUU(a2, UUR(1)); UUU(a1, UUR(0)); UUU(a1, UUR(0)-UUR(2)); UUU(a1, UUR(0)+UUR(2)); UUUBF(a2); } else if (style == SW_STYLE_STARS ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if ((style == SW_STYLE_ARROWS_HEAD) || (style == SW_STYLE_ARROWS_NOHEAD) || (style == SW_STYLE_ARROWS_TWOHEAD)) { UUC(a1, UUR(0 )); UUC(a2, UUR(1 )); if (ThreeDim) UUC(a3, UUR(2)); UUD(a1, UUR(2+ThreeDim)); UUC(a2, UUR(3+ThreeDim)); if (ThreeDim) UUC(a3, UUR(5)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); UUU(a1, UUR(2+ThreeDim)); UUU(a2, UUR(3+ThreeDim)); if (ThreeDim) { UUU(a3, UUR(2)); UUU(a3, UUR(5)); } } else if (style == SW_STYLE_SURFACE ) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); if (ThreeDim) UUC(a3, UUR(2)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); if (ThreeDim) UUU(a3, UUR(2)); } else if ((style == SW_STYLE_COLORMAP) || (style == SW_STYLE_CONTOURMAP)) { UUC(a1, UUR(0)); UUC(a2, UUR(1)); UUU(a1, UUR(0)); UUU(a2, UUR(1)); } else if ((style == SW_STYLE_BOXES) || (style == SW_STYLE_STEPS) || (style == SW_STYLE_FSTEPS) || (style == SW_STYLE_HISTEPS)) { // Boxes and steps need slightly more complicated logic to take into account finite width of boxes/steps #define FINISH_FACTORING_BOXES \ { \ /* Logic to take account of final boxes/steps */ \ if (ptCset && ((style == SW_STYLE_BOXES) || (style == SW_STYLE_STEPS) || (style == SW_STYLE_FSTEPS) || (style == SW_STYLE_HISTEPS))) \ { \ unsigned char logaxis = (a1->LogFinal==SW_BOOL_TRUE); \ UUC_RESET; \ UUC(a2, lasty); \ if (ptBset) /* We have one final box/step to process */ \ { \ if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { UUF(a1, (ptCx - (ptCx-ptBx)/2 )); UUF(a1, (ptCx + (ptCx-ptBx)/2 )); UUUBF(a2); } \ else if (style == SW_STYLE_BOXES) { UUF(a1, (ptCx - sg->BoxWidth.real/2)); UUF(a1, (ptCx + sg->BoxWidth.real/2)); UUUBF(a2); } \ else if (style == SW_STYLE_HISTEPS) { UUF(a1, (ptCx - (ptCx-ptBx)/2 )); UUF(a1, (ptCx + (ptCx-ptBx)/2 )); } \ else if (style == SW_STYLE_STEPS) { UUF(a1, ((ptBx+ptCx)/2 - (ptCx-ptBx)/2)); UUF(a1, ((ptBx+ptCx)/2 + (ptCx-ptBx)/2)); } \ else if (style == SW_STYLE_FSTEPS) { UUF(a1, ptCx); } \ } \ else if (ptCset) /* We have a dataset with only a single box/step */ \ { \ if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { UUF(a1, (ptCx - 0.5)); UUF(a1, (ptCx + 0.5)); UUUBF(a2); } \ else if (style == SW_STYLE_BOXES) { UUF(a1, (ptCx - sg->BoxWidth.real/2)); UUF(a1, (ptCx + sg->BoxWidth.real/2)); UUUBF(a2); } \ else if (sg->BoxWidth.real<1e-200) { UUF(a1, (ptCx - 0.5)); UUF(a1, (ptCx + 0.5)); } \ else { UUF(a1, (ptCx - sg->BoxWidth.real/2)); UUF(a1, (ptCx + sg->BoxWidth.real/2)); } \ } \ } \ } unsigned char logaxis = (a1->LogFinal==SW_BOOL_TRUE); if (blk->split[j]) { FINISH_FACTORING_BOXES; } UUC(a2, UUR(1)); // y-coordinates are easy ptAx=ptBx; ptAset=ptBset; ptBx=ptCx; ptBset=ptCset; ptCx=logaxis?log(UUR(0)):(UUR(0)); ptCset=1; if (ptBset) { if (ptAset) // We are processing a box in the midst of many { if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { UUF(a1, ((ptBx+(ptAx+ptCx)/2)/2 - (ptCx-ptAx)/4)); UUF(a1, ((ptBx+(ptAx+ptCx)/2)/2 + (ptCx-ptAx)/4)); UUUBF(a2); } else if (style == SW_STYLE_BOXES) { UUF(a1, (ptBx - sg->BoxWidth.real/2)); UUF(a1, (ptBx + sg->BoxWidth.real/2)); UUUBF(a2); } else if (style == SW_STYLE_HISTEPS) { UUF(a1, ((ptBx+(ptAx+ptCx)/2)/2 - (ptCx-ptAx)/4)); UUF(a1, ((ptBx+(ptAx+ptCx)/2)/2 + (ptCx-ptAx)/4)); UUUBF(a2); } else if (style == SW_STYLE_STEPS) { UUF(a1, ((ptAx+ptBx)/2 - (ptBx-ptAx)/2)); UUF(a1, ((ptAx+ptBx)/2 + (ptBx-ptAx)/2)); } else if (style == SW_STYLE_FSTEPS) { UUF(a1, ((ptBx+ptCx)/2 - (ptCx-ptBx)/2)); UUF(a1, ((ptBx+ptCx)/2 + (ptCx-ptBx)/2)); } } else // The first box/step we work out the width of { if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { UUF(a1, (ptBx - (ptCx-ptBx)/2)); UUF(a1, (ptBx + (ptCx-ptBx)/2)); UUUBF(a2); } else if (style == SW_STYLE_BOXES) { UUF(a1, (ptBx - sg->BoxWidth.real/2)); UUF(a1, (ptBx + sg->BoxWidth.real/2)); UUUBF(a2); } else if (style == SW_STYLE_HISTEPS) { UUF(a1, (ptBx - (ptCx-ptBx)/2)); UUF(a1, (ptBx + (ptCx-ptBx)/2)); } else if (style == SW_STYLE_STEPS) { UUF(a1, ptBx); } else if (style == SW_STYLE_FSTEPS) { UUF(a1, ((ptBx+ptCx)/2 - (ptCx-ptBx)/2)); UUF(a1, ((ptBx+ptCx)/2 + (ptCx-ptBx)/2)); } } } UUU(a2, UUR(1)); // y-coordinates are easy lasty = UUR(1); } i++; } blk=blk->next; } FINISH_FACTORING_BOXES; return 0; } // Render a dataset to postscript int eps_plot_dataset(EPSComm *x, dataTable *data, int style, unsigned char ThreeDim, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, double origin_x, double origin_y, double width, double height, double zdepth) { int i, j, Ncolumns, Ncol_obj, pt=0, xrn, yrn, zrn; double xpos, ypos, depth, xap, yap, zap, scale_x, scale_y, scale_z; char epsbuff[FNAME_LENGTH], *last_colstr=NULL; LineDrawHandle *ld; pplset_axis *a[3] = {a1,a2,a3}; dataBlock *blk; if ((data==NULL) || (data->Nrows<1)) { char *output = x->c->errcontext.tempErrStr; int i = 0; sprintf(output+i,"plotted item"); i+=strlen(output+i); if (!pd->function) { if (pd->filename != NULL) { output[i++]=' '; ppl_strEscapify(pd->filename, output+i); i+=strlen(output+i); // Filename of datafile we are plotting } else if (pd->vectors != NULL) { for (j=0; jNFunctions; j++) // Print out the list of functions which we are plotting { output[i++]=(j!=0)?':':' '; pplObjPrint(x->c,&pd->vectors[j],NULL,output+i,ppl_min(250,LSTR_LENGTH-i),0,0); i+=strlen(output+i); } } } else for (j=0; jNFunctions; j++) // Print out the list of functions which we are plotting { output[i++]=(j!=0)?':':' '; ppl_strStrip(pd->functions[j]->ascii , output+i); i+=strlen(output+i); } sprintf(output+i," produced no data."); ppl_warning(&x->c->errcontext,ERR_NUMERICAL,NULL); return 0; // No data present } Ncolumns = data->Ncolumns_real; Ncol_obj = data->Ncolumns_obj; if (eps_plot_WithWordsCheckUsingItemsDimLess(x->c, &pd->ww_final, data->firstEntries, Ncolumns, Ncol_obj, NULL)) return 1; if (!ThreeDim) { scale_x=width; scale_y=height; scale_z=1.0; } else { scale_x=width; scale_y=height; scale_z=zdepth; } // If axes have value-turning points, loop over all monotonic regions of axis space for (xrn=0; xrn<=a[xn]->AxisValueTurnings; xrn++) for (yrn=0; yrn<=a[yn]->AxisValueTurnings; yrn++) for (zrn=0; zrn<=(ThreeDim ? a[zn]->AxisValueTurnings : 0); zrn++) { blk = data->first; if ((style == SW_STYLE_LINES) || (style == SW_STYLE_LINESPOINTS)) // LINES { ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); if (blk->split[j]) { LineDraw_PenUp(x, ld); } IF_NOT_INVISIBLE { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } LineDraw_Point(x, ld, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); } else { LineDraw_PenUp(x, ld); } } blk=blk->next; } LineDraw_PenUp(x, ld); } if ((style == SW_STYLE_POINTS) || (style == SW_STYLE_LINESPOINTS) || (style == SW_STYLE_STARS) || (style == SW_STYLE_DOTS)) // POINTS, DOTS, STARS { last_colstr=NULL; blk = data->first; while (blk != NULL) { for (j=0; jblockPosition; j++) { double final_pointsize=0.0; eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, NULL, NULL, NULL, ThreeDim, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 0); if (!gsl_finite(xpos)) // Position of point is off side of graph { if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) x->LaTeXpageno++; continue; } // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); final_pointsize = pd->ww_final.pointsize; if (style == SW_STYLE_DOTS ) final_pointsize *= 0.05; // Dots are 1/20th size of points else if (style == SW_STYLE_STARS) final_pointsize *= 12.0 ; // Stars are BIG eps_core_SetColor(x, &pd->ww_final, 0); IF_NOT_INVISIBLE { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } if (style != SW_STYLE_STARS) { pt = (style == SW_STYLE_DOTS) ? 16 : ((pd->ww_final.pointtype-1) % N_POINTTYPES); // Dots are always pt 17 (filled circle) while (pt<0) pt+=N_POINTTYPES; x->PointTypesUsed[pt] = 1; sprintf(epsbuff, "%.2f %.2f pt%d", xpos, ypos, pt+1); eps_core_BoundingBox(x, xpos, ypos, 2 * final_pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS); } else { pt = ((pd->ww_final.pointtype-1) % N_STARTYPES); while (pt<0) pt+=N_STARTYPES; x->StarTypesUsed[pt] = 1; sprintf(epsbuff, "/angle { 40 } def %.2f %.2f st%d", xpos, ypos, pt+1); eps_core_BoundingBox(x, xpos, ypos, 2 * final_pointsize * eps_StarSize[pt] * EPS_DEFAULT_PS); } ThreeDimBuffer_writeps(x, depth, 1, pd->ww_final.pointlinewidth, 0.0, final_pointsize, last_colstr, epsbuff); } // label point if instructed to do so if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) { char *text = NULL; const double xsp = (x->current->settings.TextVAlign == SW_VALIGN_CENT) ? 1.7 : 1.13; const double ysp = (x->current->settings.TextHAlign == SW_HALIGN_CENT) ? 1.7 : 1.13; if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } canvas_EPSRenderTextItem(x, &text, x->LaTeXpageno++, xpos/M_TO_PS - (x->current->settings.TextHAlign - SW_HALIGN_CENT) * final_pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS / M_TO_PS * xsp, ypos/M_TO_PS + (x->current->settings.TextVAlign - SW_VALIGN_CENT) * final_pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS / M_TO_PS * ysp, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth, 1, 1, 0, 1, last_colstr, text); } } blk=blk->next; } } if ((style == SW_STYLE_XERRORBARS) || (style == SW_STYLE_YERRORBARS) || (style == SW_STYLE_ZERRORBARS) || (style == SW_STYLE_XYERRORBARS) || (style == SW_STYLE_YZERRORBARS) || (style == SW_STYLE_XZERRORBARS) || (style == SW_STYLE_XYZERRORBARS) || (style == SW_STYLE_XERRORRANGE) || (style == SW_STYLE_YERRORRANGE) || (style == SW_STYLE_ZERRORRANGE) || (style == SW_STYLE_XYERRORRANGE) || (style == SW_STYLE_YZERRORRANGE) || (style == SW_STYLE_XZERRORRANGE) || (style == SW_STYLE_XYZERRORRANGE)) // XERRORBARS , YERRORBARS , ZERRORBARS { unsigned char ac[3]={0,0,0}; double b,ps,min[3],max[3]; int NDirections=0; b = 0.0005 * sg->bar; ps = pd->ww_final.pointsize * EPS_DEFAULT_PS / M_TO_PS; ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); LineDraw_PenUp(x, ld); IF_NOT_INVISIBLE { for (i=0;i<3;i++) { min[i]=max[i]=UUR(i); } if (style == SW_STYLE_XERRORBARS ) { NDirections = 1; ac[0]=1; min[0] = UUR(0) - UUR(2+ThreeDim); max[0] = UUR(0) + UUR(2+ThreeDim); } else if (style == SW_STYLE_YERRORBARS ) { NDirections = 1; ac[1]=1; min[1] = UUR(1) - UUR(2+ThreeDim); max[1] = UUR(1) + UUR(2+ThreeDim); } else if (style == SW_STYLE_ZERRORBARS ) { NDirections = 1; ac[2]=1; min[2] = UUR(2) - UUR(3 ); max[2] = UUR(2) + UUR(3 ); } else if (style == SW_STYLE_XERRORRANGE ) { NDirections = 1; ac[0]=1; min[0] = UUR(2+ThreeDim); max[0] = UUR(3+ThreeDim); } else if (style == SW_STYLE_YERRORRANGE ) { NDirections = 1; ac[1]=1; min[1] = UUR(2+ThreeDim); max[1] = UUR(3+ThreeDim); } else if (style == SW_STYLE_ZERRORRANGE ) { NDirections = 1; ac[2]=1; min[2] = UUR(3 ); max[2] = UUR(4 ); } else if (style == SW_STYLE_XYERRORBARS ) { NDirections = 2; ac[0]=ac[1]=1; min[0] = UUR(0) - UUR(2+ThreeDim); max[0] = UUR(0) + UUR(2+ThreeDim); min[1] = UUR(1) - UUR(3+ThreeDim); max[1] = UUR(1) + UUR(3+ThreeDim); } else if (style == SW_STYLE_XZERRORBARS ) { NDirections = 2; ac[0]=ac[2]=1; min[0] = UUR(0) - UUR(3 ); max[0] = UUR(0) + UUR(3 ); min[2] = UUR(2) - UUR(4 ); max[2] = UUR(2) + UUR(4 ); } else if (style == SW_STYLE_YZERRORBARS ) { NDirections = 2; ac[1]=ac[2]=1; min[1] = UUR(1) - UUR(3 ); max[1] = UUR(1) + UUR(3 ); min[2] = UUR(2) - UUR(4 ); max[2] = UUR(2) + UUR(4 ); } else if (style == SW_STYLE_XYERRORRANGE ) { NDirections = 2; ac[0]=ac[1]=1; min[0] = UUR(2+ThreeDim); max[0] = UUR(3+ThreeDim); min[1] = UUR(4+ThreeDim); max[1] = UUR(5+ThreeDim); } else if (style == SW_STYLE_YZERRORRANGE ) { NDirections = 2; ac[1]=ac[2]=1; min[1] = UUR(3 ); max[1] = UUR(4 ); min[2] = UUR(5 ); max[2] = UUR(6 ); } else if (style == SW_STYLE_XZERRORRANGE ) { NDirections = 2; ac[0]=ac[2]=1; min[0] = UUR(3 ); max[0] = UUR(4 ); min[2] = UUR(5 ); max[2] = UUR(6 ); } else if (style == SW_STYLE_XYZERRORBARS ) { NDirections = 3; ac[0]=ac[1]=ac[2]=1; min[0] = UUR(0) - UUR(3); max[0] = UUR(0) + UUR(3); min[1] = UUR(1) - UUR(4); max[1] = UUR(1) + UUR(4); min[2] = UUR(2) - UUR(5); max[2] = UUR(2) + UUR(6); } else if (style == SW_STYLE_XYZERRORRANGE) { NDirections = 3; ac[0]=ac[1]=ac[2]=1; min[0] = UUR(3); max[0] = UUR(4); min[1] = UUR(5); max[1] = UUR(6); min[2] = UUR(7); max[2] = UUR(8); } if (a[0]->LogFinal==SW_BOOL_TRUE) { if (min[0]LogFinal==SW_BOOL_TRUE) { if (min[1]LogFinal==SW_BOOL_TRUE) { if (min[2]CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } for (i=0; i<3; i++) if (ac[i]) { LineDraw_Point(x, ld, (i==xn)?(min[xn]):(UUR(xn)), (i==yn)?(min[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(min[zn]):(UUR(zn))) : 0.0, 0,0,0, (i==xn)?( b ):0, (i==yn)?( b ):0, (i==zn)?( b ):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_Point(x, ld, (i==xn)?(min[xn]):(UUR(xn)), (i==yn)?(min[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(min[zn]):(UUR(zn))) : 0.0, 0,0,0, (i==xn)?(-b ):0, (i==yn)?(-b ):0, (i==zn)?(-b ):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_PenUp(x, ld); LineDraw_Point(x, ld, (i==xn)?(min[xn]):(UUR(xn)), (i==yn)?(min[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(min[zn]):(UUR(zn))) : 0.0, 0,0,0, 0, 0, 0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_Point(x, ld, (i==xn)?(max[xn]):(UUR(xn)), (i==yn)?(max[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(max[zn]):(UUR(zn))) : 0.0, 0,0,0, 0, 0, 0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_PenUp(x, ld); LineDraw_Point(x, ld, (i==xn)?(max[xn]):(UUR(xn)), (i==yn)?(max[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(max[zn]):(UUR(zn))) : 0.0, 0,0,0, (i==xn)?( b ):0, (i==yn)?( b ):0, (i==zn)?( b ):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_Point(x, ld, (i==xn)?(max[xn]):(UUR(xn)), (i==yn)?(max[yn]):(UUR(yn)), ThreeDim ? ((i==zn)?(max[zn]):(UUR(zn))) : 0.0, 0,0,0, (i==xn)?(-b ):0, (i==yn)?(-b ):0, (i==zn)?(-b ):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_PenUp(x, ld); if (NDirections!=1) continue; // Only put a central bar through errorbars which only go in a single direction LineDraw_Point(x, ld, (UUR(xn)), (UUR(yn)), ThreeDim ? ( UUR(zn) ) : 0.0, 0,0,0, (i==xn)?( ps):0, (i==yn)?( ps):0, (i==zn)?( ps):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_Point(x, ld, (UUR(xn)), (UUR(yn)), ThreeDim ? ( UUR(zn) ) : 0.0, 0,0,0, (i==xn)?(-ps):0, (i==yn)?(-ps):0, (i==zn)?(-ps):0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_PenUp(x, ld); } } // label point if instructed to do so if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) { char *text=NULL; if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, NULL, NULL, NULL, ThreeDim, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 0); if (!gsl_finite(xpos)) { x->LaTeXpageno++; continue; } // Position of point is off side of graph canvas_EPSRenderTextItem(x, &text, x->LaTeXpageno++, xpos/M_TO_PS, ypos/M_TO_PS, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth, 1, 1, 0, 1, last_colstr, text); } } blk=blk->next; } } else if (style == SW_STYLE_IMPULSES ) // IMPULSES { ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; if (a[yn]->DataUnitSet && (!ppl_unitsDimEqual(&sg->BoxFrom, &a[yn]->DataUnit))) { sprintf(x->c->errcontext.tempErrStr, "Data with units of <%s> plotted with impulses when BoxFrom is set to a value with units of <%s>.", ppl_printUnit(x->c,&a[yn]->DataUnit,NULL,NULL,0,1,0), ppl_printUnit(x->c,&sg->BoxFrom,NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1, NULL); } else { while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); LineDraw_PenUp(x, ld); IF_NOT_INVISIBLE { double boxfrom = sg->BoxFrom.real; if ((a[yn]->LogFinal==SW_BOOL_TRUE) && (boxfromCurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } LineDraw_Point(x, ld, (xn==1)?boxfrom:(UUR(xn)), (yn==1)?boxfrom:(UUR(yn)), ThreeDim ? ((zn==1)?boxfrom:(UUR(zn))) : 0.0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); LineDraw_Point(x, ld, UUR(xn) , UUR(yn) , ThreeDim ? UUR(zn) : 0.0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); } LineDraw_PenUp(x, ld); // label point if instructed to do so if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) { char *text=NULL; if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, NULL, NULL, NULL, ThreeDim, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 0); if (!gsl_finite(xpos)) { x->LaTeXpageno++; continue; } // Position of point is off side of graph canvas_EPSRenderTextItem(x, &text, x->LaTeXpageno++, xpos/M_TO_PS, ypos/M_TO_PS, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth, 1, 1, 0, 1, last_colstr, text); } } blk=blk->next; } } } else if ((style == SW_STYLE_LOWERLIMITS) || (style == SW_STYLE_UPPERLIMITS)) // LOWERLIMITS, UPPERLIMITS { int an; double ps, sgn, lw, theta[3], x2, y2, x3, y3, x4, y4, x5, y5; double offset_barx, offset_bary, offset_arrx, offset_arry; ps = pd->ww_final.pointsize * EPS_DEFAULT_PS / M_TO_PS; sgn = ( (style == SW_STYLE_UPPERLIMITS) ^ (a[yn]->MaxFinal > a[yn]->MinFinal) ) ? 1.0 : -1.0; lw = pd->ww_final.pointlinewidth; ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); LineDraw_PenUp(x, ld); IF_NOT_INVISIBLE { eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, &theta[0], &theta[1], &theta[2], ThreeDim, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 0); if (!gsl_finite(xpos)) // Position of point is off side of graph { if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) x->LaTeXpageno++; continue; } if (xn==1) an=0; else if (yn==1) an=1; else an=2; if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } offset_barx = ps * sin(theta[an] + M_PI/2); offset_bary = ps * cos(theta[an] + M_PI/2); offset_arrx = sgn*2*ps * sin(theta[an]); offset_arry = sgn*2*ps * cos(theta[an]); LineDraw_Point(x, ld, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0,-offset_barx,-offset_bary,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_Point(x, ld, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, offset_barx, offset_bary,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_PenUp(x, ld); LineDraw_Point(x, ld, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, 0, 0,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_Point(x, ld, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, offset_arrx, offset_arry,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_PenUp(x, ld); x2 = xpos + sgn*2*ps*M_TO_PS * sin(theta[an]); y2 = ypos + sgn*2*ps*M_TO_PS * cos(theta[an]); if (sgn<0.0) theta[an] += M_PI; x3 = x2 - EPS_ARROW_HEADSIZE/2 * lw * sin(theta[an] - EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on one side y3 = y2 - EPS_ARROW_HEADSIZE/2 * lw * cos(theta[an] - EPS_ARROW_ANGLE / 2); x5 = x2 - EPS_ARROW_HEADSIZE/2 * lw * sin(theta[an] + EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on other side y5 = y2 - EPS_ARROW_HEADSIZE/2 * lw * cos(theta[an] + EPS_ARROW_ANGLE / 2); x4 = x2 - EPS_ARROW_HEADSIZE/2 * lw * sin(theta[an]) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); // Point where back of arrowhead crosses stalk y4 = y2 - EPS_ARROW_HEADSIZE/2 * lw * cos(theta[an]) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); sprintf(epsbuff, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x4,y4,x3,y3,x2,y2,x5,y5); ThreeDimBuffer_writeps(x, depth, 1, lw, 0.0, 1.0, last_colstr, epsbuff); } // label point if instructed to do so if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) { char *text=NULL; if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } canvas_EPSRenderTextItem(x, &text, x->LaTeXpageno++, xpos/M_TO_PS, ypos/M_TO_PS, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth, 1, 1, 0, 1, last_colstr, text); } } blk=blk->next; } } else if ((style == SW_STYLE_BOXES) || (style == SW_STYLE_WBOXES) || (style == SW_STYLE_STEPS) || (style == SW_STYLE_FSTEPS) || (style == SW_STYLE_HISTEPS)) // BOXES, WBOXES, STEPS, FSTEPS, HISTEPS { double ptAx, ptBx=0, ptBy=0, ptCx=0, ptCy=0; unsigned char ptAset=0, ptBset=0, ptCset=0; ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; #define MAKE_STEP(X0,Y0,WIDTH) \ IF_NOT_INVISIBLE \ { \ double pA[3]={(X0)-(WIDTH),(Y0),0}, pB[3]={(X0)+(WIDTH),(Y0),0}; \ if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } \ if (logaxis) { pA[0]=exp(pA[0]); pB[0]=exp(pB[0]); } \ LineDraw_Point(x, ld, pA[xn], pA[yn], ThreeDim?(pA[zn]):0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_Point(x, ld, pB[xn], pB[yn], ThreeDim?(pB[zn]):0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ } \ #define MAKE_BOX(X0,Y0,WIDTH) \ { \ int an; \ double pA[3] = {(X0)-(WIDTH), sg->BoxFrom.real, 0}; \ double pB[3] = {(X0)-(WIDTH), (Y0) , 0}; \ double pC[3] = {(X0)+(WIDTH), (Y0) , 0}; \ double pD[3] = {(X0)+(WIDTH), sg->BoxFrom.real, 0}; \ if (logaxis) { pA[0]=exp(pA[0]); pB[0]=exp(pB[0]); pC[0]=exp(pC[0]); pD[0]=exp(pD[0]); } \ if (xn==1) an=0; else if (yn==1) an=1; else an=2; \ if ((a[an]->LogFinal==SW_BOOL_TRUE) && (pA[1]LogFinal==SW_BOOL_TRUE) && (pB[1]LogFinal==SW_BOOL_TRUE) && (pC[1]LogFinal==SW_BOOL_TRUE) && (pD[1]ww_final); \ eps_core_SwitchTo_FillColor(x,0); \ \ /* Fill box */ \ IF_NOT_INVISIBLE if (!ThreeDim) \ { \ FilledRegionHandle *fr; \ fr = FilledRegion_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); \ FilledRegion_Point(x, fr, pA[xn], pA[yn]); \ FilledRegion_Point(x, fr, pB[xn], pB[yn]); \ FilledRegion_Point(x, fr, pC[xn], pC[yn]); \ FilledRegion_Point(x, fr, pD[xn], pD[yn]); \ FilledRegion_Finish(x, fr, pd->ww_final.linetype, pd->ww_final.linewidth, 0); \ } \ eps_core_SwitchFrom_FillColor(x,0); \ \ /* Stroke outline of box */ \ IF_NOT_INVISIBLE \ { \ if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } \ LineDraw_Point(x, ld, pA[xn], pA[yn], ThreeDim?pA[zn]:0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_Point(x, ld, pB[xn], pB[yn], ThreeDim?pB[zn]:0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_Point(x, ld, pC[xn], pC[yn], ThreeDim?pC[zn]:0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_Point(x, ld, pD[xn], pD[yn], ThreeDim?pD[zn]:0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_Point(x, ld, pA[xn], pA[yn], ThreeDim?pA[zn]:0, 0,0,0,0,0,0, pd->ww_final.linetype, pd->ww_final.linewidth, last_colstr); \ LineDraw_PenUp(x, ld); \ } \ } \ #define FINISH_ROW_OF_BOXES \ { \ if (ptBset) /*/ We have one final box/step to process */ \ { \ if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { MAKE_BOX ( ptCx , ptCy, (ptCx-ptBx)/2 ); } \ else if (style == SW_STYLE_BOXES) { MAKE_BOX ( ptCx , ptCy, sg->BoxWidth.real/2); } \ else if (style == SW_STYLE_HISTEPS) { MAKE_STEP( ptCx , ptCy, (ptCx-ptBx)/2 ); } \ else if (style == SW_STYLE_STEPS) { MAKE_STEP((ptBx+ptCx)/2, ptCy, (ptCx-ptBx)/2); } \ else if (style == SW_STYLE_FSTEPS) { MAKE_STEP( ptCx , ptCy, 0.0 ); } \ } \ else if (ptCset) /* We have a dataset with only a single box/step */ \ { \ if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { MAKE_BOX (ptCx, ptCy, 0.5); } \ else if (style == SW_STYLE_BOXES) { MAKE_BOX (ptCx, ptCy, sg->BoxWidth.real/2); } \ else if (sg->BoxWidth.real<1e-200) { MAKE_STEP(ptCx, ptCy, 0.5); } \ else { MAKE_STEP(ptCx, ptCy, sg->BoxWidth.real/2); } \ } \ ptAset = ptBset = ptCset = 0; \ LineDraw_PenUp(x, ld); \ } \ if (a[yn]->DataUnitSet && (!ppl_unitsDimEqual(&sg->BoxFrom, &a[yn]->DataUnit))) { sprintf(x->c->errcontext.tempErrStr, "Data with units of <%s> plotted as boxes/steps when BoxFrom is set to a value with units of <%s>.", ppl_printUnit(x->c,&a[yn]->DataUnit,NULL,NULL,0,1,0), ppl_printUnit(x->c,&sg->BoxFrom,NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1, NULL); } else if (a[xn]->DataUnitSet && (sg->BoxWidth.real>0.0) && (!ppl_unitsDimEqual(&sg->BoxWidth, &a[xn]->DataUnit))) { sprintf(x->c->errcontext.tempErrStr, "Data with ordinate units of <%s> plotted as boxes/steps when BoxWidth is set to a value with units of <%s>.", ppl_printUnit(x->c,&a[xn]->DataUnit,NULL,NULL,0,1,0), ppl_printUnit(x->c,&sg->BoxWidth,NULL,NULL,1,1,0)); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1, NULL); } else { unsigned char logaxis = (a[xn]->LogFinal==SW_BOOL_TRUE); while (blk != NULL) { for (j=0; jblockPosition; j++) { if (blk->split[j]) { FINISH_ROW_OF_BOXES; } ptAx=ptBx; ptAset=ptBset; ptBx=ptCx; ptBy=ptCy; ptBset=ptCset; ptCx=logaxis?log(UUR(0)):(UUR(0)); ptCy=UUR(1); ptCset=1; if (ptBset) { if (ptAset) // We are processing a box in the midst of many { if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { MAKE_BOX ((ptBx+(ptAx+ptCx)/2)/2, ptBy, (ptCx-ptAx)/4 ); } else if (style == SW_STYLE_BOXES) { MAKE_BOX ( ptBx , ptBy, sg->BoxWidth.real/2); } else if (style == SW_STYLE_HISTEPS) { MAKE_STEP((ptBx+(ptAx+ptCx)/2)/2, ptBy, (ptCx-ptAx)/4 ); } else if (style == SW_STYLE_STEPS) { MAKE_STEP((ptAx+ptBx)/2, ptBy, (ptBx-ptAx)/2); } else if (style == SW_STYLE_FSTEPS) { MAKE_STEP((ptBx+ptCx)/2, ptBy, (ptCx-ptBx)/2); } } else // The first box/step we work out the width of { if ((style == SW_STYLE_BOXES) && (sg->BoxWidth.real<1e-200)) { MAKE_BOX ( ptBx , ptBy, (ptCx-ptBx)/2 ); } else if (style == SW_STYLE_BOXES) { MAKE_BOX ( ptBx , ptBy, sg->BoxWidth.real/2); } else if (style == SW_STYLE_HISTEPS) { MAKE_STEP( ptBx , ptBy, (ptCx-ptBx)/2 ); } else if (style == SW_STYLE_STEPS) { MAKE_STEP( ptBx , ptBy, 0.0 ); } else if (style == SW_STYLE_FSTEPS) { MAKE_STEP((ptBx+ptCx)/2, ptBy, (ptCx-ptBx)/2); } } } // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); if (style == SW_STYLE_WBOXES) { MAKE_BOX(ptCx, ptCy, UUR(2)/2); } } blk=blk->next; } FINISH_ROW_OF_BOXES; } LineDraw_PenUp(x, ld); } else if ((style == SW_STYLE_ARROWS_HEAD) || (style == SW_STYLE_ARROWS_NOHEAD) || (style == SW_STYLE_ARROWS_TWOHEAD)) // ARROWS_HEAD, ARROWS_NOHEAD, ARROWS_TWOHEAD { double xpos2,ypos2,depth2,xap2,yap2,zap2,lw,theta; lw = pd->ww_final.linewidth; ld = LineDraw_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); last_colstr=NULL; while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); eps_core_SetColor(x, &pd->ww_final, 0); LineDraw_PenUp(x, ld); IF_NOT_INVISIBLE { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } LineDraw_Point(x, ld, UUR(xn ), UUR(yn ), ThreeDim ? UUR(zn ) : 0.0, 0,0,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_Point(x, ld, UUR(xn+2+ThreeDim), UUR(yn+2+ThreeDim), ThreeDim ? UUR(zn+3) : 0.0, 0,0,0,0,0,0, pd->ww_final.linetype, lw, last_colstr); LineDraw_PenUp(x, ld); eps_plot_GetPosition(&xpos , &ypos , &depth , &xap , &yap , &zap , NULL, NULL, NULL, ThreeDim, UUR(xn ), UUR(yn ), ThreeDim ? UUR(zn ) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 1); eps_plot_GetPosition(&xpos2, &ypos2, &depth2, &xap2, &yap2, &zap2, NULL, NULL, NULL, ThreeDim, UUR(xn+2+ThreeDim), UUR(yn+2+ThreeDim), ThreeDim ? UUR(zn+3) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 1); if ((!gsl_finite(xpos))||(!gsl_finite(ypos))||(!gsl_finite(xpos2))||(!gsl_finite(ypos2)) || (ThreeDim&&((!gsl_finite(depth))||(!gsl_finite(depth2)))) ) { if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) x->LaTeXpageno++; continue; } theta = atan2(xpos2-xpos,ypos2-ypos); if (!gsl_finite(theta)) theta=0.0; if ((style == SW_STYLE_ARROWS_TWOHEAD) && (xap>=0.0)&&(xap<=1.0)&&(yap>=0.0)&&(yap<=1.0)&&((!ThreeDim)||((zap>=0.0)&&(zap<=1.0)))) { double x2=xpos, y2=ypos, x3, y3, x4, y4, x5, y5, theta_y = theta + M_PI; x3 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y - EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on one side y3 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y - EPS_ARROW_ANGLE / 2); x5 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y + EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on other side y5 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y + EPS_ARROW_ANGLE / 2); x4 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); // Point where back of arrowhead crosses stalk y4 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); sprintf(epsbuff, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x4,y4,x3,y3,x2,y2,x5,y5); ThreeDimBuffer_writeps(x, depth, 1, lw, 0.0, 1.0, last_colstr, epsbuff); } if (((style == SW_STYLE_ARROWS_TWOHEAD) || (style == SW_STYLE_ARROWS_HEAD)) && (xap2>=0.0)&&(xap2<=1.0)&&(yap2>=0.0)&&(yap2<=1.0)&&((!ThreeDim)||((zap2>=0.0)&&(zap2<=1.0)))) { double x2=xpos2, y2=ypos2, x3, y3, x4, y4, x5, y5, theta_y = theta; x3 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y - EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on one side y3 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y - EPS_ARROW_ANGLE / 2); x5 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y + EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on other side y5 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y + EPS_ARROW_ANGLE / 2); x4 = x2 - EPS_ARROW_HEADSIZE * lw * sin(theta_y) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); // Point where back of arrowhead crosses stalk y4 = y2 - EPS_ARROW_HEADSIZE * lw * cos(theta_y) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); sprintf(epsbuff, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x4,y4,x3,y3,x2,y2,x5,y5); ThreeDimBuffer_writeps(x, depth2, 1, lw, 0.0, 1.0, last_colstr, epsbuff); } } // label point if instructed to do so if ((blk->text[j] != NULL) && (blk->text[j][0] != '\0')) { char *text=NULL; if ((xap2<0.0)||(xap2>1.0)||(yap2<0.0)||(yap2>1.0)||(ThreeDim&&((zap2<0.0)||(zap2>1.0)))) { x->LaTeXpageno++; continue; } if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } canvas_EPSRenderTextItem(x, &text, x->LaTeXpageno++, xpos2/M_TO_PS, ypos2/M_TO_PS, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth2, 1, 1, 0, 1, last_colstr, text); } } blk=blk->next; } } else if (style == SW_STYLE_FILLEDREGION) // FILLEDREGION { FilledRegionHandle *fr; fr = FilledRegion_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); while (blk != NULL) { for (j=0; jblockPosition; j++) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); FilledRegion_Point(x, fr, UUR(xn), UUR(yn)); } blk=blk->next; } eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetFillColor(x, &pd->ww_final); eps_core_SwitchTo_FillColor(x,0); FilledRegion_Finish(x, fr, pd->ww_final.linetype, pd->ww_final.linewidth, 1); eps_core_SwitchFrom_FillColor(x,1); } else if (style == SW_STYLE_YERRORSHADED) // YERRORSHADED { FilledRegionHandle *fr; int BlkNo=0; fr = FilledRegion_Init(x, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, ThreeDim, origin_x, origin_y, scale_x, scale_y, scale_z); // First add all of the points along the tops of the error bars, moving from left to right while (blk != NULL) { for (j=0; jblockPosition; j++) FilledRegion_Point(x, fr, UUR(xn), UUR(yn)); blk=blk->next; BlkNo++; } // Now add the points along the bottoms of all of the error bars, moving from right to left for (BlkNo-- ; BlkNo>=0; BlkNo--) { blk = data->first; for (j=0; jnext; for (j=blk->blockPosition-1; j>=0; j--) { // Work out style information for next point eps_plot_WithWordsFromUsingItems(x->c, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); if (xn==0) FilledRegion_Point(x, fr, UUR(0), UUR(2)); else FilledRegion_Point(x, fr, UUR(2), UUR(0)); } } eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetFillColor(x, &pd->ww_final); eps_core_SwitchTo_FillColor(x,0); FilledRegion_Finish(x, fr, pd->ww_final.linetype, pd->ww_final.linewidth, 1); eps_core_SwitchFrom_FillColor(x,1); } else if ((style == SW_STYLE_SURFACE)&&(xrn==0)&&(yrn==0)&&(zrn==0)) // SURFACE { int fill; int XSize = pd->GridXSize; int YSize = pd->GridYSize; long X,Y; long j; double xap,yap,zap,theta_x,theta_y,theta_z,depth; double x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4; #define SURFACE_POINT(XO,YO,ZO) \ eps_plot_GetPosition(&XO,&YO,&ZO, &xap, &yap, &zap, &theta_x, &theta_y, &theta_z, ThreeDim, UUR(xn), UUR(yn), ThreeDim ? UUR(zn) : 0.0, a[xn], a[yn], a[zn], xrn, yrn, zrn, sg, origin_x, origin_y, scale_x, scale_y, scale_z, 1); \ if ((xap<0)||(xap>1)||(yap<0)||(yap>1)||(zap<0)||(zap>1)) continue; \ if ( (!gsl_finite(XO))||(!gsl_finite(YO))||(!gsl_finite(ZO)) ) continue; if (blk->blockPosition != ((long)XSize) * YSize) { ppl_error(&x->c->errcontext, ERR_INTERNAL,-1,-1,"Surface plot yielded data grid of the wrong size."); } else { last_colstr=NULL; for (fill=1; fill>=0; fill--) for (Y=0; Yc, &pd->ww_final, &blk->data_real[Ncolumns*j], &blk->data_obj[Ncol_obj*j], Ncolumns, Ncol_obj); // Work out style information for next point if (fill) { eps_core_SetFillColor(x, &pd->ww_final); eps_core_SwitchTo_FillColor(x,0); } else { eps_core_SetColor(x, &pd->ww_final, 0); } IF_NOT_INVISIBLE { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) break; strcpy(last_colstr, x->CurrentColor); } SURFACE_POINT(x1,y1,z1); j++; SURFACE_POINT(x2,y2,z2); j+=XSize; SURFACE_POINT(x3,y3,z3); j--; SURFACE_POINT(x4,y4,z4); // Draw a square depth = (z1+z2+z3+z4)/4.0; if (fill) depth += 1e-6*fabs(depth); sprintf(epsbuff, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath %s\n", x1,y1,x2,y2,x3,y3,x4,y4,fill?"eofill":"stroke"); ThreeDimBuffer_writeps(x, depth, pd->ww_final.linetype, pd->ww_final.linewidth, 0.0, 1, last_colstr, epsbuff); eps_core_BoundingBox(x, x1, y1, pd->ww_final.linewidth * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x2, y2, pd->ww_final.linewidth * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x3, y3, pd->ww_final.linewidth * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x4, y4, pd->ww_final.linewidth * EPS_DEFAULT_LINEWIDTH); } } } } else if (style == SW_STYLE_COLORMAP) // COLORMAP { // Dealt with in advance of drawing backmost axes } else if ((style == SW_STYLE_CONTOURMAP)&&(xrn==0)&&(yrn==0)&&(zrn==0)) // CONTOURMAP { // Dealt with in advance of drawing backmost axes } // End looping over monotonic regions of axis space } return 0; } // Produce an icon representing a dataset on the graph's legend void eps_plot_LegendIcon(EPSComm *x, int i, canvas_plotdesc *pd, double xpos, double ypos, double scale, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, int xn, int yn, int zn) { int style = pd->ww_final.linespoints; dataTable *data = x->current->plotdata[i]; pplset_axis *a[3] = {a1,a2,a3}; if ((data==NULL) || (data->Nrows<1)) return; // No data present if ((style==SW_STYLE_LINES) || (style==SW_STYLE_LINESPOINTS) || (style==SW_STYLE_IMPULSES) || (style==SW_STYLE_BOXES) || (style==SW_STYLE_WBOXES) || (style==SW_STYLE_STEPS) || (style==SW_STYLE_FSTEPS) || (style==SW_STYLE_HISTEPS) || (style==SW_STYLE_SURFACE) || (style==SW_STYLE_CONTOURMAP)) { eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.linewidth, pd->ww_final.linetype, 0); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", xpos-scale*0.60/2, ypos, xpos+scale*0.60/2, ypos); eps_core_BoundingBox(x, xpos-scale*0.60/2, ypos, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+scale*0.60/2, ypos, pd->ww_final.linewidth); } } if ((style==SW_STYLE_POINTS) || (style==SW_STYLE_LINESPOINTS) || (style==SW_STYLE_STARS) || (style==SW_STYLE_DOTS)) { double final_pointsize = pd->ww_final.pointsize; if (style==SW_STYLE_DOTS ) { final_pointsize *= 0.05; if (final_pointsize < 0.25) final_pointsize=0.25; } // Dots are 1/20th size of points if (style==SW_STYLE_STARS) final_pointsize = 1; eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.pointlinewidth, 1, 0); IF_NOT_INVISIBLE { int pt = (pd->ww_final.pointtype-1) % N_POINTTYPES; if (style==SW_STYLE_DOTS ) pt = 16; // Dots are always pt 17 (circle) if (style==SW_STYLE_STARS) pt = 24; // Stars are always pt 25 (star) while (pt<0) pt+=N_POINTTYPES; x->PointTypesUsed[pt] = 1; fprintf(x->epsbuffer, "/ps { %f } def %.2f %.2f pt%d\n", final_pointsize * EPS_DEFAULT_PS, xpos, ypos, pt+1); eps_core_BoundingBox(x, xpos, ypos, 2 * final_pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS); } } else if ((style==SW_STYLE_LOWERLIMITS) || (style==SW_STYLE_UPPERLIMITS)) { double ps, sgn, eah_old=EPS_ARROW_HEADSIZE; ps = pd->ww_final.pointsize * EPS_DEFAULT_PS; sgn = ( (style == SW_STYLE_UPPERLIMITS) ^ (a[yn]->MaxFinal > a[yn]->MinFinal) ) ? 1.0 : -1.0; eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.pointlinewidth, pd->ww_final.linetype, 0); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", xpos-ps, ypos-ps*sgn, xpos+ps, ypos-ps*sgn); eps_core_BoundingBox(x, xpos-ps, ypos-ps*sgn, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+ps, ypos-ps*sgn, pd->ww_final.linewidth); EPS_ARROW_HEADSIZE /=2; eps_primitive_arrow(x, SW_ARROWTYPE_HEAD, xpos, ypos-ps*sgn, NULL, xpos, ypos+ps*sgn, NULL, &pd->ww_final); EPS_ARROW_HEADSIZE = eah_old; } } else if ((style==SW_STYLE_ARROWS_HEAD) || (style==SW_STYLE_ARROWS_NOHEAD) || (style==SW_STYLE_ARROWS_TWOHEAD)) { int ArrowStyle; if (style==SW_STYLE_ARROWS_TWOHEAD) ArrowStyle = SW_ARROWTYPE_TWOWAY; else if (style==SW_STYLE_ARROWS_NOHEAD) ArrowStyle = SW_ARROWTYPE_NOHEAD; else ArrowStyle = SW_ARROWTYPE_HEAD; eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.pointlinewidth, pd->ww_final.linetype, 0); IF_NOT_INVISIBLE eps_primitive_arrow(x, ArrowStyle, xpos-scale*0.60/2, ypos, NULL, xpos+scale*0.60/2, ypos, NULL, &pd->ww_final); } else if ((style == SW_STYLE_FILLEDREGION) || (style == SW_STYLE_YERRORSHADED) || (style == SW_STYLE_COLORMAP)) { double s=scale*0.45/2; eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetFillColor(x, &pd->ww_final); eps_core_SwitchTo_FillColor(x,1); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath fill\n", xpos-s, ypos-s, xpos+s, ypos-s, xpos+s, ypos+s, xpos-s, ypos+s); eps_core_BoundingBox(x, xpos-s, ypos-s, 0); eps_core_BoundingBox(x, xpos+s, ypos-s, 0); eps_core_BoundingBox(x, xpos-s, ypos+s, 0); eps_core_BoundingBox(x, xpos+s, ypos+s, 0); } eps_core_SwitchFrom_FillColor(x,1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.pointlinewidth, pd->ww_final.linetype, 0); IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath stroke\n", xpos-s, ypos-s, xpos+s, ypos-s, xpos+s, ypos+s, xpos-s, ypos+s); eps_core_BoundingBox(x, xpos-s, ypos-s, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+s, ypos-s, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos-s, ypos+s, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+s, ypos+s, pd->ww_final.linewidth); } } else if ((style==SW_STYLE_XERRORBARS)||(style==SW_STYLE_YERRORBARS)||(style==SW_STYLE_ZERRORBARS)||(style==SW_STYLE_XYERRORBARS)||(style==SW_STYLE_XZERRORBARS)||(style==SW_STYLE_XZERRORBARS)||(style==SW_STYLE_XZERRORBARS)||(style==SW_STYLE_XERRORRANGE)||(style==SW_STYLE_YERRORRANGE)||(style==SW_STYLE_ZERRORRANGE)||(style==SW_STYLE_XYERRORRANGE)||(style==SW_STYLE_XZERRORRANGE)||(style==SW_STYLE_YZERRORRANGE)) { double s = scale*0.6/2; double b = 0.0005 * x->current->settings.bar * M_TO_PS; double ps = pd->ww_final.pointsize * EPS_DEFAULT_PS; eps_core_SetColor(x, &pd->ww_final, 1); IF_NOT_INVISIBLE { eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.linewidth, pd->ww_final.linetype, 0); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n",xpos-s,ypos ,xpos+s,ypos ); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n",xpos-s,ypos-b ,xpos-s,ypos+b ); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n",xpos+s,ypos-b ,xpos+s,ypos+b ); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n",xpos ,ypos-ps,xpos ,ypos+ps); eps_core_BoundingBox(x, xpos-s, ypos-ps, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos-s, ypos+ps, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+s, ypos-ps, pd->ww_final.linewidth); eps_core_BoundingBox(x, xpos+s, ypos+ps, pd->ww_final.linewidth); } } return; } pyxplot-0.9.2/src/epsMaker/eps_plot_labelsarrows.c0000664000175000017500000003301612026340554020736 0ustar dcf21dcf21// eps_plot_labelsarrows.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_labelsarrows.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_LABELSARROWS 1 #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "settings/epsColors.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_labelsarrows.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" void eps_plot_labelsarrows_YieldUpText(EPSComm *x) { ppllabel_object *li; for (li=x->current->label_list; li!=NULL; li=li->next) { YIELD_TEXTITEM(li->text); } return; } #define FETCH_AXES(SYSTEM, XA, XAXES, AXISN, XIN, XOUT) \ { \ XOUT = XIN.real; \ if (SYSTEM == SW_SYSTEM_FIRST ) { XA = &(XAXES[1]); } \ else if (SYSTEM == SW_SYSTEM_SECOND) { XA = &(XAXES[2]); } \ else if (SYSTEM == SW_SYSTEM_AXISN ) { if ((AXISN<0)||(AXISN>=MAX_AXES)) { XA = NULL; XOUT = 0.0; ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1,"Axis number out of range"); } else { XA = &(XAXES[AXISN]); } } \ else { XA = NULL; XOUT = 0.0; } \ if (XA != NULL) \ { \ if (!XA->RangeFinalised) { XA = &(XAXES[1]); } /* Default to first axis if desired axis doesn't exist */ \ if (XA->HardUnitSet && (!ppl_unitsDimEqual(&(XIN),&(XA->HardUnit)))) { sprintf(x->c->errcontext.tempErrStr, "Position specified for %s dimensionally incompatible with the range specified for the axis. Position has units of <%s> while axis has units of <%s>.", ItemName, ppl_printUnit(x->c, &(XIN), NULL, NULL, 0, 1, 0), ppl_printUnit(x->c, &(XA->HardUnit), NULL, NULL, 1, 1, 0)); ppl_error(&x->c->errcontext, ERR_NUMERICAL, -1, -1,NULL); XA=NULL; XOUT=0.5; status=1; } \ if (XA->DataUnitSet && (!ppl_unitsDimEqual(&(XIN),&(XA->DataUnit)))) { sprintf(x->c->errcontext.tempErrStr, "Position specified for %s dimensionally incompatible with data plotted against the axis. Position has units of <%s> while axis has units of <%s>.", ItemName, ppl_printUnit(x->c, &(XIN), NULL, NULL, 0, 1, 0), ppl_printUnit(x->c, &(XA->DataUnit), NULL, NULL, 1, 1, 0)); ppl_error(&x->c->errcontext, ERR_NUMERICAL, -1, -1,NULL); XA=NULL; XOUT=0.5; status=1; } \ if (!XA->RangeFinalised) { XA=NULL; XOUT=0.5; } \ } \ } #define ADD_PAGE_COORDINATES(SYSTEM, XIN, THETA_X) \ if ((SYSTEM==SW_SYSTEM_PAGE)||(SYSTEM==SW_SYSTEM_GRAPH)) \ { \ xpos_ += XIN.real * sin(THETA_X) * M_TO_PS; \ ypos_ += XIN.real * cos(THETA_X) * M_TO_PS; \ } void eps_plot_labelsarrows(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth) { int pageno, hal, val; char ItemName[64]; pplarrow_object *ai; ppllabel_object *li; withWords ww, ww_default; ppl_withWordsZero(x->c, &ww_default); ww_default.USEcolor = 1; ww_default.color = COLOR_BLACK; ww_default.USElinetype = ww_default.USElinewidth = 1; ww_default.linetype = ww_default.linewidth = 1.0; pageno = x->LaTeXpageno = x->current->SetLabelTextID; // Loop through all arrows, rendering them in turn for (ai=x->current->arrow_list; ai!=NULL; ai=ai->next) { pplset_axis *xa0, *ya0, *za0=NULL, *xa1, *ya1, *za1=NULL; double xin0, yin0, zin0=0.5, xin1, yin1, zin1=0.5; double xpos_, ypos_, xpos[2], ypos[2], depth[2]; double xap[2], yap[2], zap[2], theta_x, theta_y, theta_z; int status=0, xrn0, yrn0, zrn0, xrn1, yrn1, zrn1; int ArrowType=ai->pplarrow_style; sprintf(ItemName, "arrow %d on plot %d", ai->id, x->current->id); FETCH_AXES(ai->system_x0, xa0, x->current->XAxes, ai->axis_x0, ai->x0, xin0); FETCH_AXES(ai->system_y0, ya0, x->current->YAxes, ai->axis_y0, ai->y0, yin0); if (x->current->ThreeDim) { FETCH_AXES(ai->system_z0, za0, x->current->ZAxes, ai->axis_z0, ai->z0, zin0); } FETCH_AXES(ai->system_x1, xa1, x->current->XAxes, ai->axis_x1, ai->x1, xin1); FETCH_AXES(ai->system_y1, ya1, x->current->YAxes, ai->axis_y1, ai->y1, yin1); if (x->current->ThreeDim) { FETCH_AXES(ai->system_z1, za1, x->current->ZAxes, ai->axis_z1, ai->z1, zin1); } if (!status) for (xrn0=0; xrn0<=( (xa0!=NULL) ? xa0->AxisValueTurnings : 0); xrn0++) for (yrn0=0; yrn0<=( (ya0!=NULL) ? ya0->AxisValueTurnings : 0); yrn0++) for (zrn0=0; zrn0<=((x->current->ThreeDim && (za0!=NULL)) ? za0->AxisValueTurnings : 0); zrn0++) for (xrn1=0; xrn1<=( (xa1!=NULL) ? xa1->AxisValueTurnings : 0); xrn1++) for (yrn1=0; yrn1<=( (ya1!=NULL) ? ya1->AxisValueTurnings : 0); yrn1++) for (zrn1=0; zrn1<=((x->current->ThreeDim && (za1!=NULL)) ? za1->AxisValueTurnings : 0); zrn1++) { if ((xa0==xa1)&&(xrn0!=xrn1)) continue; if ((ya0==ya1)&&(yrn0!=yrn1)) continue; if ((za0==za1)&&(zrn0!=zrn1)) continue; eps_plot_GetPosition(&xpos[0], &ypos[0], &depth[0], &xap[0], &yap[0], &zap[0], &theta_x, &theta_y, &theta_z, x->current->ThreeDim, xin0, yin0, zin0, xa0, ya0, za0, xrn0, yrn0, zrn0, &x->current->settings, origin_x, origin_y, width, height, zdepth, 1); eps_plot_GetPosition(&xpos[1], &ypos[1], &depth[1], &xap[1], &yap[1], &zap[1], &theta_x, &theta_y, &theta_z, x->current->ThreeDim, xin1, yin1, zin1, xa1, ya1, za1, xrn1, yrn1, zrn1, &x->current->settings, origin_x, origin_y, width, height, zdepth, 1); if (((xap[0]<0)||(xap[0]>1)||(yap[0]<0)||(yap[0]>1)||(zap[0]<0)||(zap[0]>1)) && ((xa0==NULL)||(ya0==NULL)||(x->current->ThreeDim&&(za0==NULL))||(xa1==NULL)||(ya1==NULL)||(x->current->ThreeDim&&(za1==NULL)))) continue; xpos_=xpos[0]; ypos_=ypos[0]; ADD_PAGE_COORDINATES(ai->system_x0, ai->x0, theta_x); ADD_PAGE_COORDINATES(ai->system_y0, ai->y0, theta_y); if (x->current->ThreeDim) { ADD_PAGE_COORDINATES(ai->system_z0, ai->z0, theta_z); } xpos[0]=xpos_; ypos[0]=ypos_; xpos_=xpos[1]; ypos_=ypos[1]; ADD_PAGE_COORDINATES(ai->system_x1, ai->x1, theta_x); ADD_PAGE_COORDINATES(ai->system_y1, ai->y1, theta_y); if (x->current->ThreeDim) { ADD_PAGE_COORDINATES(ai->system_z1, ai->z1, theta_z); } xpos[1]=xpos_; ypos[1]=ypos_; { const double grad[3][6] = { // d[x y z xap yap zap]/d[xap yap zap] { (xap[1]==xap[0])?0.0:(xpos[1] -xpos[0] )/(xap[1]-xap[0]), (xap[1]==xap[0])?0.0:(ypos[1] -ypos[0] )/(xap[1]-xap[0]), (xap[1]==xap[0])?0.0:(depth[1]-depth[0])/(xap[1]-xap[0]), 1.0, (xap[1]==xap[0])?0.0:(yap[1] -yap[0] )/(xap[1]-xap[0]), (xap[1]==xap[0])?0.0:(zap[1] -zap[0] )/(xap[1]-xap[0]), },{ (yap[1]==yap[0])?0.0:(xpos[1] -xpos[0] )/(yap[1]-yap[0]), (yap[1]==yap[0])?0.0:(ypos[1] -ypos[0] )/(yap[1]-yap[0]), (yap[1]==yap[0])?0.0:(depth[1]-depth[0])/(yap[1]-yap[0]), (yap[1]==yap[0])?0.0:(xap[1] -xap[0] )/(yap[1]-yap[0]), 1.0, (yap[1]==yap[0])?0.0:(zap[1] -zap[0] )/(yap[1]-yap[0]), },{ (zap[1]==zap[0])?0.0:(xpos[1] -xpos[0] )/(zap[1]-zap[0]), (zap[1]==zap[0])?0.0:(ypos[1] -ypos[0] )/(zap[1]-zap[0]), (zap[1]==zap[0])?0.0:(depth[1]-depth[0])/(zap[1]-zap[0]), (zap[1]==zap[0])?0.0:(xap[1] -xap[0] )/(zap[1]-zap[0]), (zap[1]==zap[0])?0.0:(yap[1] -yap[0] )/(zap[1]-zap[0]), 1.0 }}; #define CLIP(XAP, XYZ, XAPV, P) \ if (XAPV ? (XAP[P]>1) : (XAP[P]<0) ) \ { \ const double t=XAP[P]; \ if (XAP[1-P]<0.0) continue; \ xpos[P] += grad[XYZ][0]*(XAPV-t); \ ypos[P] += grad[XYZ][1]*(XAPV-t); \ depth[P] += grad[XYZ][2]*(XAPV-t); \ xap[P] += grad[XYZ][3]*(XAPV-t); \ yap[P] += grad[XYZ][4]*(XAPV-t); \ zap[P] += grad[XYZ][5]*(XAPV-t); \ \ if (P==0) \ { \ if (ArrowType==SW_ARROWTYPE_TWOWAY) ArrowType=SW_ARROWTYPE_HEAD; \ } \ else \ { \ if (ArrowType==SW_ARROWTYPE_HEAD ) ArrowType=SW_ARROWTYPE_NOHEAD; \ if (ArrowType==SW_ARROWTYPE_TWOWAY) \ { \ double t1=xpos[0],t2=ypos[0],t3=depth[0],t4=xap[0],t5=yap[0],t6=zap[0]; \ xpos[0]=xpos[1]; ypos[0]=ypos[1]; depth[0]=depth[1]; xap[0]=xap[1]; yap[0]=yap[1]; zap[0]=zap[1]; \ xpos[1]=t1; ypos[1]=t2; depth[1]=t3; xap[1]=t4; yap[1]=t5; zap[1]=t6; \ ArrowType=SW_ARROWTYPE_HEAD; \ } \ } \ } CLIP(xap, 0, 0.0, 0); CLIP(xap, 0, 1.0, 0); CLIP(xap, 0, 0.0, 1); CLIP(xap, 0, 1.0, 1); CLIP(yap, 1, 0.0, 0); CLIP(yap, 1, 1.0, 0); CLIP(yap, 1, 0.0, 1); CLIP(yap, 1, 1.0, 1); CLIP(zap, 2, 0.0, 0); CLIP(zap, 2, 1.0, 0); CLIP(zap, 2, 0.0, 1); CLIP(zap, 2, 1.0, 1); } ppl_withWordsMerge(x->c, &ww, &ai->style, &ww_default, NULL, NULL, NULL, 1); if ((gsl_finite(xpos[0]))&&(gsl_finite(ypos[0]))&&(gsl_finite(xpos[1]))&&(gsl_finite(ypos[1]))) eps_primitive_arrow(x, ArrowType, xpos[0], ypos[0], x->current->ThreeDim?&depth[0]:NULL, xpos[1], ypos[1], x->current->ThreeDim?&depth[1]:NULL, &ww); } } // By default, use 'set textcolor' color for text labels if (x->current->settings.TextColor > 0) { ww_default.color = x->current->settings.TextColor; ww_default.USEcolor = 1; ww_default.USEcolor1234 = 0; } else { ww_default.Col1234Space = x->current->settings.TextCol1234Space; ww_default.color1 = x->current->settings.TextColor1; ww_default.color2 = x->current->settings.TextColor2; ww_default.color3 = x->current->settings.TextColor3; ww_default.color4 = x->current->settings.TextColor4; ww_default.USEcolor = 0; ww_default.USEcolor1234 = 1; } // Loop through all text labels, rendering them in turn for (li=x->current->label_list; li!=NULL; li=li->next) if ((li->text!=NULL)&&(li->text[0]!='\0')) { pplset_axis *xa, *ya, *za=NULL; double xin, yin, zin=0.5; double xpos_, ypos_, depth, xap, yap, zap, theta_x, theta_y, theta_z; int status=0, xrn, yrn, zrn; sprintf(ItemName, "label %d on plot %d", li->id, x->current->id); FETCH_AXES(li->system_x, xa, x->current->XAxes, li->axis_x, li->x, xin); FETCH_AXES(li->system_y, ya, x->current->YAxes, li->axis_y, li->y, yin); if (x->current->ThreeDim) { FETCH_AXES(li->system_z, za, x->current->ZAxes, li->axis_z, li->z, zin); } if (!status) for (xrn=0; xrn<=( (xa!=NULL) ? xa->AxisValueTurnings : 0); xrn++) for (yrn=0; yrn<=( (ya!=NULL) ? ya->AxisValueTurnings : 0); yrn++) for (zrn=0; zrn<=((x->current->ThreeDim && (za!=NULL)) ? za->AxisValueTurnings : 0); zrn++) { double xgap,ygap,xgap2,ygap2; eps_plot_GetPosition(&xpos_, &ypos_, &depth, &xap, &yap, &zap, &theta_x, &theta_y, &theta_z, x->current->ThreeDim, xin, yin, zin, xa, ya, za, xrn, yrn, zrn, &x->current->settings, origin_x, origin_y, width, height, zdepth, 0); ADD_PAGE_COORDINATES(li->system_x, li->x, theta_x); ADD_PAGE_COORDINATES(li->system_y, li->y, theta_y); if (x->current->ThreeDim) { ADD_PAGE_COORDINATES(li->system_z, li->z, theta_z); } if (li->HAlign != 0) hal = li->HAlign; else hal = x->current->settings.TextHAlign; if (li->VAlign != 0) val = li->VAlign; else val = x->current->settings.TextVAlign; xgap = -(hal - SW_HALIGN_CENT) * li->gap; ygap = (val - SW_VALIGN_CENT) * li->gap; xgap2 = xgap*cos(li->rotation) - ygap*sin(li->rotation); ygap2 = xgap*sin(li->rotation) + ygap*cos(li->rotation); ppl_withWordsMerge(x->c, &ww, &li->style, &ww_default, NULL, NULL, NULL, 1); eps_core_SetColor(x, &ww, 0); IF_NOT_INVISIBLE if ((gsl_finite(xpos_))&&(gsl_finite(ypos_))&&(gsl_finite(depth))) { char *colstr=NULL, *text=NULL; colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (colstr!=NULL) { double fs = x->current->settings.FontSize; if (li->fontsizeSet) fs = li->fontsize; strcpy(colstr, x->CurrentColor); canvas_EPSRenderTextItem(x, &text, pageno, xpos_/M_TO_PS+xgap2, ypos_/M_TO_PS+ygap2, hal, val, x->CurrentColor, fs, li->rotation, NULL, NULL); if (text!=NULL) ThreeDimBuffer_writeps(x, depth, 1, 1, 0, 1, colstr, text); } } } pageno++; } return; } pyxplot-0.9.2/src/epsMaker/eps_plot_contourmap.c0000664000175000017500000011277612026340554020440 0ustar dcf21dcf21// eps_plot_contourmap.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_contourmap.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_CONTOURMAP_C 1 #include #include #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "epsMaker/canvasDraw.h" #include "canvasItems.h" #include "coreUtils/errorReport.h" #include "settings/settings.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/garbageCollector.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" #include "userspace/pplObj_fns.h" #include "userspace/contextVarDef.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "settings/epsColors.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_contourmap.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_settings.h" #include "epsMaker/eps_style.h" // Codes for the four sides of a cell #define FACE_ALL -1 #define FACE_T 1 #define FACE_R 2 #define FACE_B 3 #define FACE_L 4 #define MAX_CONTOUR_PATHS 1024 typedef struct ContourDesc { long Nvertices_min, Nvertices_max; long i, segment_flatest; unsigned char closepath; double *posdata; double area; double vreal; } ContourDesc; static int ContourCmp(const void *xv, const void *yv) { const ContourDesc *x = (const ContourDesc *)xv; const ContourDesc *y = (const ContourDesc *)yv; if (x->area < y->area) return 1.0; else if (x->area > y->area) return -1.0; else return 0.0; } // Yield up text items which label contours on a contourmap void eps_plot_contourmap_YieldText(EPSComm *x, dataTable *data, pplset_graph *sg, canvas_plotdesc *pd) { dataBlock *blk; int XSize = (x->current->settings.SamplesXAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX; int YSize = (x->current->settings.SamplesYAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY; int i, j, k, Ncol; double CMin, CMax, min_prelim, max_prelim, OoM, UnitMultiplier; unsigned char CMinAuto, CMinSet, CMaxAuto, CMaxSet, CLog; char *UnitString; // Check that we have some data if ((data==NULL) || (data->Nrows<1)) return; // No data present Ncol = data->Ncolumns_real; blk = data->first; // Work out normalisation of variable c1 CMinAuto = (sg->Cminauto[0]==SW_BOOL_TRUE); CMinSet = !CMinAuto; CMin = sg->Cmin[0].real; CMaxAuto = (sg->Cmaxauto[0]==SW_BOOL_TRUE); CMaxSet = !CMaxAuto; CMax = sg->Cmax[0].real; CLog = (sg->Clog[0]==SW_BOOL_TRUE); // Find extremal values if (CMinAuto || CMaxAuto) for (j=0; jdata_real[2 + Ncol*(i+XSize*j)]; if (!gsl_finite(val)) continue; if ((CMinAuto) && ((!CMinSet) || (CMin>val)) && ((!CLog)||(val>0.0))) { CMin=val; CMinSet=1; } if ((CMaxAuto) && ((!CMaxSet) || (CMax0.0))) { CMax=val; CMaxSet=1; } } // If no data present, stop now if ((!CMinSet)||(!CMaxSet)) return; // If log spacing, make sure range is strictly positive if (CLog && (CMin<1e-200)) CMin=1e-200; if (CLog && (CMax<1e-200)) CMax=1e-200; // If there's no spread of data, make a spread up if ( (fabs(CMax) <= fabs(CMin)) || (fabs(CMin-CMax) <= fabs(1e-14*CMax)) ) { if (!CLog) { double step = ppl_max(1.0,1e-3*fabs(CMin)); CMin -= step; CMax += step; } else { if (CMin > 1e-300) CMin /= 10.0; if (CMax < 1e300) CMax *= 10.0; } } // Work out units in which contours will be labelled pd->CRangeUnit = data->firstEntries[2]; pd->CRangeUnit.flagComplex = 0; pd->CRangeUnit.imag = 0.0; pd->CRangeUnit.real = CLog ? (CMin * sqrt(CMax/CMin)) : ((CMin + CMax)/2); UnitString = ppl_printUnit(x->c,&pd->CRangeUnit,&UnitMultiplier,NULL,0,0,SW_DISPLAY_L); UnitMultiplier /= pd->CRangeUnit.real; if (!gsl_finite(UnitMultiplier)) UnitMultiplier=1.0; // Round range outwards to round endpoints min_prelim = CMin * UnitMultiplier; max_prelim = CMax * UnitMultiplier; if (CLog) { min_prelim = log10(min_prelim); max_prelim = log10(max_prelim); } OoM = pow(10.0, floor(log10(fabs(max_prelim - min_prelim)/5))); min_prelim = floor(min_prelim / OoM) * OoM; max_prelim = ceil (max_prelim / OoM) * OoM; if (CLog) { min_prelim = pow(10.0,min_prelim); max_prelim = pow(10.0,max_prelim); } min_prelim /= UnitMultiplier; max_prelim /= UnitMultiplier; if (gsl_finite(min_prelim) && (CLog||(min_prelim>1e-300))) CMin = min_prelim; if (gsl_finite(max_prelim) && (CLog||(min_prelim>1e-300))) CMax = max_prelim; // Loop over all contours submitting labels for (k=0; (kContoursListLen< 0) && (kContoursN)) || ((sg->ContoursListLen>=0) && (kContoursListLen)) ); k++) { pplObj v = pd->CRangeUnit; if (sg->ContoursListLen< 0) v.real = CLog?(CMin*pow(CMax/CMin,(k+0.5*CMinAuto)/(sg->ContoursN-0.5*((!CMinAuto)+(!CMaxAuto))))) :(CMin+(CMax-CMin)*(k+0.5*CMinAuto)/(sg->ContoursN-0.5*((!CMinAuto)+(!CMaxAuto)))); else v.real = sg->ContoursList[k]; sprintf(UnitString,"%s",ppl_unitsNumericDisplay(x->c,&v,0,SW_DISPLAY_L,0)); YIELD_TEXTITEM_CPY(UnitString); } // Store range of values for which contours will be drawn pd->CMinFinal = CMin; pd->CMaxFinal = CMax; return; } // Routines for tracking the paths of contours // -----+-----+-----+-----+ // | | | | blk->split[X] contains flags indicating whether crossing points on lines // | | | | A (in bit 1) and B (in bit 2) have been used. // | |--A--| | on successive passes, bits (3,4), (5,6) are used, etc. // -----+-----X-----+-----+ // | || | | // | B| | | // | || | | // -----+-----+-----+-----+ // | | | | // | | | | // | | | | // -----+-----+-----+-----+ static int IsBetween(double x, double a, double b, double *f) { *f=0.5; if (a==b) { return x==a; } if ((a< b)&&(x>=a)&&(x<=b)) { *f=(x-a)/(b-a); return 1; } if ((a> b)&&(x<=a)&&(x>=b)) { *f=(x-a)/(b-a); return 1; } return 0; } // See whether cell X contains any unused starting points for contours static int GetStartPoint(double c1, dataTable *data, unsigned char **flags, int XSize, int YSize, int x0, int y0, int EntryFace, int *ExitFace, int *xcell, int *ycell, double *Xout, double *Yout) { dataBlock *blk = data->first; int Ncol = data->Ncolumns_real; const int pass = 0; double f; *xcell = x0; *ycell = y0; if (((EntryFace<0)||(EntryFace==FACE_T)) && (x0<=XSize-2) && (x0>= 0) && (y0>= 0) && (y0<=YSize-1) && (((blk->split[(x0 )+(y0 )*XSize]>>(0+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0 )*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0 )*XSize)],&f)) { *flags = &blk->split[(x0 )+(y0 )*XSize]; *ExitFace=FACE_T; *Xout=x0+f; *Yout=y0; return 1; } if (((EntryFace<0)||(EntryFace==FACE_R)) && (x0<=XSize-2) && (x0>=-1) && (y0>= 0) && (y0<=YSize-2) && (((blk->split[(x0+1)+(y0 )*XSize]>>(1+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0+1)+(y0 )*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0+1)*XSize)],&f)) { *flags = &blk->split[(x0+1)+(y0 )*XSize]; *ExitFace=FACE_R; *Xout=x0+1; *Yout=y0+f; return 1; } if (((EntryFace<0)||(EntryFace==FACE_B)) && (x0<=XSize-2) && (x0>= 0) && (y0>=-1) && (y0<=YSize-2) && (((blk->split[(x0 )+(y0+1)*XSize]>>(0+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0+1)*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0+1)*XSize)],&f)) { *flags = &blk->split[(x0 )+(y0+1)*XSize]; *ExitFace=FACE_B; *Xout=x0+f; *Yout=y0+1; return 1; } if (((EntryFace<0)||(EntryFace==FACE_L)) && (x0<=XSize-1) && (x0>= 0) && (y0>= 0) && (y0<=YSize-2) && (((blk->split[(x0 )+(y0 )*XSize]>>(1+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0 )*XSize)], blk->data_real[2+Ncol*((x0 )+(y0+1)*XSize)],&f)) { *flags = &blk->split[(x0 )+(y0 )*XSize]; *ExitFace=FACE_L; *Xout=x0; *Yout=y0+f; return 1; } return 0; } // Given a contour already tracking through cell X from a given face, where to go next? static int GetNextPoint(double c1, dataTable *data, int pass, int XSize, int YSize, int x0, int y0, int EntryFace, int *ExitFace, int *xcell, int *ycell, double *Xout, double *Yout) { dataBlock *blk = data->first; int Ncol = data->Ncolumns_real; int j; double f; for (j=0; j<2; j++) { if (((j==1 )||(EntryFace==FACE_B)) && (x0<=XSize-2) && (x0>= 0) && (y0>= 0) && (y0<=YSize-1) && (((blk->split[(x0 )+(y0 )*XSize]>>(0+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0 )*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0 )*XSize)],&f)) { blk->split[(x0 )+(y0 )*XSize] |= 1<<(0+2*pass); *ExitFace=FACE_T; *xcell=x0; *ycell=y0-1; *Xout=x0+f; *Yout=y0; return 1; } if (((j==1 )||(EntryFace==FACE_L)) && (x0<=XSize-2) && (x0>=-1) && (y0>= 0) && (y0<=YSize-2) && (((blk->split[(x0+1)+(y0 )*XSize]>>(1+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0+1)+(y0 )*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0+1)*XSize)],&f)) { blk->split[(x0+1)+(y0 )*XSize] |= 1<<(1+2*pass); *ExitFace=FACE_R; *xcell=x0+1; *ycell=y0; *Xout=x0+1; *Yout=y0+f; return 1; } if (((j==1 )||(EntryFace==FACE_T)) && (x0<=XSize-2) && (x0>= 0) && (y0>=-1) && (y0<=YSize-2) && (((blk->split[(x0 )+(y0+1)*XSize]>>(0+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0+1)*XSize)], blk->data_real[2+Ncol*((x0+1)+(y0+1)*XSize)],&f)) { blk->split[(x0 )+(y0+1)*XSize] |= 1<<(0+2*pass); *ExitFace=FACE_B; *xcell=x0; *ycell=y0+1; *Xout=x0+f; *Yout=y0+1; return 1; } if (((j==1 )||(EntryFace==FACE_R)) && (x0<=XSize-1) && (x0>= 0) && (y0>= 0) && (y0<=YSize-2) && (((blk->split[(x0 )+(y0 )*XSize]>>(1+2*pass))&1)==0) && IsBetween(c1, blk->data_real[2+Ncol*((x0 )+(y0 )*XSize)], blk->data_real[2+Ncol*((x0 )+(y0+1)*XSize)],&f)) { blk->split[(x0 )+(y0 )*XSize] |= 1<<(1+2*pass); *ExitFace=FACE_L; *xcell=x0-1; *ycell=y0; *Xout=x0; *Yout=y0+f; return 1; } } return 0; } static void FollowContour(EPSComm *x, dataTable *data, ContourDesc *cd, pplObj *v, unsigned char *flags, int XSize, int YSize, int xcell, int ycell, int face, double xpos, double ypos, double Lx, double ThetaX, double Ly, double ThetaY) { long i, j, i_flatest=0; int xcelli=xcell, ycelli=ycell; double xposi =xpos , yposi =ypos , grad_flatest = 1e100; int facei =face; double xold=xpos, yold=ypos; // Starting point has been used on pass zero *flags |= 1<<(((face==FACE_L)||(face==FACE_R)) + 0); // Trace path, looking for flattest segment and counting length for (i=1; (GetNextPoint(v->real, data, 0, XSize, YSize, xcell, ycell, face, &face, &xcell, &ycell, &xpos, &ypos)!=0); i++) { double grad; if (xpos!=xold) { double x0, y0, x1, y1; x0 = Lx*xold/(XSize-1)*sin(ThetaX) + Ly*yold/(YSize-1)*sin(ThetaY); y0 = Lx*xold/(XSize-1)*cos(ThetaX) + Ly*yold/(YSize-1)*cos(ThetaY); x1 = Lx*xpos/(XSize-1)*sin(ThetaX) + Ly*ypos/(YSize-1)*sin(ThetaY); y1 = Lx*xpos/(XSize-1)*cos(ThetaX) + Ly*ypos/(YSize-1)*cos(ThetaY); grad = fabs((y1-y0)/(x1-x0)); if (gradNvertices_min = cd->Nvertices_max = i; cd->segment_flatest = i_flatest; cd->posdata = (double *)ppl_memAlloc((i+8) * 2 * sizeof(double)); if (cd->posdata==NULL) return; // Begin pass one xcell=xcelli; ycell=ycelli; xpos=xposi; ypos=yposi; face=facei; // Starting point has been used on pass one *flags |= 1<<(((face==FACE_L)||(face==FACE_R)) + 2); // Trace path, looking for flattest segment and counting length cd->posdata[2*0 ] = xpos; cd->posdata[2*0+1] = ypos; for (j=1; (GetNextPoint(v->real, data, 1, XSize, YSize, xcell, ycell, face, &face, &xcell, &ycell, &xpos, &ypos)!=0); j++) { cd->posdata[2*j ] = xpos; cd->posdata[2*j+1] = ypos; } return; } // Render a contourmap to postscript int eps_plot_contourmap(EPSComm *x, dataTable *data, unsigned char ThreeDim, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, int pdn, double origin_x, double origin_y, double width, double height, double zdepth) { double scale_x, scale_y, scale_z; dataBlock *blk; int XSize = (x->current->settings.SamplesXAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesX; int YSize = (x->current->settings.SamplesYAuto==SW_BOOL_TRUE) ? x->current->settings.samples : x->current->settings.SamplesY; int i, j, k, cn, pass, face, xcell, ycell; double xo, yo, Lx, Ly, ThetaX, ThetaY, CMin, CMax, xpos, ypos; double col=GSL_NAN,col1=-1,col2=-1,col3=-1,col4=-1,fc=GSL_NAN,fc1=-1,fc2=-1,fc3=-1,fc4=-1; unsigned char CLog, CMinAuto, CMaxAuto, CRenorm, *flags; char *errtext, c1name[]="c1"; pplObj *CVar=NULL, CDummy; ContourDesc *clist; int cpos=0; // int Ncol_real, Ncol_obj; if ((data==NULL) || (data->Nrows<1)) return 0; // No data present // Ncol_real = data->Ncolumns_real; // Ncol_obj = data->Ncolumns_obj; // if (eps_plot_WithWordsCheckUsingItemsDimLess(&pd->ww_final, data->firstEntries, Ncol_real, NULL, Ncol_obj)) return 1; if (!ThreeDim) { scale_x=width; scale_y=height; scale_z=1.0; } else { scale_x=width; scale_y=height; scale_z=zdepth; } blk = data->first; clist = (ContourDesc *)ppl_memAlloc(MAX_CONTOUR_PATHS * sizeof(ContourDesc)); errtext = ppl_memAlloc(LSTR_LENGTH); if ((clist==NULL)||(errtext==NULL)) { ppl_error(&x->c->errcontext,ERR_MEMORY,-1,-1,"Out of memory (p)."); return 1; } // Work out orientation of contourmap if (!ThreeDim) { xo = origin_x; yo = origin_y; Lx = scale_x; Ly = scale_y; ThetaX = M_PI/2; ThetaY = 0.0; if (xn!=0) { double t1=Lx, t2=ThetaX; Lx=Ly; ThetaX=ThetaY; Ly=t1; ThetaY=t2; } } else // 3D case: put color map on back face of cuboid { double ap[3]={0.5,0.5,0.0}, xtmp, ytmp, z0tmp, z1tmp; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); ap[2]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z1tmp); ap[2]=(z1tmp>z0tmp)?1.0:0.0; // Determine whether zap=0 or zap=1 represents back of cuboid ap[0]=ap[1]=0.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xo, &yo, &z0tmp); ap[0]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); Lx = hypot(xtmp-xo, ytmp-yo); ThetaX = atan2(xtmp-xo, ytmp-yo); if (!gsl_finite(ThetaX)) ThetaX = 0.0; ap[0]=0.0; ap[1]=1.0; eps_plot_ThreeDimProject(ap[xn], ap[yn], ap[zn], sg, origin_x, origin_y, scale_x, scale_y, scale_z, &xtmp, &ytmp, &z0tmp); Ly = hypot(xtmp-xo, ytmp-yo); ThetaY = atan2(xtmp-xo, ytmp-yo); if (!gsl_finite(ThetaY)) ThetaY = 0.0; } // Look up normalisation of variable c1 CLog = (sg->Clog[0]==SW_BOOL_TRUE); CMin = pd->CMinFinal; CMax = pd->CMaxFinal; CMinAuto = (sg->Cminauto[0]==SW_BOOL_TRUE); CMaxAuto = (sg->Cmaxauto[0]==SW_BOOL_TRUE); CRenorm = (sg->Crenorm [0]==SW_BOOL_TRUE); // If no data present, stop now if ((CMin==0)&&(CMax==0)) { sprintf(x->c->errcontext.tempErrStr, "No data supplied to determine range for variable c1"); return 0; } // Output result to debugging output if (DEBUG) { int SF = x->c->set->term_current.SignificantFigures; sprintf(x->c->errcontext.tempErrStr, "Range for variable c1 is [%s:%s]", ppl_numericDisplay(CMin,x->c->numdispBuff[0],SF,0), ppl_numericDisplay(CMax,x->c->numdispBuff[1],SF,0)); ppl_log(&x->c->errcontext,NULL); } // Check that variable c1 has appropriate units if ( ((!CMinAuto)||(!CMaxAuto)) && (!ppl_unitsDimEqual(&data->firstEntries[2] , (sg->Cminauto[0]==SW_BOOL_TRUE)?(&sg->Cmax[0]):(&sg->Cmin[0]))) ) { sprintf(x->c->errcontext.tempErrStr, "Column 3 of data supplied to the colormap plot style has conflicting units with those set in the 'set crange' command. The former has units of <%s> whilst the latter has units of <%s>.", ppl_printUnit(x->c,&data->firstEntries[2], NULL, NULL, 0, 1, 0), ppl_printUnit(x->c,(sg->Cminauto[0]==SW_BOOL_TRUE)?(&sg->Cmax[0]):(&sg->Cmin[0]), NULL, NULL, 1, 1, 0)); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); return 1; } // Get pointer to variable c1 in the user's variable space ppl_contextGetVarPointer(x->c, c1name, &CVar, &CDummy); if (!CRenorm) { *CVar = pd->CRangeUnit; CVar->flagComplex=0; CVar->imag=0.0; } else pplObjNum(CVar,0,0,0); // c1 is a dimensionless number in range 0-1, regardless of units of input data // Loop over contours for (k=0; (kContoursListLen< 0) && (kContoursN)) || ((sg->ContoursListLen>=0) && (kContoursListLen)) ); k++) { pplObj v = pd->CRangeUnit; if (sg->ContoursListLen< 0) v.real = CLog?(CMin*pow(CMax/CMin,(k+0.5*CMinAuto)/(sg->ContoursN-0.5*((!CMinAuto)+(!CMaxAuto))))) :(CMin+(CMax-CMin)*(k+0.5*CMinAuto)/(sg->ContoursN-0.5*((!CMinAuto)+(!CMaxAuto)))); else v.real = sg->ContoursList[k]; // Write debugging output if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Beginning to trace path of contour at c1=%g.", v.real); ppl_log(&x->c->errcontext,NULL); } // Reset contour map usage flags for (j=0; jsplit[i+XSize*j] = 0; // Set value of c1 if (CRenorm) { if (sg->ContoursListLen< 0) CVar->real = ((double)(k+1)/(sg->ContoursN+1)); else CVar->real = CLog?(log(v.real/CMin) / log(CMax/CMin)) :((v.real-CMin)/(CMax-CMin)); if (CVar->real<0.0) CVar->real=0.0; if (CVar->real>1.0) CVar->real=1.0; if (!gsl_finite(CVar->real)) CVar->real=0.5; } else CVar->real = v.real; // Scan edges of plot looking for contour start points for (i=0; ireal; clist[cpos].closepath = 0; FollowContour(x, data, &clist[cpos], &v, flags, XSize, YSize, xcell, ycell, face, xpos, ypos, Lx, ThetaX, Ly, ThetaY); if (++cpos>=MAX_CONTOUR_PATHS) goto GOT_CONTOURS; } for (i=0; ireal; clist[cpos].closepath = 0; FollowContour(x, data, &clist[cpos], &v, flags, XSize, YSize, xcell, ycell, face, xpos, ypos, Lx, ThetaX, Ly, ThetaY); if (++cpos>=MAX_CONTOUR_PATHS) goto GOT_CONTOURS; } for (i=0; ireal; clist[cpos].closepath = 0; FollowContour(x, data, &clist[cpos], &v, flags, XSize, YSize, xcell, ycell, face, xpos, ypos, Lx, ThetaX, Ly, ThetaY); if (++cpos>=MAX_CONTOUR_PATHS) goto GOT_CONTOURS; } for (i=0; ireal; clist[cpos].closepath = 0; FollowContour(x, data, &clist[cpos], &v, flags, XSize, YSize, xcell, ycell, face, xpos, ypos, Lx, ThetaX, Ly, ThetaY); if (++cpos>=MAX_CONTOUR_PATHS) goto GOT_CONTOURS; } // Scan body of plot looking for undrawn contours for (j=0; jreal; clist[cpos].closepath = 1; FollowContour(x, data, &clist[cpos], &v, flags, XSize, YSize, xcell, ycell, face, xpos, ypos, Lx, ThetaX, Ly, ThetaY); if (++cpos>=MAX_CONTOUR_PATHS) goto GOT_CONTOURS; } } // Finish looping over contours we are to trace GOT_CONTOURS: #define XPOS_TO_POSTSCRIPT \ { \ xps = xo + Lx*xpos/(XSize-1)*sin(ThetaX) + Ly*ypos/(YSize-1)*sin(ThetaY); \ yps = yo + Lx*xpos/(XSize-1)*cos(ThetaX) + Ly*ypos/(YSize-1)*cos(ThetaY); \ } // Add corners of plot to paths of non-closed contours for (cn=0; cn (XSize-0.0001)) faceA = FACE_R; else if (clist[cn].posdata[ 1] < 0.0001 ) faceA = FACE_T; else faceA = FACE_B; if (clist[cn].posdata[2*(n-1) + 0] < 0.0001 ) faceB = FACE_L; else if (clist[cn].posdata[2*(n-1) + 0] > (XSize-0.0001)) faceB = FACE_R; else if (clist[cn].posdata[2*(n-1) + 1] < 0.0001 ) faceB = FACE_T; else faceB = FACE_B; if ( ((faceA==FACE_L)&&(faceB==FACE_T)) || ((faceA==FACE_T)&&(faceB==FACE_L)) ) { clist[cn].posdata[2*n+0] = 0; clist[cn].posdata[2*n+1] = 0; clist[cn].Nvertices_max += 1; } else if ( ((faceA==FACE_R)&&(faceB==FACE_T)) || ((faceA==FACE_T)&&(faceB==FACE_R)) ) { clist[cn].posdata[2*n+0] = XSize; clist[cn].posdata[2*n+1] = 0; clist[cn].Nvertices_max += 1; } else if ( ((faceA==FACE_L)&&(faceB==FACE_B)) || ((faceA==FACE_B)&&(faceB==FACE_L)) ) { clist[cn].posdata[2*n+0] = 0; clist[cn].posdata[2*n+1] = YSize; clist[cn].Nvertices_max += 1; } else if ( ((faceA==FACE_R)&&(faceB==FACE_B)) || ((faceA==FACE_B)&&(faceB==FACE_R)) ) { clist[cn].posdata[2*n+0] = XSize; clist[cn].posdata[2*n+1] = YSize; clist[cn].Nvertices_max += 1; } else if ((faceA==FACE_L)&&(faceB==FACE_R)) { clist[cn].posdata[2*n+0] = XSize; clist[cn].posdata[2*n+1] = 0; clist[cn].posdata[2*n+2] = 0; clist[cn].posdata[2*n+3] = 0; clist[cn].Nvertices_max += 2; } else if ((faceA==FACE_R)&&(faceB==FACE_L)) { clist[cn].posdata[2*n+0] = 0; clist[cn].posdata[2*n+1] = 0; clist[cn].posdata[2*n+2] = XSize; clist[cn].posdata[2*n+3] = 0; clist[cn].Nvertices_max += 2; } else if ((faceA==FACE_T)&&(faceB==FACE_B)) { clist[cn].posdata[2*n+0] = 0; clist[cn].posdata[2*n+1] = YSize; clist[cn].posdata[2*n+2] = 0; clist[cn].posdata[2*n+3] = 0; clist[cn].Nvertices_max += 2; } else if ((faceA==FACE_B)&&(faceB==FACE_T)) { clist[cn].posdata[2*n+0] = 0; clist[cn].posdata[2*n+1] = 0; clist[cn].posdata[2*n+2] = 0; clist[cn].posdata[2*n+3] = YSize; clist[cn].Nvertices_max += 2; } } // Calculate area of each contour for (cn=0; cnContoursLabel!=SW_ONOFF_ON)) continue; if ((pass==2)&&(sg->ContoursLabel==SW_ONOFF_ON)) fprintf(x->epsbuffer, "gsave\n"); if ((pass==4)&&(sg->ContoursLabel==SW_ONOFF_ON)) fprintf(x->epsbuffer, "grestore\n"); for (cn=0; cnc->stackPtr; if (clist[cn].Nvertices_max<1) continue; // Set value of c1 if (clist[cn].posdata==NULL) continue; CVar->real = clist[cn].vreal; if ((pass==1)||(pass==3)) // Set before filling and stroking { // Evaluate any expressions in style information for next contour for (i=0 ; ; i++) { int lOP; pplExpr *expr [] = { pd->ww_final.EXPlinetype , pd->ww_final.EXPlinewidth , pd->ww_final.EXPpointlinewidth , pd->ww_final.EXPpointsize , pd->ww_final.EXPpointtype , pd->ww_final.EXPcolor , pd->ww_final.EXPfillcolor , NULL}; double *outD [] = { NULL , &pd->ww_final.linewidth , &pd->ww_final.pointlinewidth , &pd->ww_final.pointsize , NULL , &col , &fc , NULL}; int *outI [] = {&pd->ww_final.linetype , NULL , NULL , NULL , &pd->ww_final.pointtype , NULL , NULL , NULL}; unsigned char *flagU[] = {&pd->ww_final.USElinetype , &pd->ww_final.USElinewidth , &pd->ww_final.USEpointlinewidth , &pd->ww_final.USEpointsize , &pd->ww_final.USEpointtype , NULL , NULL , NULL}; int *flagA[] = {&pd->ww_final.AUTOlinetype, NULL , NULL , NULL , &pd->ww_final.AUTOpointtype, NULL , NULL , NULL}; unsigned char clip [] = {0,0,0,0,0,0,0,2}; pplObj *outval; double dbl; int errpos=-1; if (clip[i]>1) break; if (expr[i]==NULL) continue; outval = ppl_expEval(x->c, expr[i], &lOP, 1, x->iterDepth+1); if (errpos>=0) { sprintf(x->c->errcontext.tempErrStr, "Could not evaluate the style expression <%s>. The error, encountered at character position %d, was: '%s'", expr[i]->ascii, errpos, errtext); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); continue; } if (!outval->dimensionless) { sprintf(x->c->errcontext.tempErrStr, "The style expression <%s> yielded a result which was not a dimensionless number.", expr[i]->ascii); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); continue; } if (outval->flagComplex) { sprintf(x->c->errcontext.tempErrStr, "The style expression <%s> yielded a result which was a complex number.", expr[i]->ascii); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); continue; } if (!gsl_finite(outval->real)) { sprintf(x->c->errcontext.tempErrStr, "The style expression <%s> yielded a result which was not a finite number.", expr[i]->ascii); ppl_error(&x->c->errcontext,ERR_NUMERICAL,-1,-1,NULL); continue; } dbl = outval->real; if (outD[i]!=NULL) *outD[i] = dbl; if (outI[i]!=NULL) { if (dblINT_MAX) dbl=INT_MAX-1; *outI[i] = (int)dbl; } if (flagU[i]!=NULL) *flagU[i] = 1; if (flagA[i]!=NULL) *flagA[i] = 0; EPS_STACK_POP; } EPS_STACK_POP; if ((col1>=0.0)&&(col2>=0.0)&&(col3>=0.0)&&((pd->ww_final. Col1234Space!=SW_COLSPACE_CMYK)||(col4>=0.0))) { pd->ww_final.color1=col1; pd->ww_final.color2=col2; pd->ww_final.color3=col3; pd->ww_final.color4=col4; pd->ww_final.USEcolor=0; pd->ww_final.USEcolor1234=1; pd->ww_final.AUTOcolor=0; } if ((fc1 >=0.0)&&(fc2 >=0.0)&&(fc3 >=0.0)&&((pd->ww_final.FillCol1234Space!=SW_COLSPACE_CMYK)||(fc4 >=0.0))) { pd->ww_final.fillcolor1=fc1; pd->ww_final.fillcolor2=fc2; pd->ww_final.fillcolor3=fc3; pd->ww_final.fillcolor4=fc4; pd->ww_final.USEfillcolor=0; pd->ww_final.USEfillcolor1234=1; } if (gsl_finite(col)) { int j, palette_index; for (j=1; jc->set->palette_current[j]==-1) break; palette_index = (((int)col)-1)%j; while (palette_index < 0) palette_index+=j; pd->ww_final.color = x->c->set->palette_current [palette_index]; pd->ww_final.Col1234Space = x->c->set->paletteS_current[palette_index]; pd->ww_final.color1 = x->c->set->palette1_current[palette_index]; pd->ww_final.color2 = x->c->set->palette2_current[palette_index]; pd->ww_final.color3 = x->c->set->palette3_current[palette_index]; pd->ww_final.color4 = x->c->set->palette4_current[palette_index]; pd->ww_final.USEcolor1234 = (pd->ww_final.color == 0); pd->ww_final.AUTOcolor = 0; pd->ww_final.USEcolor = (pd->ww_final.color > 0); } if (gsl_finite(fc )) { int j, palette_index; for (j=1; jc->set->palette_current[j]==-1) break; palette_index = (((int)fc)-1)%j; while (palette_index < 0) palette_index+=j; pd->ww_final.fillcolor = x->c->set->palette_current [palette_index]; pd->ww_final.FillCol1234Space = x->c->set->paletteS_current[palette_index]; pd->ww_final.fillcolor1 = x->c->set->palette1_current[palette_index]; pd->ww_final.fillcolor2 = x->c->set->palette2_current[palette_index]; pd->ww_final.fillcolor3 = x->c->set->palette3_current[palette_index]; pd->ww_final.fillcolor4 = x->c->set->palette4_current[palette_index]; pd->ww_final.USEfillcolor1234 = (pd->ww_final.fillcolor == 0); pd->ww_final.USEfillcolor = (pd->ww_final.fillcolor > 0); } // Advance automatic plot styles if (pd->ww_final.AUTOcolor) { int i,j; for (j=0; jc->set->palette_current[j]==-1) break; // j now contains length of palette i = ((pd->ww_final.AUTOcolor+clist[cn].i)-5) % j; // i is now the palette color number to use while (i<0) i+=j; if (x->c->set->palette_current[i] > 0) { pd->ww_final.color = x->c->set->palette_current[i]; pd->ww_final.USEcolor = 1; } else { pd->ww_final.Col1234Space = x->c->set->paletteS_current[i]; pd->ww_final.color1 = x->c->set->palette1_current[i]; pd->ww_final.color2 = x->c->set->palette2_current[i]; pd->ww_final.color3 = x->c->set->palette3_current[i]; pd->ww_final.color4 = x->c->set->palette4_current[i]; pd->ww_final.USEcolor1234 = 1; } } else if (pd->ww_final.AUTOlinetype) pd->ww_final.linetype = pd->ww_final.AUTOlinetype + clist[cn].i; } // PASS 1: Fill path, if required if (pass==1) { // eps_core_SetFillColor(x, &pd->ww_final); // eps_core_SwitchTo_FillColor(x,1); // IF_NOT_INVISIBLE // { // double xps, yps; long c=0; // xpos = clist[cn].posdata[c++]; // ypos = clist[cn].posdata[c++]; // XPOS_TO_POSTSCRIPT; // fprintf(x->epsbuffer, "newpath %.2f %.2f moveto\n", xps, yps); // while (c<2*clist[cn].Nvertices_max) // { // xpos = clist[cn].posdata[c++]; // ypos = clist[cn].posdata[c++]; // XPOS_TO_POSTSCRIPT; // fprintf(x->epsbuffer, "%.2f %.2f lineto\n", xps, yps); // } // fprintf(x->epsbuffer, "closepath fill\n"); // } } // PASS 2: Set clip path before stroking else if (pass==2) { long n=clist[cn].Nvertices_max; if (n<1) continue; if (sg->ContoursLabel==SW_ONOFF_ON) { int page = x->current->DatasetTextID[pdn]+clist[cn].i; long i = clist[cn].segment_flatest; double xlab0= (clist[cn].posdata[2*((i )%n)+0] + clist[cn].posdata[2*((i+1)%n)+0] )/2; double ylab0= (clist[cn].posdata[2*((i )%n)+1] + clist[cn].posdata[2*((i+1)%n)+1] )/2; double xlab, ylab, wlab, hlab; double bb_top,bb_bottom,ab_left,ab_right; postscriptPage *dviPage; xlab = xo + Lx*xlab0/(XSize-1)*sin(ThetaX) + Ly*ylab0/(YSize-1)*sin(ThetaY); ylab = yo + Lx*xlab0/(XSize-1)*cos(ThetaX) + Ly*ylab0/(YSize-1)*cos(ThetaY); if (x->dvi == NULL) { continue; } dviPage = (postscriptPage *)ppl_listGetItem(x->dvi->output->pages, page+1); if (dviPage== NULL) { continue; } //bb_left = dviPage->boundingBox[0]; bb_bottom = dviPage->boundingBox[1]; //bb_right = dviPage->boundingBox[2]; bb_top = dviPage->boundingBox[3]; ab_left = dviPage->textSizeBox[0]; //ab_bottom = dviPage->textSizeBox[1]; ab_right = dviPage->textSizeBox[2]; //ab_top = dviPage->textSizeBox[3]; hlab = (fabs(bb_top - bb_bottom) + 2) * x->current->settings.FontSize; wlab = (fabs(ab_right - ab_left) + 2) * x->current->settings.FontSize; fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto %.2f %.2f lineto %.2f %.2f lineto closepath %.2f %.2f %.2f 0 360 arc closepath eoclip\n", xlab-wlab/2, ylab-hlab/2, xlab+wlab/2, ylab-hlab/2, xlab+wlab/2, ylab+hlab/2, xlab-wlab/2, ylab+hlab/2, xlab, ylab, 2*(Lx+Ly)); } } // PASS 3: Stroke path else if (pass==3) { eps_core_SetColor(x, &pd->ww_final, 1); eps_core_SetLinewidth(x, EPS_DEFAULT_LINEWIDTH * pd->ww_final.linewidth, pd->ww_final.linetype, 0); IF_NOT_INVISIBLE { double xps, yps; long c=0; long n=clist[cn].Nvertices_max; if (n<1) continue; xpos = clist[cn].posdata[c++]; ypos = clist[cn].posdata[c++]; XPOS_TO_POSTSCRIPT; fprintf(x->epsbuffer, "newpath %.2f %.2f moveto\n", xps, yps); while (c<2*clist[cn].Nvertices_min) { xpos = clist[cn].posdata[c++]; ypos = clist[cn].posdata[c++]; XPOS_TO_POSTSCRIPT; fprintf(x->epsbuffer, "%.2f %.2f lineto\n", xps, yps); } fprintf(x->epsbuffer, "%sstroke\n", clist[cn].closepath?"closepath ":""); } } // PASS 4: Label contours else if ((pass==4) && (sg->ContoursLabel==SW_ONOFF_ON)) { long i = clist[cn].segment_flatest; long n = clist[cn].Nvertices_max; withWords ww; if (n<1) continue; ppl_withWordsZero(x->c,&ww); if (x->current->settings.TextColor > 0) { ww.color = x->current->settings.TextColor; ww.USEcolor = 1; } else { ww.Col1234Space = x->current->settings.TextCol1234Space; ww.color1 = x->current->settings.TextColor1; ww.color2 = x->current->settings.TextColor2; ww.color3 = x->current->settings.TextColor3; ww.color4 = x->current->settings.TextColor4; ww.USEcolor1234 = 1; } eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE { double xlab = (clist[cn].posdata[2*((i )%n)+0] + clist[cn].posdata[2*((i+1)%n)+0] )/2; double ylab = (clist[cn].posdata[2*((i )%n)+1] + clist[cn].posdata[2*((i+1)%n)+1] )/2; canvas_EPSRenderTextItem(x, NULL, x->current->DatasetTextID[pdn]+clist[cn].i, (xo + Lx*xlab/(XSize-1)*sin(ThetaX) + Ly*ylab/(YSize-1)*sin(ThetaY))/M_TO_PS, (yo + Lx*xlab/(XSize-1)*cos(ThetaX) + Ly*ylab/(YSize-1)*cos(ThetaY))/M_TO_PS, SW_HALIGN_CENT, SW_VALIGN_CENT, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } } } } // Reset value of variable c1 if (CVar!=NULL) ppl_contextRestoreVarPointer(x->c, c1name, &CDummy); return 0; } pyxplot-0.9.2/src/epsMaker/eps_point.c0000664000175000017500000001017612026340554016333 0ustar dcf21dcf21// eps_point.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_point.c 1301 2012-09-02 15:42:16Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_POINT 1 #include #include #include #include "coreUtils/memAlloc.h" #include "epsMaker/canvasDraw.h" #include "coreUtils/errorReport.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_styles.h" #include "epsMaker/eps_point.h" #include "epsMaker/eps_settings.h" #include "epsMaker/eps_style.h" void eps_point_YieldUpText(EPSComm *x) { CanvasTextItem *i; if (x->current->text != NULL) { x->current->FirstTextID = x->NTextItems; if (x->current->text[0]=='\0') return; i = (CanvasTextItem *)ppl_memAlloc(sizeof(CanvasTextItem)); if (i==NULL) { ppl_error(&x->c->errcontext,ERR_MEMORY, -1, -1, "Out of memory"); *(x->status) = 1; return; } i->text = x->current->text; i->CanvasMultiplotID = x->current->id; ppl_listAppend(x->TextItems, i); x->NTextItems++; } return; } void eps_point_RenderEPS(EPSComm *x) { int pt, lt; double lw, lw_scale, xpos, ypos; withWords ww, ww_default; int pageno; pageno = x->LaTeXpageno = x->current->FirstTextID; x->LaTeXpageno++; // Print label at top of postscript description of box fprintf(x->epsbuffer, "%% Canvas item %d [point]\n", x->current->id); eps_core_clear(x); // Look up position of point xpos = x->current->xpos * M_TO_PS; ypos = x->current->ypos * M_TO_PS; // Expand any numbered styles which may appear in the with words we are passed eps_withwords_default(x, &ww_default, &x->current->settings, 0, 0, 0, 0, 0); ppl_withWordsMerge(x->c, &ww, &x->current->with_data, &ww_default, NULL, NULL, NULL, 1); // Display point eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE { // Set linewidth and linetype of point if (ww.USElinewidth) lw_scale = ww.pointlinewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; lt = 1; eps_core_SetLinewidth(x, lw, lt, 0.0); fprintf(x->epsbuffer, "/ps { %f } def\n", ww.pointsize * EPS_DEFAULT_PS); pt = (ww.pointtype-1) % N_POINTTYPES; while (pt<0) pt+=N_POINTTYPES; x->PointTypesUsed[pt] = 1; fprintf(x->epsbuffer, "%.2f %.2f pt%d\n", xpos, ypos, pt+1); eps_core_BoundingBox(x, xpos, ypos, 2 * ww.pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS); // Label point if it is labelled if ((x->current->text != NULL) && (x->current->text[0]!='\0')) { const double xsp = (x->current->settings.TextVAlign == SW_VALIGN_CENT) ? 1.7 : 1.13; const double ysp = (x->current->settings.TextHAlign == SW_HALIGN_CENT) ? 1.7 : 1.13; canvas_EPSRenderTextItem(x, NULL, pageno, x->current->xpos - (x->current->settings.TextHAlign - SW_HALIGN_CENT) * ww.pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS / M_TO_PS * xsp, x->current->ypos + (x->current->settings.TextVAlign - SW_VALIGN_CENT) * ww.pointsize * eps_PointSize[pt] * EPS_DEFAULT_PS / M_TO_PS * ysp, x->current->settings.TextHAlign, x->current->settings.TextVAlign, x->CurrentColor, x->current->settings.FontSize, 0.0, NULL, NULL); } } // Free with words ppl_withWordsDestroy(x->c, &ww); ppl_withWordsDestroy(x->c, &ww_default); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_settings.h0000664000175000017500000000457012026340554017050 0ustar dcf21dcf21// eps_settings.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_settings.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_SETTINGS_H #define _PPL_EPS_SETTINGS_H 1 // Baseline values of settings used by the eps generation routines #define EPS_BASE_DEFAULT_LINEWIDTH ( 0.566929 ) /* 0.2mm in TeX points */ #define EPS_BASE_DEFAULT_PS ( 3.0 ) #define EPS_BASE_ARROW_ANGLE ( 45.0 *M_PI/180 ) #define EPS_BASE_ARROW_CONSTRICT ( 0.2 ) #define EPS_BASE_ARROW_HEADSIZE ( 6.0 ) #define EPS_BASE_AXES_LINEWIDTH ( 1.0 ) #define EPS_BASE_AXES_MAJTICKLEN ( 0.0012 ) #define EPS_BASE_AXES_MINTICKLEN ( 0.000848528137 ) /* 0.0012 divided by sqrt(2) */ #define EPS_BASE_AXES_SEPARATION ( 0.008 ) #define EPS_BASE_AXES_TEXTGAP ( 0.003 ) #define EPS_BASE_COLORSCALE_MARG ( 3e-3 ) #define EPS_BASE_COLORSCALE_WIDTH ( 4e-3 ) #define EPS_BASE_GRID_MAJLINEWIDTH ( 1.0 ) #define EPS_BASE_GRID_MINLINEWIDTH ( 0.5 ) // Copies of the values actually used by the eps generation routines, which may have been scaled relative to their baselines #ifndef _PPL_EPS_SETTINGS_C extern double M_TO_PS; extern double EPS_DEFAULT_LINEWIDTH; extern double EPS_DEFAULT_PS; extern double EPS_ARROW_ANGLE; extern double EPS_ARROW_CONSTRICT; extern double EPS_ARROW_HEADSIZE; extern double EPS_AXES_LINEWIDTH; extern double EPS_AXES_MAJTICKLEN; extern double EPS_AXES_MINTICKLEN; extern double EPS_AXES_SEPARATION; extern double EPS_AXES_TEXTGAP; extern double EPS_COLORSCALE_MARGIN; extern double EPS_COLORSCALE_WIDTH; extern double EPS_GRID_MAJLINEWIDTH; extern double EPS_GRID_MINLINEWIDTH; #endif #endif pyxplot-0.9.2/src/epsMaker/eps_box.h0000664000175000017500000000163212026340554015774 0ustar dcf21dcf21// eps_box.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_box.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_BOX_H #define _PPL_EPS_BOX_H 1 #include "epsMaker/eps_comm.h" void eps_box_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/bmp_jpegread.c0000664000175000017500000002067112026340554016753 0ustar dcf21dcf21// bmp_jpegread.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2012 Michael Rutter // // $Id: bmp_jpegread.c 1276 2012-07-25 22:50:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from JPEG files without performing any // decompression, since the DCT-compressed data can be rewritten straight out // to postscript for decompression by the postscript rasterising engine. #define _PPL_BMP_JPEGREAD_C 1 #include #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" #include "epsMaker/bmp_jpegread.h" #define HEADLEN 8*1024 void ppl_bmp_jpegread(pplerr_context *ec, FILE *jpeg, bitmap_data *image) { int comps=0, i, j; unsigned int width=0, height=0, save, sos; unsigned int len, chunk=64*1024; unsigned char *buff, *header, *headp, *headendp, type=0, comp=0, *p; BMP_ALLOC(buff, chunk); header = (unsigned char *)ppl_memAlloc(HEADLEN); headp = header; headendp = header + HEADLEN - 8; if (DEBUG) ppl_log(ec, "Beginning to decode JPEG image file"); if ((buff == NULL)||(header == NULL)) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } *(headp++)=0xff; *(headp++)=0xd8; do { if (fread(buff,3,1,jpeg)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This JPEG image file appears to be corrupted (A)"); return; } type=buff[0]; len=buff[1]*256+buff[2]-2; save=0; if (fread(buff,len,1,jpeg)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This JPEG image file appears to be corrupted (B)"); return; } if (DEBUG) { sprintf(ec->tempErrStr,"Entry type %x length 0x%x",(int)type,len+2); ppl_log(ec, NULL); } if ((type==0xe0)&&!strcmp((char*)buff,"JFIF")) { if ( ((buff[7]==1)||(buff[7]==2)) ) { image->XDPI=buff[8]*256+buff[9]; image->YDPI=buff[10]*256+buff[11]; if (buff[7]==2) /* units were pixels per cm */ { image->XDPI*=25.4; image->YDPI*=25.4; } } if (DEBUG) { sprintf(ec->tempErrStr, "JPEG version %d.%02d",(int)buff[5],(int)buff[6]); ppl_log(ec, NULL); sprintf(ec->tempErrStr, "JFIF thumbnail size %dx%d", (int)buff[12],(int)buff[13]); ppl_log(ec, NULL); if (image->XDPI) { sprintf(ec->tempErrStr, "DPI: %.1fx%.1f",image->XDPI, image->YDPI); ppl_log(ec, NULL); } sprintf(ec->tempErrStr, "JFIF APP0 entry length 0x%x",len+2); ppl_log(ec, NULL); } } if (DEBUG && ((type==0xe1) && (!strcmp((char*)buff,"Exif"))) ) { sprintf(ec->tempErrStr, "Exif JPEG file"); ppl_log(ec, NULL); sprintf(ec->tempErrStr, "Exif APP1 entry length 0x%x",len+2); ppl_log(ec, NULL); } if ( ((type&0xf0)==0xc0) && (type!=0xc4) && (type!=0xcc) ) { if (comp) { ppl_error(ec, ERR_FILE, -1, -1, "Cannot decode JPEG image file: it contains multiple images?"); return; } comp = type; height = 256*buff[1]+buff[2]; width = 256*buff[3]+buff[4]; comps = buff[5]; save = 1; } if (DEBUG && (type==0xfe)) { buff[len]=0; sprintf(ec->tempErrStr, "JPEG Comment: %s",buff); ppl_log(ec, NULL); } if (DEBUG && (type==0xe0)) { sprintf(ec->tempErrStr, "APP0 Marker: %s",buff); ppl_log(ec, NULL); } if (DEBUG && (type==0xdd)) { sprintf(ec->tempErrStr, "Restart markers present"); ppl_log(ec, NULL); } if ((type==0xdb)||(type==0xc4)||(type==0xda)||(type==0xdd)) save=1; if (save) { *(headp++)=0xff; *(headp++)=type; *(headp++)=(len+2)>>8; *(headp++)=(len+2)&0xff; if (headp+len>headendp) { ppl_error(ec, ERR_FILE, -1, -1, "JPEG header storage exhausted"); return ; } for (i=0; itempErrStr, "Discarding section of JPEG image file."); ppl_log(ec, NULL); } } while ((type!=0xda) && fread(buff,1,1,jpeg) && (buff[0]==0xff)); if (DEBUG) { sprintf(ec->tempErrStr, "Image size %dx%d with %d components",width,height,comps); ppl_log(ec, NULL); } switch (comp) { case 0xc0: if (DEBUG) ppl_log(ec, "Encoding: baseline JPEG"); break; case 0xc1: if (DEBUG) ppl_log(ec, "Encoding: extended sequential, Huffman JPEG"); break; case 0xc2: ppl_error(ec, ERR_FILE, -1, -1, "JPEG image detected to have progressive encoding, which Pyxplot does not support. Please convert to baseline JPEG and try again."); return; default: sprintf(ec->tempErrStr, "JPEG image detected to have unsupported compression type SOF%d. Please convert to baseline JPEG and try again.",((int)comp)&0xf); ppl_error(ec, ERR_FILE, -1, -1, NULL); return; } if ((comps!=3) && (comps!=1)) { sprintf(ec->tempErrStr,"JPEG image contains %d colour components; Pyxplot only supports JPEG images with one (greyscale) or three (RGB) components", comps); ppl_error(ec, ERR_FILE, -1, -1, NULL); return; } if (comps == 3) { image->colour = BMP_COLOUR_RGB; image->depth = 24; } else { image->colour = BMP_COLOUR_GREY; image->depth = 8; } image->width = width; image->height = height; image->TargetCompression = BMP_ENCODING_DCT; // Now read JPEG image data. Unfortunately, we don't know how much we'll get if (DEBUG) { sprintf(ec->tempErrStr, "%d bytes of header read",(int)(headp-header)); ppl_log(ec, NULL); } for(i=0; header+idata_len = i+j; } else { i=j; while (i==len) { chunk *= 2; BMP_ALLOC(p , chunk); // We didn't malloc enough memory, and ppl_memAlloc can't realloc, so just have to malloc a new chunk :( if (p == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return; } memcpy(p, buff, chunk/2); buff = p; len = chunk/2; i = fread(buff+len,1,len,jpeg); } image->data_len=len+i; } // Check what we have read for integrity and trailing rubbish. Assume that // the first two bytes are 0xffd8. Then we need not deal with awkward markers // which are not followed by lengths... i =2; sos=0; while(idata_len) { if (buff[i]!=0xff) { if (DEBUG) { sprintf(ec->tempErrStr, "Offset %d",i); ppl_log(ec, NULL); } ppl_error(ec, ERR_FILE, -1, -1, "Unexpected data in JPEG - no marker where expected"); return; } i++; if (DEBUG) { sprintf(ec->tempErrStr, "Check: entry type %x ...",buff[i]); ppl_log(ec, NULL); } if (buff[i]==0xd9) break; // End of image if (buff[i]==0xda) sos=1; if (buff[i]==0xd8) { ppl_error(ec, ERR_FILE, -1, -1, "Unexpected extra SOI in JPEG data."); return; } i++; len=buff[i]*256+buff[i+1]-2; i+=2; if (DEBUG) { sprintf(ec->tempErrStr, "... length 0x%x",len+2); ppl_log(ec, NULL); } i+=len; if (sos) // We now have an entropy-encoded section of unknown length { j=i; // Entropy-encoded sections stop at a marker (0xff), save that they // don't for 0xff00, and it is easiest to consider the restart markers // 0xffd0 to 0xffd7 to be part of the entropy-encoded section while (!((i>=image->data_len) || ((buff[i]==0xff)&&((buff[i+1]!=0)&&((buff[i+1]&0xf8)!=0xd0))))) i++; if (DEBUG) { sprintf(ec->tempErrStr, "Check: entropy encoded section %d bytes",i-j); ppl_log(ec, NULL); } sos=0; } } if (buff[i]!=0xd9) { ppl_error(ec, ERR_FILE, -1, -1, "Error -- JPEG EOI not found, file corrupted/truncated?"); return; } if (DEBUG && (i+1data_len)) { sprintf(ec->tempErrStr, "%lu bytes of trailing garbage removed from JPEG", image->data_len-i-1); ppl_log(ec, NULL); } image->data=buff; image->data_len=i+1; return; } pyxplot-0.9.2/src/epsMaker/dvi_font.h0000664000175000017500000000670612026340554016154 0ustar dcf21dcf21// dvi_font.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_font.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating dvi files -- font section #ifndef _PPL_DVI_FONT_H #define _PPL_DVI_FONT_H 1 #include "coreUtils/errorReport.h" #define ASCII_CHAR_A_UP 65 #define ASCII_CHAR_Z_UP 90 #define ASCII_CHAR_A_DN 97 #define ASCII_CHAR_Z_DN 122 #define FONT_UNKNOWN 0 #define FONT_TEX_TEXT 1 #define FONT_TEX_MATH 2 #define FONT_TEX_MEXT 3 #define FONT_TEX_MSYM 4 #define FONT_SYMBOL 10 typedef struct TFMcharInfo { char wi; // Width index char hi; // Height index char di; // Depth index char ii; // Italic index char tag; char rem; } TFMcharInfo; // Information for dealing with ligatures typedef struct TFMligKern { char skip_byte; char next_char; char op_byte; char remainder; } TFMligKern; typedef struct TFMextRec { char top, mid, bot, rep; } TFMextRec; typedef struct dviTFM { int lf; // length of the entire file, in words int lh; // length of the header data, in words int bc; // smallest character code in the font int ec; // largest character code in the font int nw; // number of words in the width table int nh; // number of words in the height table int nd; // number of words in the depth table int ni; // number of words in the italic correction table int nl; // number of words in the lig/kern table int nk; // number of words in the kern table int ne; // number of words in the extensible character table int np; // number of font parameter words // Header int checksum; double ds; // Design size of font char coding[40]; char family[20]; int face; // Tables TFMcharInfo *charInfo; double *width, *height, *depth, *italic; TFMligKern *ligKern; double *kern; TFMextRec * extensibleRecipe; double *param; } dviTFM; typedef struct dviFontDetails { int number; char *area; // "Area" that the font is given as living in char *name; // Font name char *psName; // Name to use for font in postscript file int useSize, desSize; // Use and design sizes dviTFM *tfm; // Data from tfm file char *pfaPath; // PFA file location // Maximum dimensions of glyphs double maxHeight, maxDepth; // Type of font int fontType; } dviFontDetails; // Call the first of these functions, passing it a font structure. It will find and read the corresponding TFM file. int dviGetTFM (pplerr_context *ec, dviFontDetails *font); dviTFM *dviReadTFM (pplerr_context *ec, FILE *fp, int *err); int dviFindMaxSize(pplerr_context *ec, dviFontDetails *font); int pfb2pfa (pplerr_context *ec, FILE *in, FILE *out); char *psNameFromPFA (pplerr_context *ec, char *PFApath); #endif pyxplot-0.9.2/src/epsMaker/eps_core.h0000664000175000017500000000356412026340554016142 0ustar dcf21dcf21// eps_core.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_core.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_CORE_H #define _PPL_EPS_CORE_H 1 #define IF_NOT_INVISIBLE if (x->CurrentColor[0]!='\0') #define EPS_STACK_POP \ while (x->c->stackPtr>stkLevelOld) \ { \ x->c->stackPtr--; \ ppl_garbageObject(&x->c->stack[x->c->stackPtr]); \ if (x->c->stack[x->c->stackPtr].refCount != 0) { ppl_error(&x->c->errcontext,ERR_INTERNAL,-1,-1,"Stack forward reference detected."); } \ } #include "epsMaker/eps_comm.h" void eps_core_clear (EPSComm *x); void eps_core_WritePSColor (EPSComm *x); void eps_core_SetColor (EPSComm *x, withWords *ww, unsigned char WritePS); void eps_core_SetFillColor (EPSComm *x, withWords *ww); void eps_core_SwitchTo_FillColor (EPSComm *x, unsigned char WritePS); void eps_core_SwitchFrom_FillColor(EPSComm *x, unsigned char WritePS); void eps_core_SetLinewidth (EPSComm *x, double lw, int lt, double offset); void eps_core_BoundingBox (EPSComm *x, double xpos, double ypos, double lw); void eps_core_PlotBoundingBox (EPSComm *x, double xpos, double ypos, double lw, unsigned char UpdatePsBB); #endif pyxplot-0.9.2/src/epsMaker/bmp_bmpread.h0000664000175000017500000000262412026340554016607 0ustar dcf21dcf21// bmp_bmpread.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_bmpread.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from Windows and OS/2 bitmap files. #ifndef _PPL_BMP_BMPREAD_H #define _PPL_BMP_BMPREAD_H 1 #include #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" void ppl_bmp_bmpread (pplerr_context *ec, FILE *in, bitmap_data *image); void ppl_bmp_bmp16read (pplerr_context *ec, FILE *in, unsigned char *header, bitmap_data *image); int ppl_bmp_demsrle (pplerr_context *ec, bitmap_data *image, unsigned char *in, unsigned long len); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto2.h0000664000175000017500000000212512026340554021002 0ustar dcf21dcf21// eps_plot_ticking_auto2.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto2.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_TICKING_AUTO2_H #define _PPL_EPS_PLOT_TICKING_AUTO2_H 1 #include "epsMaker/eps_comm.h" #include "settings/settings.h" void eps_plot_ticking_auto2(EPSComm *x, pplset_axis *axis, double UnitMultiplier, unsigned char *AutoTicks, pplset_axis *linkedto); #endif pyxplot-0.9.2/src/epsMaker/bmp_pngread.c0000664000175000017500000001573712026340554016621 0ustar dcf21dcf21// bmp_pngread.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_pngread.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from PNG files uses libpng. #define _PPL_BMP_PNGREAD_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" #include "epsMaker/bmp_pngread.h" void ppl_bmp_pngread(pplerr_context *ec, FILE *in, bitmap_data *image) { int depth,ncols,ntrans,png_colour_type,i,j; unsigned width,height,row_bytes; static unsigned char index[3]; png_structp png_ptr; png_infop info_ptr; png_bytep *row_ptrs,trans_colours; png_color_16p trans_val; png_color_16p backgndp; png_color_16 background; png_colorp palette; if (DEBUG) ppl_log(ec, "Beginning to decode PNG image file"); // Initialise libpng data structures png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); if (png_ptr == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } info_ptr = png_create_info_struct(png_ptr); if (info_ptr == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } if (setjmp(png_jmpbuf(png_ptr))) { ppl_error(ec, ERR_INTERNAL, -1, -1, "Unexpected error in libpng while trying to decode PNG image file"); return; } png_init_io(png_ptr, in); png_set_sig_bytes(png_ptr, 3); // Three bytes consumed before this routine was called // Let libpng read header, and deal with outcome png_read_info(png_ptr, info_ptr); width = png_get_image_width (png_ptr,info_ptr); height = png_get_image_height(png_ptr,info_ptr); depth = png_get_bit_depth (png_ptr,info_ptr); png_colour_type = png_get_color_type (png_ptr,info_ptr); if (DEBUG) { sprintf(ec->tempErrStr, "Size %dx%d", width, height); ppl_log(ec, NULL); } if (DEBUG) { sprintf(ec->tempErrStr, "Depth %d", depth); ppl_log(ec, NULL); } if (depth==16) { if (DEBUG) ppl_log(ec, "Reducing 16 bit per components to 8 bits"); png_set_strip_16(png_ptr); depth=8; } if (png_colour_type & PNG_COLOR_MASK_ALPHA) { if (DEBUG) ppl_log(ec, "PNG uses transparency"); if (png_get_bKGD(png_ptr,info_ptr,&backgndp)) { if (DEBUG) ppl_log(ec, "PNG defines a background colour"); png_set_background(png_ptr,backgndp,PNG_BACKGROUND_GAMMA_FILE,1,1.0); } else { if (DEBUG) ppl_log(ec, "PNG does not define a background colour"); background.red = background.green = background.blue = background.gray = 0xff; // Define background colour to be white png_set_background(png_ptr,&background,PNG_BACKGROUND_GAMMA_FILE,0,1.0); } } if ( (png_colour_type == PNG_COLOR_TYPE_GRAY) || (png_colour_type == PNG_COLOR_TYPE_GRAY_ALPHA)) image->colour = BMP_COLOUR_GREY; if ( (png_colour_type == PNG_COLOR_TYPE_RGB ) || (png_colour_type == PNG_COLOR_TYPE_RGB_ALPHA )) image->colour = BMP_COLOUR_RGB; if (png_colour_type == PNG_COLOR_TYPE_PALETTE) { image->type = BMP_COLOUR_PALETTE; image->colour = BMP_COLOUR_PALETTE; i = png_get_PLTE(png_ptr,info_ptr,&palette,&ncols); if (i==0) { ppl_error(ec, ERR_FILE, -1, -1, "PNG image file claims to be paletted, but no palette was found"); return; } image->pal_len = ncols; BMP_ALLOC(image->palette , ncols*3); if (image->palette == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } for (i=0; ipalette+3*i ) = palette[i].red; *(image->palette+3*i+1) = palette[i].green; *(image->palette+3*i+2) = palette[i].blue; } if (DEBUG) { sprintf(ec->tempErrStr, "PNG image file contains a palette of %d colours", ncols); ppl_log(ec, NULL); } } else { image->type = BMP_COLOUR_BMP; } // Update png info to reflect any requested conversions (e.g. 16 bit to 8 bit or Alpha to non-alpha png_read_update_info(png_ptr, info_ptr); // Now rowbytes will reflect what we will get, not what we had originally row_bytes = png_get_rowbytes(png_ptr, info_ptr); // Allocate block of memory for uncompressed image BMP_ALLOC(image->data , row_bytes*height); if (image->data == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } // libpng requires a separate pointer to each row of image row_ptrs = (png_bytep *)ppl_memAlloc(height*sizeof(png_bytep)); if (row_ptrs == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); image->data = NULL; return; } for (i=0; idata + row_bytes*i; // Get uncompressed image png_read_image(png_ptr, row_ptrs); // Free everything we don't need png_read_end(png_ptr,NULL); // Deal with transparency (we can only support images with single transparent palette entries) if (png_get_valid(png_ptr,info_ptr,PNG_INFO_tRNS)) { if (DEBUG) ppl_log(ec, "PNG has transparency"); png_get_tRNS(png_ptr, info_ptr, &trans_colours, &ntrans, &trans_val); if (DEBUG) { sprintf(ec->tempErrStr, "PNG has %d transparent entries in palette", ntrans); ppl_log(ec, NULL); } if (png_colour_type == PNG_COLOR_TYPE_PALETTE) { // We can cope with just one, fully transparent, entry in palette j=0; for (i=0; itrans = index; *image->trans = i; } } else { image->trans = index; *image->trans = trans_val->gray; if (image->colour == BMP_COLOUR_RGB) { image->trans[0] = trans_val->red; image->trans[1] = trans_val->green; image->trans[2] = trans_val->blue; } } } png_destroy_read_struct(&png_ptr, &info_ptr,(png_infopp)NULL); // Put all necessary information into the output data structure image->data_len = ((long)row_bytes)*height; image->height = height; image->width = width; image->depth = depth; if (image->colour == BMP_COLOUR_RGB) image->depth*=3; return; } pyxplot-0.9.2/src/epsMaker/bmp_pngread.h0000664000175000017500000000230012026340554016604 0ustar dcf21dcf21// bmp_pngread.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_pngread.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from PNG files uses libpng. #ifndef _PPL_BMP_PNGREAD_H #define _PPL_BMP_PNGREAD_H 1 #include #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" void ppl_bmp_pngread(pplerr_context *ec, FILE *in, bitmap_data *image); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto.c0000664000175000017500000014242712026340554020725 0ustar dcf21dcf21// eps_plot_ticking_auto.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contain an algorithm for the automatic placement of ticks along axes. // METHOD 1: Axes which are 'linked using' or which have non-trivial 'format' // expressions. The axis is broken up into many small sections and a list of // 'significant' points constructed. #define _PPL_EPS_PLOT_TICKING_AUTO_C 1 #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "stringTools/asciidouble.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_ticking.h" #include "epsMaker/eps_plot_ticking_auto.h" #include "epsMaker/eps_plot_ticking_auto2.h" #include "epsMaker/eps_plot_ticking_auto3.h" #define MAX_ARGS 32 /* Maximum number of substitution arguments in 'set format' which we analyse */ #define STEP_DUPLICITY 100 /* Controls how many steps we divide axis into, multiplied by max number of ticks which fit on axis */ #define MAX_TICKS_PER_INTERVAL 20 /* Maximum number of ticks which we file in any interval */ #define MAX_FACTORS 32 /* Maximum number of factors of LogBase which we consider */ #define FACTOR_MULTIPLY 2.0 /* Factorise LogBase**2, so that 0.00,0.25,0.50,0.75,1.00 is a valid factorisation */ #define NOT_THROW 9999 /* Value we put in DivOfThrow when a tick isn't dividing throw (to get sorting right) */ #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { ppl_warning(&c->errcontext,ERR_STACKED,"Stack forward reference detected."); } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } // Structure used for storing information about a substitution argument in 'set format' typedef struct ArgumentInfo { int id, score, NValueChanges, Throw, FactorsThrow[MAX_FACTORS], NFactorsThrow; unsigned char StringArg, ContinuousArg, MinValueSet, MaxValueSet, vetoed, OoM_RangeSet; int OoM_min, OoM_max; double MinValue, MaxValue; // Work out range of values which this argument takes (aka the 'throw') double *NumericValues; // Raster of values sampled along axis char **StringValues; } ArgumentInfo; // Structure used when sorting a list of ints according to some double-precision 'score' typedef struct ArgLeagueTableEntry { int id; double score; } ArgLeagueTableEntry; // Structure used for storing information about a potential tick which we might put on the axis typedef struct PotentialTick { int ArgNo; // The argument whose changing is marked by this tick int DivOfThrow; // This tick divides up throw of argument in one of its factors int OoM; // The order of magnitude of the digit which changes on this tick int DivOfOoM; // Order of magnitude is being split up into factors of log base int IntervalNum; // Number of the interval in which this tick lies double TargetValue; // Target value of argument where this tick should be placed int OrderPosition; // Position of this tick in TickOrder } PotentialTick; // Compare two ArgumentInfo structures; used by qsort int compare_arg(const void *x, const void *y) { const ArgumentInfo *xai, *yai; xai = (const ArgumentInfo *)x; yai = (const ArgumentInfo *)y; if ((!xai->vetoed) && ( yai->vetoed)) return -1; if (( xai->vetoed) && (!yai->vetoed)) return 1; if ((!xai->ContinuousArg) && ( yai->ContinuousArg)) return -1; // Discrete arguments more important than continuous if (( xai->ContinuousArg) && (!yai->ContinuousArg)) return 1; if (!xai->ContinuousArg) { if (xai->NValueChanges < yai->NValueChanges) return -1; // Slow-moving continuous arguments most important if (xai->NValueChanges > yai->NValueChanges) return 1; } else { if (xai->score < yai->score) return -1; // Slow-moving continuous arguments most important if (xai->score > yai->score) return 1; } return 0; } // Compare two ArgLeagueTableEntry structures; used by qsort int compare_ArgLeagueEntry(const void *x, const void *y) { const ArgLeagueTableEntry *xalte, *yalte; xalte = (const ArgLeagueTableEntry *)x; yalte = (const ArgLeagueTableEntry *)y; if (xalte->score > yalte->score) return -1; if (xalte->score < yalte->score) return 1; return 0; } // Compare two PotentialTick structures; used by qsort int compare_PotentialTicks(const void *x, const void *y) { const PotentialTick *xpt, *ypt; xpt = (const PotentialTick *)x; ypt = (const PotentialTick *)y; if (xpt->ArgNo > ypt->ArgNo ) return 1; if (xpt->ArgNo < ypt->ArgNo ) return -1; if (xpt->DivOfThrow > ypt->DivOfThrow) return 1; if (xpt->DivOfThrow < ypt->DivOfThrow) return -1; if (xpt->OoM > ypt->OoM ) return -1; if (xpt->OoM < ypt->OoM ) return 1; if (xpt->DivOfOoM > ypt->DivOfOoM ) return 1; if (xpt->DivOfOoM < ypt->DivOfOoM ) return -1; return 0; } // Return up to a maximum of MaxFactors factors of in. Factors are returned to array out. static void factorise(int in, int *out, int MaxFactors, int FactorMax, int *NFactors) { int i,j=0,k,N=sqrt(in); for (i=2; i<=N; i++) if (in%i==0) { out[j]=i; out[MaxFactors-1-j]=in/i; j++; if (j>=MaxFactors/2) break; } for (i=MaxFactors-j; i<=MaxFactors-1; i++) { out[j] = out[i]; if (out[j]!=out[j-1]) j++; } for (i=0; i=0)&&(PotTickList[TickOrder[j].id].IntervalNum>=IntNum-1)&&(PotTickList[TickOrder[j].id].IntervalNum<=IntNum+1)); j--) if ((TicksAcceptedOut[j]>0) && (PotTickList[id].TargetValue == PotTickList[TickOrder[j].id].TargetValue)) { if (MAJORminor ) TicksAcceptedOut[j]=0; // Major ticks overwrite minor ticks else if (TicksAcceptedOut[j]==1) abort=1; // Minor ticks don't overwrite major ticks else if (TicksAcceptedOut[j]==2) TicksAcceptedOut[j]=0; // Minor ticks overwrite minor ticks } // Apply same tests to ticks accepted immediately to the right of this tick for (j=i+1; ((j=IntNum-1)&&(PotTickList[TickOrder[j].id].IntervalNum<=IntNum+1)); j++) if ((TicksAcceptedOut[j]>0) && (PotTickList[id].TargetValue == PotTickList[TickOrder[j].id].TargetValue)) { if (MAJORminor ) TicksAcceptedOut[j]=0; else if (TicksAcceptedOut[j]==1) abort=1; else if (TicksAcceptedOut[j]==2) TicksAcceptedOut[j]=0; } // If above tests haven't cancelled this tick (minor tick trying to overwrite major tick), accept it if (!abort) { TicksAcceptedOut[i] = MAJORminor ? 1 : 2; if ((imin<0) || (imin>PotTickList[id].IntervalNum)) imin = PotTickList[id].IntervalNum; // Update span of this tick scheme if ((imax<0) || (imax=0; j--) // Scan left for nearest accepted tick if (TicksAcceptedOut[j]==1) { double gap = fabs(PotTickList[id].IntervalNum - PotTickList[TickOrder[j].id].IntervalNum) * AxisLength / (NIntervals-1); if (gap < 1) *FLAGacceptable = 0; // Gap between this tick and that to our left is too small break; } } } if (!MAJORminor) // Check that minor ticks don't exceed maximum allowed density { int Nnewticks=0; for (i=0; i=imin) && (id<=imax)) Nnewticks++; } if (Nnewticks <= 1) *FLAGacceptable = 1; else *FLAGacceptable = (unsigned char)((Nnewticks>0) && (AxisLength*(imax-imin)/(NIntervals-1)/(Nnewticks-1) > 1)); } return; } // Take a list of accepted ticks and convert these into a final TickList to associate with axis static int AutoTickListFinalise(EPSComm *X, pplset_axis *axis, const double UnitMultiplier, unsigned char *AutoTicks, pplObj *VarVal, const int NIntervals, char *format, const int start, pplExpr **formatExp, const ArgumentInfo *args, const PotentialTick *PotTickList, const int NPotTicks, const ArgLeagueTableEntry *TickOrder, const unsigned char *TicksAccepted, int OutContext) { ppl_context *c = X->c; int i, jMAJ, jMIN, Nmajor=0, Nminor=0; double axispos, x, x1, x2; // Count number of accepted ticks for (i=0; i TickListPositions = (double *)ppl_memAlloc_incontext((Nmajor+1) * sizeof(double), OutContext); axis-> TickListStrings = (char **)ppl_memAlloc_incontext((Nmajor+1) * sizeof(char *), OutContext); } if (AutoTicks[0]) { axis->MTickListPositions = (double *)ppl_memAlloc_incontext((Nminor+1) * sizeof(double), OutContext); axis->MTickListStrings = (char **)ppl_memAlloc_incontext((Nminor+1) * sizeof(char *), OutContext); } if ( ((AutoTicks[1]) && ((axis-> TickListPositions==NULL) || (axis-> TickListStrings==NULL))) || ((AutoTicks[0]) && ((axis->MTickListPositions==NULL) || (axis->MTickListStrings==NULL))) ) goto FAIL; // NULL terminate lists if (AutoTicks[1]) axis-> TickListStrings[Nmajor] = NULL; if (AutoTicks[0]) axis->MTickListStrings[Nminor] = NULL; // Make ticks for (i=jMAJ=jMIN=0; i0) { const PotentialTick *tick; const ArgumentInfo *arg; int count_steps=0; double axispos_min, axispos_max, axispos_mid; unsigned char DiscreteMoveMin, SlopePositive; // If we're not doing automatic major/minor ticks, don't finalise these ticks if ((TicksAccepted[i]==1) && (!AutoTicks[1])) continue; if ((TicksAccepted[i]==2) && (!AutoTicks[0])) continue; // Find precise location of tick tick = &PotTickList[ TickOrder[i].id ]; arg = &args[ tick->ArgNo ]; axispos_min = ((double)tick->IntervalNum - 1.0)/(NIntervals-1); axispos_max = ((double)tick->IntervalNum )/(NIntervals-1); SlopePositive = (arg->NumericValues[tick->IntervalNum] >= arg->NumericValues[tick->IntervalNum-1]); while (count_steps<200) { const int stkLevelOld = c->stackPtr; int lOp; double x = GSL_NAN; pplObj *o = NULL; axispos_mid = (axispos_min+axispos_max)/2; VarVal->real = eps_plot_axis_InvGetPosition(axispos_mid, axis) * UnitMultiplier; o = ppl_expEval(c, formatExp[tick->ArgNo], &lOp, 1, X->iterDepth+1); if (arg->StringArg) // Evaluate argument at midpoint of the interval we know it to be in { char *DummyStr; if ((o==NULL) || c->errStat.status || (o->objType!=PPLOBJ_STR)) { ppl_tbClear(c); DummyStr=""; } else { DummyStr = (char *)o->auxil; } DiscreteMoveMin = (strcmp(DummyStr, arg->StringValues[tick->IntervalNum-1])==0); } else { if ((o==NULL) || c->errStat.status || ((o->objType!=PPLOBJ_NUM) && (o->objType!=PPLOBJ_DATE) && (o->objType!=PPLOBJ_BOOL))) { ppl_tbClear(c); x=GSL_NAN; } else { x=o->real; } DiscreteMoveMin = (x == arg->NumericValues[tick->IntervalNum-1]); } STACK_CLEAN; // Decide whether to pick left half of interval or right half if (!arg->ContinuousArg) { if (DiscreteMoveMin) axispos_min = axispos_mid; else axispos_max = axispos_mid; } else { if (SlopePositive ^ (x >= tick->TargetValue)) axispos_min = axispos_mid; else axispos_max = axispos_mid; } if (axispos_max == axispos_min) break; count_steps++; } axispos = (axispos_min+axispos_max)/2; x = eps_plot_axis_InvGetPosition(axispos , axis); x1 = eps_plot_axis_InvGetPosition(axispos-1e-14, axis); x2 = eps_plot_axis_InvGetPosition(axispos+1e-14, axis); if ( ((x1<=0.0)&&(x2>=0.0)) || ((x1>=0.0)&&(x2<=0.0)) ) x=0.0; // When tick is very close to a zero, enforce that it is at zero // File this tick if (TicksAccepted[i]==1) // Major tick, with label { axis->TickListPositions[jMAJ] = axispos; if (axis->format == NULL) TickLabelAutoGen (X, &axis->TickListStrings[jMAJ], x * UnitMultiplier, axis->tics.logBase, OutContext); else TickLabelFromFormat(X, &axis->TickListStrings[jMAJ], axis->format, x, &axis->DataUnit, axis->xyz, OutContext); if (axis->TickListStrings[jMAJ]==NULL) goto FAIL; jMAJ++; } else if (TicksAccepted[i]==2) // Minor tick, without label { axis->MTickListPositions[jMIN] = axispos; axis->MTickListStrings [jMIN] = ""; jMIN++; } } return 0; FAIL: axis-> TickListPositions = NULL; axis-> TickListStrings = NULL; axis->MTickListPositions = NULL; axis->MTickListStrings = NULL; return 1; } // Main entry point for automatic ticking of axes void eps_plot_ticking_auto(EPSComm *x, pplset_axis *axis, double UnitMultiplier, unsigned char *AutoTicks, pplset_axis *linkedto) { ppl_context *c = x->c; int i, j, k, start, NArgs, OutContext, ContextRough=-1, CommaPositions[MAX_ARGS+2], NFactorsLogBase, LogBase; int FactorsLogBase[MAX_FACTORS]; int N_STEPS, tripleQuote=0, rawString=0; char *format, VarName[2]="\0\0", FormatTemp[32], quoteType, *DummyStr; pplObj CentralValue, *VarVal=NULL, DummyTemp; pplExpr **formatExp=NULL; ArgumentInfo *args; ArgLeagueTableEntry *ArgLeagueTable, *TickOrder; PotentialTick *PotTickList; int NPotTicks, NPotTicksMax; unsigned char *TicksAccepted, *TicksAcceptedNew, *TicksAcceptedNewTF, *TicksAcceptedNew2B, *TicksAcceptedRough, *TicksAcceptedRough2; if (DEBUG) ppl_log(&x->c->errcontext,"Using eps_plot_ticking_auto()"); N_STEPS = (2 + axis->PhysicalLengthMajor) * STEP_DUPLICITY; // Number of intervals into which we divide axis // Make temporary rough workspace OutContext = ppl_memAlloc_GetMemContext(); ContextRough = ppl_memAlloc_DescendIntoNewContext(); DummyStr = (char *)ppl_memAlloc(LSTR_LENGTH); if (DummyStr==NULL) goto FAIL; // Work through format string identifying substitution expressions VarName[0] = "xyzc"[axis->xyz]; if (axis->format == NULL) { sprintf(FormatTemp, "\"%%s\"%%(%s)", VarName); format=FormatTemp; } else { format=((pplExpr *)axis->format)->ascii; } if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "format string is <<%s>>.", format); ppl_log(&x->c->errcontext,NULL); } if ((format==FormatTemp) && (axis->AxisLinearInterpolation==NULL) && (axis->LogFinal==SW_BOOL_TRUE) && (log(axis->MaxFinal / axis->MinFinal) / log(axis->tics.logBase) > axis->PhysicalLengthMajor)) { sprintf(FormatTemp, "\"%%s\"%%(logn(%s,%d))", VarName, axis->tics.logBase); } for (i=0; ((format[i]!='\0')&&(format[i]!='\'')&&(format[i]!='\"')); i++); quoteType = format[i]; if (quoteType=='\0') goto FAIL; if ((i>0)&&(format[i-1]=='r')) { rawString=1; } if ((format[i+1]==quoteType)&&(format[i+2]==quoteType)) { tripleQuote=1; i+=3; } else { i++; } if (!rawString) { if (!tripleQuote) for (; ((format[i]!='\0')&&((format[i]!=quoteType)||(format[i-1]=='\\'))); i++); else for (; ((format[i]!='\0')&&((format[i]!=quoteType)||(format[i+1]!=quoteType)||(format[i+2]!=quoteType)||(format[i-1]=='\\'))); i++); } else { if (!tripleQuote) for (; ((format[i]!='\0')&&((format[i]!=quoteType))); i++); else for (; ((format[i]!='\0')&&((format[i]!=quoteType)||(format[i+1]!=quoteType)||(format[i+2]!=quoteType))); i++); } if (format[i]!=quoteType) goto FAIL; i+=tripleQuote?3:1; for (;((format[i]<=' ')&&(format[i]!='\0'));i++); if (format[i]!='%') goto FAIL; i++; for (;((format[i]<=' ')&&(format[i]!='\0'));i++); if (format[i]!='(') goto FAIL; ppl_strBracketMatch(format+i, '(', ')', CommaPositions, &NArgs, &j, MAX_ARGS); if (j<0) goto FAIL; if (NArgs<1) goto FAIL; start=i; // Malloc structure to hold argument info args = (ArgumentInfo *)ppl_memAlloc(NArgs * sizeof(ArgumentInfo)); if (args==NULL) goto FAIL; ArgLeagueTable = (ArgLeagueTableEntry *)ppl_memAlloc(NArgs * sizeof(ArgLeagueTableEntry)); if (ArgLeagueTable==NULL) goto FAIL; // Compile argument expressions formatExp = (pplExpr **)ppl_memAlloc(NArgs * sizeof(pplExpr *)); if (formatExp==NULL) goto FAIL; for (i=0; ierrcontext.tempErrStr); if (es || c->errStat.status) { ppl_tbClear(c); goto FAIL; } } // Look up variable x/y/z in user space and get pointer to its value ppl_contextGetVarPointer(x->c, VarName, &VarVal, &DummyTemp); // Identify string versus numeric arguments CentralValue = axis->DataUnit; CentralValue.refCount = VarVal->refCount; CentralValue.amMalloced = VarVal->amMalloced; CentralValue.flagComplex = 0; CentralValue.imag = 0.0; CentralValue.real = eps_plot_axis_InvGetPosition(0.5, axis); *VarVal = CentralValue; for (i=0; istackPtr; int lOp; pplObj *o = ppl_expEval(c, formatExp[i], &lOp, 1, x->iterDepth+1); if ((o==NULL) || c->errStat.status) { STACK_CLEAN; ppl_tbClear(c); goto FAIL; } if ((o->objType==PPLOBJ_NUM)||(o->objType==PPLOBJ_DATE)||(o->objType==PPLOBJ_BOOL)) { args[i].StringArg=0; STACK_CLEAN; continue; } else if (o->objType==PPLOBJ_STR) { args[i].StringArg=1; STACK_CLEAN; continue; } else { STACK_CLEAN; ppl_tbClear(c); goto FAIL; } // Not a number or a string } // Sample arguments at equally-spaced intervals along axis for (i=0; ireal = eps_plot_axis_InvGetPosition(j/(N_STEPS-1.0), axis) * UnitMultiplier; for (i=0; istackPtr; int lOp; pplObj *o = ppl_expEval(c, formatExp[i], &lOp, 1, x->iterDepth+1); if (args[i].StringArg) { char *DummyStr; if ((o==NULL) || c->errStat.status || (o->objType!=PPLOBJ_STR)) { ppl_tbClear(c); DummyStr=""; } else { DummyStr = (char *)o->auxil; } args[i].StringValues[j]=(char *)ppl_memAlloc(strlen(DummyStr)+1); if (args[i].StringValues[j]==NULL) { STACK_CLEAN; goto FAIL; } strcpy(args[i].StringValues[j], DummyStr); if ((j>0) && (strcmp(args[i].StringValues[j],args[i].StringValues[j-1])!=0)) args[i].NValueChanges++; } else { int err; double x; if ((o==NULL) || c->errStat.status || ((o->objType!=PPLOBJ_NUM) && (o->objType!=PPLOBJ_DATE) && (o->objType!=PPLOBJ_BOOL))) { ppl_tbClear(c); x=GSL_NAN; } else { x=o->real; } err = !gsl_finite(x); args[i].NumericValues[j] = x; if ((!err) && (j>0) && (x!=args[i].NumericValues[j-1])) args[i].NValueChanges++; if ((!err) && ((!args[i].MinValueSet) || (x < args[i].MinValue))) { args[i].MinValue = x; args[i].MinValueSet=1; } if ((!err) && ((!args[i].MaxValueSet) || (x > args[i].MaxValue))) { args[i].MaxValue = x; args[i].MaxValueSet=1; } } STACK_CLEAN; } } for (i=0; iN_STEPS/4); args[i].vetoed = (!args[i].ContinuousArg) && (args[i].NValueChanges>N_STEPS/STEP_DUPLICITY); // Discrete argument changes too fast to be useful } // Work out factors of log base of axis. In fact, work out factors of log base ** 2, so that ten divides by four. LogBase = (axis->LogFinal == SW_BOOL_TRUE) ? axis->tics.logBase : 10; factorise(pow(LogBase,FACTOR_MULTIPLY), FactorsLogBase, MAX_FACTORS, axis->PhysicalLengthMinor*1.2, &NFactorsLogBase); // Work out throw of each argument (i.e. the spread of values that it takes) for (i=0; i1e6) || (args[i].MinValue < INT_MIN+10) || (args[i].MaxValue > INT_MAX-10)) args[i].Throw = 0.0; else args[i].Throw = throw; args[i].MinValue = floor(args[i].MinValue); factorise(args[i].Throw*pow(LogBase,FACTOR_MULTIPLY-1), args[i].FactorsThrow, MAX_FACTORS, axis->PhysicalLengthMinor*1.2, &args[i].NFactorsThrow); } // Compile scores of how fast each continuous argument moves for (j=1; jm)?n:m) / pow(LogBase,FACTOR_MULTIPLY-1) * args[i].FactorsThrow[k]),j); } } // Ticks which mark the changes of the Nth significant digit if ( ((args[i].NumericValues[j-1]!=0)&&(args[i].NumericValues[j]==0)) || ((args[i].NumericValues[j-1]==0) && (j==1)) || ((args[i].NumericValues[j-1]< 0)&&(args[i].NumericValues[j]> 0)) || ((args[i].NumericValues[j-1]> 0)&&(args[i].NumericValues[j]< 0)) ) { ADDTICK(i,NOT_THROW,INT_MAX,-10,0.0,j); // Zero should be marked in this interval n=0; ZeroInInterval = 1; } else if ((args[i].NumericValues[j-1]!=0)||(args[i].NumericValues[j]!=0)) { // Should a tick go on the left extreme of the axis? if (j==1) { for (n=0; nargs[i].OoM_max)) args[i].OoM_max = OoM-n; args[i].OoM_RangeSet = 1; ADDTICK(i,NOT_THROW,OoM-n,priority,(floor(xn/divisor+0.5)*divisor),j); break; } } } // Should tick go within body of interval j-1 -> j? for (n=0; nfabs(yn)?xn:yn; int priority = 0; if (n==0) { priority = -1; // Marking 0.1 is more important than marking 1.1 if (floor(fabs(zn/divisor)+0.5)< 2) priority = -3; // Marking 0.1 is more important than marking 0.3 else if (floor(fabs(zn/divisor)+0.5)==2) priority = -2; // Marking 0.2 and 0.5 alone is allowable on log axes else if (floor(fabs(zn/divisor)+0.5)==5) priority = -2; } if ((!args[i].OoM_RangeSet)||(OoM-nargs[i].OoM_max)) args[i].OoM_max = OoM-n; args[i].OoM_RangeSet = 1; ADDTICK(i,NOT_THROW,OoM-n,priority,(floor(ppl_max(xn,yn)/divisor)*divisor),j); break; } } } // Ticks which mark the passing of fractions of the Nth significant digit if (n=n-((ZeroInInterval||(j==1))?Nsteps:3); m--) { double divisor = pow(LogBase , OoM-m); int o; if (gsl_finite(divisor)) for (o=0; oynf)?xnf:ynf)*divisor/pow(LogBase,FACTOR_MULTIPLY)*FactorsLogBase[o],j); } else if ((j==1) && (fabs(floor(xnfd+0.5)-xnfd)<1e-12)) { ADDTICK(i,NOT_THROW,OoM-m,2*(o+1)+priority,floor(xnfd+0.5)*divisor/pow(LogBase,FACTOR_MULTIPLY)*FactorsLogBase[o],j); } } } } } } // Finished compiling list of potential ticks if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Finished compiling list of %d potential ticks. Maximum list size was %d ticks.", NPotTicks, NPotTicksMax); ppl_log(&x->c->errcontext,NULL); } if (DEBUG && (NPotTicks > NPotTicksMax)) { ppl_log(&x->c->errcontext,"Warning: Overflow of potential tick buffer."); } if (NPotTicks > NPotTicksMax) NPotTicks = NPotTicksMax; // Overflow happened // Sort list of potential ticks if (DEBUG) qsort((void *)PotTickList, NPotTicks, sizeof(PotentialTick), compare_PotentialTicks); // Create look-up table of ticks in order of position along axis TickOrder = (ArgLeagueTableEntry *)ppl_memAlloc(NPotTicks * sizeof(ArgLeagueTableEntry)); if (TickOrder==NULL) goto FAIL; for (i=0; ic->errcontext.tempErrStr,"Potential ticks for %s axis (NArgs = %d)",VarName,NArgs); ppl_log(&x->c->errcontext,NULL); for (i=0; ic->errcontext.tempErrStr, "Argument %d: id %d score %d StringArg %d ContinuousArg %d Vetoed %d NValueChanges %d",i,(int)args[i].id,(int)args[i].score,(int)args[i].StringArg,(int)args[i].ContinuousArg,(int)args[i].vetoed,args[i].NValueChanges); ppl_log(&x->c->errcontext,NULL); } sprintf(x->c->errcontext.tempErrStr, "Number of potential ticks: %d", NPotTicks); ppl_log(&x->c->errcontext,NULL); for (i=0; ((ic->errcontext.tempErrStr, "Tick %7d: Arg %3d DivOfThrow %4d OoM %10d DivOfOoM %3d IntervalNum %3d TargetVal %12.3e",PotTickList[i].OrderPosition,PotTickList[i].ArgNo,PotTickList[i].DivOfThrow,PotTickList[i].OoM,PotTickList[i].DivOfOoM,PotTickList[i].IntervalNum,PotTickList[i].TargetValue); ppl_log(&x->c->errcontext,NULL); } } // Make arrays for noting which ticks have been accepted TicksAccepted = (unsigned char *)ppl_memAlloc(NPotTicks); TicksAcceptedNew = (unsigned char *)ppl_memAlloc(NPotTicks); TicksAcceptedNewTF = (unsigned char *)ppl_memAlloc(NPotTicks); TicksAcceptedNew2B = (unsigned char *)ppl_memAlloc(NPotTicks); TicksAcceptedRough = (unsigned char *)ppl_memAlloc(NPotTicks); TicksAcceptedRough2 = (unsigned char *)ppl_memAlloc(NPotTicks); if ((TicksAccepted==NULL)||(TicksAcceptedNew==NULL)||(TicksAcceptedNewTF==NULL)||(TicksAcceptedNew2B==NULL)||(TicksAcceptedRough==NULL)||(TicksAcceptedRough2==NULL)) goto FAIL; for (i=0; iPhysicalLengthMajor, &acceptable, &NTicksMajor, &NTicksMinor); if (acceptable) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Accepted major ticks to mark changes of argument %d (now %d ticks).", i, NTicksMajor); ppl_log(&x->c->errcontext,NULL); } memcpy(TicksAccepted, TicksAcceptedNew, NPotTicks); // Update TicksAccepted continue; } // Try marking discrete changes to arguments with minor ticks AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, 0, 0, 0, TicksAccepted, TicksAcceptedNew, 0, axis->PhysicalLengthMinor, &acceptable, &NTicksMajor, &NTicksMinor); if (acceptable) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Accepted minor ticks to mark changes of argument %d (now %d ticks).", i, NTicksMajor); ppl_log(&x->c->errcontext,NULL); } memcpy(TicksAccepted, TicksAcceptedNew, NPotTicks); // Update TicksAccepted continue; } } else // Continuous arguments are more complicated { int ThrowFactors_Nticks=-1, ThrowFactors_Nticks_minor, ThrowFactors_FactNum=-1; int Divide_LogBase_Nticks=-1, Divide_LogBase_Nticks_minor=-1; int Nticks_new, Nticks_new_minor, Nticks_new_accepted, Nticks_new_accepted_minor; int Nticks_new_prev, Nticks_new_prev_minor, Nticks_2B, Nticks_2B_minor; int Nticks_2B_best=-1, Nticks_2B_minor_best=-1; int l, l2, l3, l4, l_final=0; int NMajorTicksIn, NMinorTicksIn; unsigned char MAJORminor; // Option 1: Divide throw for (k=0; kPhysicalLengthMajor, &acceptable, &ThrowFactors_Nticks, &ThrowFactors_Nticks_minor); if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing throw of %3d into intervals of %.1f produces %d major ticks [%s].",args[i].Throw,args[i].FactorsThrow[k]/pow(LogBase,FACTOR_MULTIPLY-1),ThrowFactors_Nticks,acceptable?"pass":"fail"); ppl_log(&x->c->errcontext,NULL); } if (acceptable) { ThrowFactors_FactNum = k; break; } else { ThrowFactors_FactNum = -1; ThrowFactors_Nticks = -1; } } // Minor ticks: Try other factors of throw for (k=0; kPhysicalLengthMinor, &acceptable, &ThrowFactors_Nticks, &ThrowFactors_Nticks_minor); if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing throw of %3d into intervals of %.1f produces %d minor ticks [%s].",args[i].Throw,args[i].FactorsThrow[k]/pow(LogBase,FACTOR_MULTIPLY-1),ThrowFactors_Nticks_minor,acceptable?"pass":"fail"); ppl_log(&x->c->errcontext,NULL); } if (acceptable) { memcpy(TicksAcceptedNewTF, TicksAcceptedRough, NPotTicks); break; } } else if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing throw of %3d into intervals of %.1f for minor ticks not allowed.",args[i].Throw,args[i].FactorsThrow[k]/pow(LogBase,FACTOR_MULTIPLY-1)); ppl_log(&x->c->errcontext,NULL); } } // Option 2: Divide log base if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Checking for ticks which divide OoMs %g to %g [i.e. %d to %d].",pow(LogBase,args[i].OoM_max),pow(LogBase,args[i].OoM_min),args[i].OoM_max,args[i].OoM_min); ppl_log(&x->c->errcontext,NULL); } if (args[i].OoM_RangeSet) { memcpy(TicksAcceptedNew, TicksAccepted, NPotTicks); Nticks_new_prev = -1; Nticks_new_prev_minor = -1; for (k=args[i].OoM_max+1; k>=args[i].OoM_min; k--) { // Option 2B: Divide 10 into factor intervals Nticks_2B = -1; Nticks_2B_minor = -1; CountTicks(TicksAcceptedNew, NPotTicks, &NMajorTicksIn, &NMinorTicksIn); for (l2=0; l2<2; l2++) for (l=0; l=0) break; l_final = l; acceptable=1; if (!l2) AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, k, 2*(l+1)-1, TicksAcceptedNew, TicksAcceptedRough, 1, axis->PhysicalLengthMajor, &acceptable, &Nticks_2B, &Nticks_2B_minor); if (acceptable) AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, k, 2*(l+1), l2?TicksAcceptedNew:TicksAcceptedRough, TicksAcceptedRough, 1, axis->PhysicalLengthMajor, &acceptable, &Nticks_2B, &Nticks_2B_minor); if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing OoM %g into intervals of %g produces %d major ticks [%s%s].",pow(LogBase,k),FactorsLogBase[l ]*pow(LogBase,k-FACTOR_MULTIPLY),Nticks_2B,acceptable?"pass":"fail",(Nticks_2B<=NMajorTicksIn)?"; no new ticks":""); ppl_log(&x->c->errcontext,NULL); } if ((!acceptable) || (Nticks_2B<=NMajorTicksIn)) { Nticks_2B=-1; Nticks_2B_minor=-1; } } if (Nticks_2B<=NMajorTicksIn) { l_final = -1; memcpy(TicksAcceptedRough, TicksAcceptedNew, NPotTicks); } Nticks_2B_minor = NMinorTicksIn; for (l4=0; l4<2; l4++) for (l3=0; l3 NMinorTicksIn) break; if ((l_final>=0) && (FactorsLogBase[l_final] % FactorsLogBase[l3] != 0)) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing OoM %g into intervals of %g for minor ticks not allowed.",pow(LogBase,k),FactorsLogBase[l3]*pow(LogBase,k-FACTOR_MULTIPLY)); ppl_log(&x->c->errcontext,NULL); } continue; // Minor ticks must mark common factors of log base and major tick interval } acceptable=1; if (!l4) AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, k, 2*(l3+1)-1, TicksAcceptedRough, TicksAcceptedRough2, 0, axis->PhysicalLengthMinor, &acceptable, &Nticks_2B, &Nticks_2B_minor); if (acceptable) AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, k, 2*(l3+1), l4?TicksAcceptedRough:TicksAcceptedRough2, TicksAcceptedRough2, 0, axis->PhysicalLengthMinor, &acceptable, &Nticks_2B, &Nticks_2B_minor); if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Dividing OoM %g into intervals of %g produces %d minor ticks [%s%s].",pow(LogBase,k),FactorsLogBase[l3]*pow(LogBase,k-FACTOR_MULTIPLY),Nticks_2B_minor,acceptable?"pass":"fail",(Nticks_2B_minor<=NMinorTicksIn)?"; no new ticks":""); ppl_log(&x->c->errcontext,NULL); } if (!acceptable) Nticks_2B_minor = NMinorTicksIn; } if (Nticks_2B_minor>NMinorTicksIn) memcpy(TicksAcceptedRough, TicksAcceptedRough2, NPotTicks); // Check whether this option 2B is better than previous option 2Bs if ( (Nticks_2B > Nticks_2B_best) || ((Nticks_2B == Nticks_2B_best) && (Nticks_2B_minor > Nticks_2B_minor_best)) ) { memcpy(TicksAcceptedNew2B, TicksAcceptedRough, NPotTicks); Nticks_2B_best = Nticks_2B; Nticks_2B_minor_best = Nticks_2B_minor; } // Option 2A: Add 1, 1-2-5, or 1-2-3-4... acceptable = 1; Nticks_new_accepted = Nticks_new_prev; Nticks_new_accepted_minor = Nticks_new_prev_minor; MAJORminor = 1; // On first pass, add zero with highest order-of-magnitude if (k==args[i].OoM_max+1) { AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, INT_MAX, -10, TicksAcceptedNew, TicksAcceptedRough, 1, axis->PhysicalLengthMajor, &acceptable, &Nticks_new, &Nticks_new_minor); // Must have zero, if present, with highest OoM if (acceptable) memcpy(TicksAcceptedNew, TicksAcceptedRough, NPotTicks); } memcpy(TicksAcceptedRough, TicksAcceptedNew, NPotTicks); // on with Option 2A.... acceptable = 1; for (l=-3; l<=0; l++) { AddTickScheme(PotTickList, NPotTicks, TickOrder, N_STEPS, i, NOT_THROW, k, l, TicksAcceptedNew, TicksAcceptedRough, MAJORminor, MAJORminor ? axis->PhysicalLengthMajor : axis->PhysicalLengthMinor, &acceptable, &Nticks_new, &Nticks_new_minor); if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "OoM %g Priority %2d produces %d %s ticks [%s].",pow(LogBase,k),l,Nticks_new,MAJORminor?"major":"minor",acceptable?"pass":"fail"); ppl_log(&x->c->errcontext,NULL); } if (acceptable) { Nticks_new_accepted=Nticks_new; Nticks_new_accepted_minor=Nticks_new_minor; memcpy(TicksAcceptedNew, TicksAcceptedRough, NPotTicks); } else { if (MAJORminor) { MAJORminor=0; l--; continue; } else { break; } } } // Print results of options 2A and 2B if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "Option 2A -- %d major ticks and %d minor ticks. Option 2B -- %d major ticks and %d minor ticks.", Nticks_new_accepted, Nticks_new_accepted_minor, Nticks_2B_best, Nticks_2B_minor_best); ppl_log(&x->c->errcontext,NULL); sprintf(x->c->errcontext.tempErrStr, "Option 2A Major: "); TickScheme_sprintf(x->c->errcontext.tempErrStr+strlen(x->c->errcontext.tempErrStr), PotTickList, NPotTicks, TickOrder, TicksAcceptedNew,1); ppl_log(&x->c->errcontext,NULL); sprintf(x->c->errcontext.tempErrStr, "Option 2A Minor: "); TickScheme_sprintf(x->c->errcontext.tempErrStr+strlen(x->c->errcontext.tempErrStr), PotTickList, NPotTicks, TickOrder, TicksAcceptedNew,1); ppl_log(&x->c->errcontext,NULL); sprintf(x->c->errcontext.tempErrStr, "Option 2B Major: "); TickScheme_sprintf(x->c->errcontext.tempErrStr+strlen(x->c->errcontext.tempErrStr), PotTickList, NPotTicks, TickOrder, TicksAcceptedNew2B,1); ppl_log(&x->c->errcontext,NULL); sprintf(x->c->errcontext.tempErrStr, "Option 2B Minor: "); TickScheme_sprintf(x->c->errcontext.tempErrStr+strlen(x->c->errcontext.tempErrStr), PotTickList, NPotTicks, TickOrder, TicksAcceptedNew2B,2); ppl_log(&x->c->errcontext,NULL); } // If not making progress, abort if ((kc->errcontext,"Making no further progress."); break; } Nticks_new_prev = Nticks_new_accepted; Nticks_new_prev_minor = Nticks_new_accepted_minor; } Divide_LogBase_Nticks = Nticks_new_prev; Divide_LogBase_Nticks_minor = Nticks_new_prev_minor; } // Choose which option produced best result if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"Dividing by factors of throw produced %d major ticks (%d minor ticks).", ThrowFactors_Nticks, ThrowFactors_Nticks_minor); ppl_log(&x->c->errcontext,NULL); } if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"Dividing by factors of log base produced %d major ticks (%d minor ticks).", Divide_LogBase_Nticks, Divide_LogBase_Nticks_minor); ppl_log(&x->c->errcontext,NULL); } if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"Option 2B produced %d major ticks (%d minor ticks).", Nticks_2B_best, Nticks_2B_minor_best); ppl_log(&x->c->errcontext,NULL); } // Compare option 2A and option 2B if ((Nticks_2B_best > Divide_LogBase_Nticks) || ((Nticks_2B_best == Divide_LogBase_Nticks) && (Nticks_2B_minor_best > Divide_LogBase_Nticks_minor))) { if (DEBUG) ppl_log(&x->c->errcontext,"Option 2B accepted over 2A."); memcpy(TicksAcceptedNew, TicksAcceptedNew2B, NPotTicks); Divide_LogBase_Nticks = Nticks_2B_best; Divide_LogBase_Nticks_minor = Nticks_2B_minor_best; } else { if (DEBUG) ppl_log(&x->c->errcontext,"Option 2A accepted over 2B."); } // Factors of throw are best tick scheme if ((ThrowFactors_Nticks > Divide_LogBase_Nticks) || ((ThrowFactors_Nticks == Divide_LogBase_Nticks) && (ThrowFactors_Nticks_minor > Divide_LogBase_Nticks_minor))) { if (DEBUG) ppl_log(&x->c->errcontext,"Factors of throw accepted over option 2."); if (ThrowFactors_Nticks > 0) memcpy(TicksAccepted, TicksAcceptedNewTF, NPotTicks); } else { if (DEBUG) ppl_log(&x->c->errcontext,"Option 2 accepted over factors of throw."); if (Divide_LogBase_Nticks > 0) memcpy(TicksAccepted, TicksAcceptedNew, NPotTicks); } } } // Finalise list of ticks AutoTickListFinalise(x, axis, UnitMultiplier, AutoTicks, VarVal, N_STEPS, format, start, formatExp, args, PotTickList, NPotTicks, TickOrder, TicksAccepted, OutContext); goto CLEANUP; FAIL: if (DEBUG) ppl_log(&x->c->errcontext,"eps_plot_ticking_auto() has failed"); // When clever logic fails, revert to Pyxplot 0.7 ticking algorithm if (ContextRough>0) ppl_memAlloc_AscendOutOfContext(ContextRough); ContextRough = -1; if (linkedto!=NULL) eps_plot_ticking_auto3(x, axis, UnitMultiplier, AutoTicks, linkedto); else eps_plot_ticking_auto2(x, axis, UnitMultiplier, AutoTicks, linkedto); CLEANUP: // Delete compiled expressions if (formatExp!=NULL) for (i=0; ic, VarName, &DummyTemp); // Delete rough workspace if (ContextRough>0) ppl_memAlloc_AscendOutOfContext(ContextRough); return; } pyxplot-0.9.2/src/epsMaker/eps_arrow.c0000664000175000017500000001606612026340554016340 0ustar dcf21dcf21// eps_arrow.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_arrow.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_ARROW 1 #include #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" void eps_arrow_RenderEPS(EPSComm *x) { double x1, x2, y1, y2; withWords ww; // Print label at top of postscript description of arrow fprintf(x->epsbuffer, "%% Canvas item %d [arrow]\n", x->current->id); eps_core_clear(x); // Calculate positions of start and end of arrow x1 = x->current->xpos * M_TO_PS; // Start of arrow y1 = x->current->ypos * M_TO_PS; x2 = (x->current->xpos2 + x->current->xpos) * M_TO_PS; // End of arrow y2 = (x->current->ypos2 + x->current->ypos) * M_TO_PS; // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(x->c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Call primitive routine eps_primitive_arrow(x, x->current->ArrowType, x1, y1, NULL, x2, y2, NULL, &ww); // Free with words ppl_withWordsDestroy(x->c, &ww); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } // Primitive routine for drawing arrow, suitable for use elsewhere in the EPS library void eps_primitive_arrow(EPSComm *x, int ArrowType, double x1, double y1, const double *z1, double x2, double y2, const double *z2, withWords *with_data) { int lt; double lw, lw_scale, x3, y3, x4, y4, x5, y5, xstart, ystart, xend, yend, direction; unsigned char ThreeDim = (z1!=NULL)&&(z2!=NULL); char *last_colstr=NULL; // Set color of arrow eps_core_SetColor(x, with_data, !ThreeDim); if (ThreeDim) { last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr==NULL) return; strcpy(last_colstr, x->CurrentColor); } // Set linewidth and linetype if (with_data->USElinewidth) lw_scale = with_data->linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (with_data->USElinetype) lt = with_data->linetype; else lt = 1; if (!ThreeDim) { IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); } // Factor two ends of arrow into EPS file's bounding box IF_NOT_INVISIBLE { eps_core_PlotBoundingBox(x, x1, y1, lw, 1); eps_core_PlotBoundingBox(x, x2, y2, lw, 1); } // Work out direction of arrow if (hypot(x2-x1,y2-y1) < 1e-200) direction = 0.0; else direction = atan2(x2-x1,y2-y1); // Draw arrowhead on beginning of arrow if desired if (ArrowType == SW_ARROWTYPE_TWOWAY) { x3 = x1 - EPS_ARROW_HEADSIZE * lw_scale * sin((direction+M_PI) - EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on one side y3 = y1 - EPS_ARROW_HEADSIZE * lw_scale * cos((direction+M_PI) - EPS_ARROW_ANGLE / 2); x5 = x1 - EPS_ARROW_HEADSIZE * lw_scale * sin((direction+M_PI) + EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on other side y5 = y1 - EPS_ARROW_HEADSIZE * lw_scale * cos((direction+M_PI) + EPS_ARROW_ANGLE / 2); x4 = x1 - EPS_ARROW_HEADSIZE * lw_scale * sin(direction+M_PI) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); // Point where back of arrowhead crosses stalk y4 = y1 - EPS_ARROW_HEADSIZE * lw_scale * cos(direction+M_PI) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); IF_NOT_INVISIBLE { sprintf(x->c->errcontext.tempErrStr,"newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x4,y4,x3,y3,x1,y1,x5,y5); if (!ThreeDim) fprintf(x->epsbuffer, "%s", x->c->errcontext.tempErrStr); else ThreeDimBuffer_writeps(x, *z1, lt, lw, 0.0, 1, last_colstr, x->c->errcontext.tempErrStr); eps_core_PlotBoundingBox(x, x3, y3, lw, 1); eps_core_PlotBoundingBox(x, x5, y5, lw, 1); } xstart = x4; ystart = y4; } else { xstart = x1; ystart = y1; } // Draw arrowhead on end of arrow if desired if ((ArrowType == SW_ARROWTYPE_HEAD) || (ArrowType == SW_ARROWTYPE_TWOWAY)) { x3 = x2 - EPS_ARROW_HEADSIZE * lw_scale * sin(direction - EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on one side y3 = y2 - EPS_ARROW_HEADSIZE * lw_scale * cos(direction - EPS_ARROW_ANGLE / 2); x5 = x2 - EPS_ARROW_HEADSIZE * lw_scale * sin(direction + EPS_ARROW_ANGLE / 2); // Pointy back of arrowhead on other side y5 = y2 - EPS_ARROW_HEADSIZE * lw_scale * cos(direction + EPS_ARROW_ANGLE / 2); x4 = x2 - EPS_ARROW_HEADSIZE * lw_scale * sin(direction) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); // Point where back of arrowhead crosses stalk y4 = y2 - EPS_ARROW_HEADSIZE * lw_scale * cos(direction) * (1.0 - EPS_ARROW_CONSTRICT) * cos(EPS_ARROW_ANGLE / 2); IF_NOT_INVISIBLE { sprintf(x->c->errcontext.tempErrStr,"newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x4,y4,x3,y3,x2,y2,x5,y5); if (!ThreeDim) fprintf(x->epsbuffer, "%s", x->c->errcontext.tempErrStr); else ThreeDimBuffer_writeps(x, *z2, lt, lw, 0.0, 1, last_colstr, x->c->errcontext.tempErrStr); eps_core_PlotBoundingBox(x, x3, y3, lw, 1); eps_core_PlotBoundingBox(x, x5, y5, lw, 1); } xend = x4; yend = y4; } else { xend = x2; yend = y2; } // Draw stalk of arrow IF_NOT_INVISIBLE { if (!ThreeDim) { fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\nstroke\n", xstart, ystart, xend, yend); } else { int i; const int Nsteps=100; double path=0.0, element=hypot(xend-xstart,yend-ystart)/Nsteps; for (i=0;ic->errcontext.tempErrStr,"newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\nstroke\n", xstart+(xend-xstart)/Nsteps* i , ystart+(yend-ystart)/Nsteps* i , xstart+(xend-xstart)/Nsteps*(i+1), ystart+(yend-ystart)/Nsteps*(i+1) ); ThreeDimBuffer_writeps(x, *z1 + (*z2-*z1)/Nsteps*i, lt, lw, path, 1, last_colstr, x->c->errcontext.tempErrStr); path += element; } } } return; } pyxplot-0.9.2/src/epsMaker/eps_plot_colormap.h0000664000175000017500000000254412026340554020061 0ustar dcf21dcf21// eps_plot_colormap.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_colormap.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_COLORMAP_H #define _PPL_EPS_PLOT_COLORMAP_H 1 #include "settings/settings.h" void eps_plot_colormap_YieldText(EPSComm *x, dataTable *data, pplset_graph *sg, canvas_plotdesc *pd); int eps_plot_colormap(EPSComm *x, dataTable *data, unsigned char ThreeDim, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, int pdn, double origin_x, double origin_y, double width, double height, double zdepth); int eps_plot_colormap_DrawScales(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth); #endif pyxplot-0.9.2/src/epsMaker/kpse_wrap.c0000664000175000017500000001553412026340554016331 0ustar dcf21dcf21// kpse_wrap.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: kpse_wrap.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Wrapper for libkpathsea which provides an alternative implementation of the // library -- directly forking kpsewhich -- for use on machines such as Macs // where libkpathsea is tricky to install. #include #include #include #include "coreUtils/errorReport.h" #include "epsMaker/kpse_wrap.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #ifdef HAVE_KPATHSEA #include #else #include #include #include #include #include #include #include #include "children.h" #define MAX_PATHS 256 char ppl_kpse_FilePaths [3][LSTR_LENGTH]; char *ppl_kpse_PathList [3][MAX_PATHS]; unsigned char ppl_kpse_PathRecursive[3][MAX_PATHS]; #endif void ppl_kpse_wrap_init(ppl_context *c) { #ifdef HAVE_KPATHSEA kpse_set_program_name("dvips", "dvips"); #else const char *FileTypes[3] = {"tfm","pfa","pfb"}; int i, j, k, l, s, TrialNumber, fstdout; struct timespec waitperiod; // A time.h timespec specifier for a wait of zero seconds fd_set readable; sigset_t sigs; pplerr_context *ec=&c->errcontext; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); for (j=0; j<3; j++) { ppl_kpse_PathList[j][0] = NULL; for (i=0; i=0)&&(ppl_kpse_FilePaths[j][l]==PATHLINK[0])); l--) ppl_kpse_FilePaths[j][l]='\0'; s=0; ppl_kpse_FilePaths[j][i]='\0'; continue; } if (!s) { s=1; ppl_kpse_PathList[j][k++] = ppl_kpse_FilePaths[j]+i; if (k==MAX_PATHS) { k--; ppl_error(ec, ERR_GENERIC, -1, -1, "kpsewhich returned too many paths"); } } } ppl_kpse_PathList[j][k] = NULL; // If debugging, log a list of the paths that we've extracted if (DEBUG) { for (i=0; ppl_kpse_PathList[j][i]!=NULL; i++) { sprintf(ec->tempErrStr, "Using path for %s files: <%s> [%srecursive]", FileTypes[j], ppl_kpse_PathList[j][i], ppl_kpse_PathRecursive[j][i]?"":"non-"); ppl_log(ec, NULL); } } } #endif return; } #ifndef HAVE_KPATHSEA char *ppl_kpse_wrap_test_path(pplerr_context *ec, char *s, char *path, unsigned char recurse) { int pos; DIR *dp; struct dirent *dirp; struct stat statbuf; static char buffer[FNAME_LENGTH], next[FNAME_LENGTH]; static unsigned char found; if (path[0]=='.') return NULL; // Do not look for files in cwd found=0; snprintf(buffer, FNAME_LENGTH, "%s%s%s", path, PATHLINK, s); buffer[FNAME_LENGTH-1]='\0'; if (access(buffer, R_OK) == 0) { if (DEBUG) { sprintf(ec->tempErrStr, "KPSE found file <%s>", buffer); ppl_log(ec, NULL); } found=1; return buffer; } if (recurse) { snprintf(buffer, FNAME_LENGTH, "%s%s", path, PATHLINK); buffer[FNAME_LENGTH-1]='\0'; pos = strlen(buffer); if ((dp = opendir(buffer))==NULL) return NULL; while (((dirp = readdir(dp))!=NULL)&&(!found)) { if ((strcmp(dirp->d_name,".")==0) || (strcmp(dirp->d_name,"..")==0)) continue; buffer[pos]='\0'; snprintf(next, FNAME_LENGTH, "%s%s", buffer, dirp->d_name); next[FNAME_LENGTH-1]='\0'; if (lstat(next,&statbuf) < 0) continue; if (S_ISDIR(statbuf.st_mode) == 0) continue; ppl_kpse_wrap_test_path(ec, s, next, 1); } closedir(dp); } return found ? buffer : NULL; } char *ppl_kpse_wrap_find_file(pplerr_context *ec, char *s, char **paths, unsigned char *RecurseList) { int i; char *output; if (DEBUG) { sprintf(ec->tempErrStr, "Searching for file <%s>", s); ppl_log(ec, NULL); } for (i=0; paths[i]!=NULL; i++) { output = ppl_kpse_wrap_test_path(ec, s, paths[i], RecurseList[i]); if (output!=NULL) return output; } return NULL; } #endif char *ppl_kpse_wrap_find_pfa(pplerr_context *ec, char *s) { #ifdef HAVE_KPATHSEA return (char *)kpse_find_file(s, kpse_type1_format, true); #else return ppl_kpse_wrap_find_file(ec, s, ppl_kpse_PathList[1], ppl_kpse_PathRecursive[1]); #endif } char *ppl_kpse_wrap_find_pfb(pplerr_context *ec, char *s) { #ifdef HAVE_KPATHSEA return (char *)kpse_find_file(s, kpse_type1_format, true); #else return ppl_kpse_wrap_find_file(ec, s, ppl_kpse_PathList[2], ppl_kpse_PathRecursive[2]); #endif } char *ppl_kpse_wrap_find_tfm(pplerr_context *ec, char *s) { #ifdef HAVE_KPATHSEA return (char *)kpse_find_tfm(s); #else return ppl_kpse_wrap_find_file(ec, s, ppl_kpse_PathList[0], ppl_kpse_PathRecursive[0]); #endif } pyxplot-0.9.2/src/epsMaker/eps_plot_gridlines.c0000664000175000017500000001553212026340554020221 0ustar dcf21dcf21// eps_plot_gridlines.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_gridlines.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_GRIDLINES 1 #include #include #include #include #include "settings/settings.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_gridlines.h" #include "epsMaker/eps_settings.h" void eps_plot_gridlines(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth) { int i, j, k, l, m; double left, right, adepth, bdepth, cdepth, ddepth, x1, y1, x2, y2, ap_back[3]; pplset_axis *axes; unsigned char *GridLines; withWords ww; #define MAJOR_GRIDCOL \ /* Set color for major axis axes */ \ ppl_withWordsZero(x->c, &ww); \ if (x->current->settings.GridMajColor > 0) { ww.color = x->current->settings.GridMajColor; ww.USEcolor = 1; } \ else { ww.Col1234Space = x->current->settings.GridMajCol1234Space; ww.color1 = x->current->settings.GridMajColor1; ww.color2 = x->current->settings.GridMajColor2; ww.color3 = x->current->settings.GridMajColor3; ww.color4 = x->current->settings.GridMajColor4; ww.USEcolor1234 = 1; } \ eps_core_SetColor(x, &ww, 1); \ IF_NOT_INVISIBLE eps_core_SetLinewidth(x, EPS_GRID_MAJLINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1, 0.0); #define MINOR_GRIDCOL \ /* Set color for minor axis axes */ \ ppl_withWordsZero(x->c, &ww); \ if (x->current->settings.GridMinColor > 0) { ww.color = x->current->settings.GridMinColor; ww.USEcolor = 1; } \ else { ww.Col1234Space = x->current->settings.GridMinCol1234Space; ww.color1 = x->current->settings.GridMinColor1; ww.color2 = x->current->settings.GridMinColor2; ww.color3 = x->current->settings.GridMinColor3; ww.color4 = x->current->settings.GridMinColor4; ww.USEcolor1234 = 1; } \ eps_core_SetColor(x, &ww, 1); \ IF_NOT_INVISIBLE eps_core_SetLinewidth(x, EPS_GRID_MINLINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1, 0.0); if (x->current->settings.grid != SW_ONOFF_ON) return; // Grid lines are off // Work out which faces of 3D cube are at back if (x->current->ThreeDim) { eps_plot_ThreeDimProject(0.5,0.5,0.5,&x->current->settings,origin_x,origin_y,width,height,zdepth,&x1,&y1,&adepth); eps_plot_ThreeDimProject(1.0,0.5,0.5,&x->current->settings,origin_x,origin_y,width,height,zdepth,&x1,&y1,&bdepth); eps_plot_ThreeDimProject(0.5,1.0,0.5,&x->current->settings,origin_x,origin_y,width,height,zdepth,&x1,&y1,&cdepth); eps_plot_ThreeDimProject(0.5,0.5,1.0,&x->current->settings,origin_x,origin_y,width,height,zdepth,&x1,&y1,&ddepth); ap_back[0] = (adepth < bdepth); ap_back[1] = (adepth < cdepth); ap_back[2] = (adepth < ddepth); } for (j=0; j<3; j++) // Loop over x,y,z axes { if ((j==2) && (!x->current->ThreeDim)) continue; if (j==2) { axes = x->current->ZAxes; GridLines = x->current->settings.GridAxisZ; left = right = GSL_NAN; } else if (j==1) { axes = x->current->YAxes; GridLines = x->current->settings.GridAxisY; left = origin_y; right = origin_y+height; } else { axes = x->current->XAxes; GridLines = x->current->settings.GridAxisX; left = origin_x; right = origin_x+width; } for (i=0; icurrent->ThreeDim) { for (m=0;m<2;m++) { double ap[3]; int n,o; ap[j] = TLP[l]; n = (j!=0)?0:1; o = (j!=2)?2:1; if (m) { int t=n; n=o; o=t; } ap[n] = ap_back[n]; ap[o] = 0.0; eps_plot_ThreeDimProject(ap[0],ap[1],ap[2],&x->current->settings,origin_x,origin_y,width,height,zdepth,&x1,&y1,&adepth); ap[o] = 1.0; eps_plot_ThreeDimProject(ap[0],ap[1],ap[2],&x->current->settings,origin_x,origin_y,width,height,zdepth,&x2,&y2,&adepth); fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", x1, y1, x2, y2); eps_core_BoundingBox(x, x1, y1, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, x2, y2, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); } } // 2D Gnomonic axes else if (x->current->settings.projection == SW_PROJ_GNOM) { } // 2D flat axes else { double lrpos = left + (right-left) * TLP[l]; // left--right position of tick if (j==1) { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", origin_x, lrpos, origin_x+width, lrpos); eps_core_BoundingBox(x, origin_x , lrpos, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, origin_x+width , lrpos, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); } else { fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", lrpos, origin_y, lrpos, origin_y+height); eps_core_BoundingBox(x, lrpos, origin_y , EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); eps_core_BoundingBox(x, lrpos, origin_y+height , EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH); } } } } } } } return; } pyxplot-0.9.2/src/epsMaker/eps_plot_linedraw.c0000664000175000017500000001734112026340554020046 0ustar dcf21dcf21// eps_plot_linedraw.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_linedraw.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_LINEDRAW_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_linedraw.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" void LineDraw_FindCrossingPoints(EPSComm *x, double x1, double y1, double z1, double xap1, double yap1, double zap1, double x2, double y2, double z2, double xap2, double yap2, double zap2, int *Inside1, int *Inside2, double *cx1, double *cy1, double *cz1, double *cx2, double *cy2, double *cz2, unsigned char *face1, double *AxisPos1, unsigned char *face2, double *AxisPos2, int *NCrossings) { double fr, cx, cy, cz; *Inside1 = ((xap1>=0.0)&&(xap1<=1.0)&&(yap1>=0.0)&&(yap1<=1.0)&&(zap1>=0.0)&&(zap1<=1.0)); *Inside2 = ((xap2>=0.0)&&(xap2<=1.0)&&(yap2>=0.0)&&(yap2<=1.0)&&(zap2>=0.0)&&(zap2<=1.0)); *cx1 = x1; *cy1 = y1; *cz1 = z1; // If either point is inside canvas, set clip-region crossings to be the points themselves *cx2 = x2; *cy2 = y2; *cz2 = z2; *NCrossings = 0; *face1 = *face2 = 0; *AxisPos1 = *AxisPos2 = -1; if ((*Inside1) && (*Inside2)) return; // If both points are inside canvas, don't need to find clip-region crossings #define DOCLIP(XAP1,XAP2,YAP1,YAP2,ZAP1,ZAP2,POS,SGN,FACE) \ if (XAP2 != XAP1) \ { \ fr = (POS-XAP1)/(XAP2-XAP1); \ if ((fr>=0)&&(fr<=1)) \ { \ double yleft, zleft; \ yleft = YAP1 + (YAP2-YAP1) * fr; \ zleft = ZAP1 + (ZAP2-ZAP1) * fr; \ if ((yleft>=0.0)&&(yleft<=1.0)&&(zleft>=0.0)&&(zleft<=1.0)) \ { \ cx = x1 + (x2-x1)*fr; \ cy = y1 + (y2-y1)*fr; \ cz = z1 + (z2-z1)*fr; \ if ((XAP1*SGN)<(XAP2*SGN)) { *cx1 = cx; *cy1 = cy; *cz1 = cz; *face1 = FACE; *AxisPos1 = yleft; } \ else { *cx2 = cx; *cy2 = cy; *cz2 = cz; *face2 = FACE; *AxisPos2 = yleft; } \ (*NCrossings)++; \ } \ } \ } DOCLIP(zap1,zap2,xap1,xap2,yap1,yap2, 0.0, 1.0, 0 ); // front DOCLIP(zap1,zap2,xap1,xap2,yap1,yap2, 1.0,-1.0, 0 ); // back DOCLIP(xap1,xap2,yap1,yap2,zap1,zap2, 0.0, 1.0, FACE_LEFT ); // left DOCLIP(xap1,xap2,yap1,yap2,zap1,zap2, 1.0,-1.0, FACE_RIGHT ); // right DOCLIP(yap1,yap2,xap1,xap2,zap1,zap2, 0.0, 1.0, FACE_BOTTOM); // bottom DOCLIP(yap1,yap2,xap1,xap2,zap1,zap2, 1.0,-1.0, FACE_TOP ); // top return; } LineDrawHandle *LineDraw_Init (EPSComm *x, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, unsigned char ThreeDim, double origin_x, double origin_y, double width, double height, double zdepth) { LineDrawHandle *output; output = (LineDrawHandle *)ppl_memAlloc(sizeof(LineDrawHandle)); if (output==NULL) return NULL; output->x = x; output->xa = xa; output->ya = ya; output->za = za; output->xrn = xrn; output->yrn = yrn; output->zrn = zrn; output->sg = sg; output->ThreeDim = ThreeDim; output->origin_x = origin_x; output->origin_y = origin_y; output->width = width; output->height = height; output->zdepth = zdepth; output->x0set = 0; output->x1set = 0; return output; } void LineDraw_Point(EPSComm *X, LineDrawHandle *ld, double x, double y, double z, double x_offset, double y_offset, double z_offset, double x_perpoffset, double y_perpoffset, double z_perpoffset, int linetype, double linewidth, char *colstr) { unsigned char f1, f2; double ap1, ap2; int Inside1, Inside2, NCrossings; double xpos, ypos, depth, xap, yap, zap; double theta_x, theta_y, theta_z; double cx1, cy1, cz1, cx2, cy2, cz2; eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, &theta_x, &theta_y, &theta_z, ld->ThreeDim, x, y, z, ld->xa, ld->ya, ld->za, ld->xrn, ld->yrn, ld->zrn, ld->sg, ld->origin_x, ld->origin_y, ld->width, ld->height, ld->zdepth, 1); if ((!gsl_finite(xpos))||(!gsl_finite(ypos))||(!gsl_finite(depth))) { LineDraw_PenUp(X,ld); return; } xpos += x_offset * M_TO_PS; ypos += y_offset * M_TO_PS; depth += z_offset * M_TO_PS; xap += x_offset / ld->width; yap += y_offset / ld->height; zap += z_offset / ld->zdepth; if (!ld->x1set) { ld->x1set = 1; ld->x1=xpos; ld->y1=ypos; ld->z1=depth; ld->xap1=xap; ld->yap1=yap; ld->zap1=zap; ld->xpo1=x_perpoffset; ld->ypo1=y_perpoffset; ld->zpo1=z_perpoffset; return; } LineDraw_FindCrossingPoints(X, ld->x1, ld->y1, ld->z1, ld->xap1, ld->yap1, ld->zap1, xpos, ypos, depth, xap, yap, zap, &Inside1, &Inside2, &cx1, &cy1, &cz1, &cx2, &cy2, &cz2, &f1, &ap1, &f2, &ap2, &NCrossings); // Add in perpendicular offsets cx1 = cx1 + ( ld->xpo1 * cos(theta_x) + ld->ypo1 * cos(theta_y) + ld->zpo1 * cos(theta_z) )*M_TO_PS; cy1 = cy1 + ( ld->xpo1 * sin(theta_x) + ld->ypo1 * sin(theta_y) + ld->zpo1 * sin(theta_z) )*M_TO_PS; cx2 = cx2 + ( x_perpoffset * cos(theta_x) + y_perpoffset * cos(theta_y) + z_perpoffset * cos(theta_z) )*M_TO_PS; cy2 = cy2 + ( x_perpoffset * sin(theta_x) + y_perpoffset * sin(theta_y) + z_perpoffset * sin(theta_z) )*M_TO_PS; // Test whether end-points of line are within clip region if ((!Inside1) && (!Inside2)) // Neither point on line segment is inside clip-region { if (NCrossings>=2) // Check that we haven't crossed clip region during the course of line segment ThreeDimBuffer_linesegment(ld->x, depth, linetype, linewidth, colstr, cx1, cy1, cx1, cy1, cx2, cy2, 1, 0, 0.0); ld->x0set=0; } else if ((!Inside1) && ( Inside2)) // We have just entered clip region; previous point was outside { ThreeDimBuffer_linesegment(ld->x, z, linetype, linewidth, colstr, cx1, cy1, cx1, cy1, cx2, cy2, 1, 0, 0.0); if ((!ld->x0set)||(cx1!=cx2)||(cy1!=cy2)) { ld->x0=cx1; ld->y0=cy1; } ld->x0set=1; } else if (( Inside1) && (!Inside2)) // We have just left clip region; previous point was inside { if (ld->x0set) ThreeDimBuffer_linesegment(ld->x, depth, linetype, linewidth, colstr, ld->x0, ld->y0, cx1, cy1, cx2, cy2, 0, 0, 0.0); else ThreeDimBuffer_linesegment(ld->x, depth, linetype, linewidth, colstr, cx1 , cy1 , cx1, cy1, cx2, cy2, 1, 0, 0.0); ld->x0set=0; } else // if (( Inside1) && ( Inside2)) // We are within the clip region { if (ld->x0set) ThreeDimBuffer_linesegment(ld->x, depth, linetype, linewidth, colstr, ld->x0, ld->y0, cx1, cy1, cx2, cy2, 0, 0, 0.0); else ThreeDimBuffer_linesegment(ld->x, depth, linetype, linewidth, colstr, cx1 , cy1 , cx1, cy1, cx2, cy2, 1, 0, 0.0); if ((!ld->x0set)||(cx1!=cx2)||(cy1!=cy2)) { ld->x0=cx1; ld->y0=cy1; } ld->x0set=1; } ld->x1=xpos; ld->y1=ypos; ld->z1=depth; ld->xap1=xap; ld->yap1=yap; ld->zap1=zap; ld->xpo1=x_perpoffset; ld->ypo1=y_perpoffset; ld->zpo1=z_perpoffset; return; } void LineDraw_PenUp(EPSComm *x, LineDrawHandle *ld) { ThreeDimBuffer_linepenup(ld->x); ld->x0set=0; ld->x1set=0; return; } pyxplot-0.9.2/src/epsMaker/eps_plot_linedraw.h0000664000175000017500000000440512026340554020050 0ustar dcf21dcf21// eps_plot_linedraw.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_linedraw.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_LINEDRAW_H #define _PPL_EPS_PLOT_LINEDRAW_H 1 #include "epsMaker/eps_comm.h" #include "settings/settings.h" #define FACE_TOP 1 #define FACE_LEFT 2 #define FACE_BOTTOM 3 #define FACE_RIGHT 4 typedef struct LineDrawHandle { EPSComm *x; pplset_graph *sg; pplset_axis *xa, *ya, *za; int xrn, yrn, zrn; unsigned char ThreeDim; double origin_x, origin_y, width, height, zdepth; unsigned char x0set, x1set; double x0, y0; double x1 , y1 , z1 ; double xpo1, ypo1, zpo1; double xap1, yap1, zap1; } LineDrawHandle; void LineDraw_FindCrossingPoints(EPSComm *x, double x1, double y1, double z1, double xap1, double yap1, double zap1, double x2, double y2, double z2, double xap2, double yap2, double zap2, int *Inside1, int *Inside2, double *cx1, double *cy1, double *cz1, double *cx2, double *cy2, double *cz2, unsigned char *face1, double *AxisPos1, unsigned char *face2, double *AxisPos2, int *NCrossings); LineDrawHandle *LineDraw_Init (EPSComm *x, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, unsigned char ThreeDim, double origin_x, double origin_y, double width, double height, double zdepth); void LineDraw_Point(EPSComm *X, LineDrawHandle *ld, double x, double y, double z, double x_offset, double y_offset, double z_offset, double x_perpoffset, double y_perpoffset, double z_perpoffset, int linetype, double linewidth, char *colstr); void LineDraw_PenUp(EPSComm *x, LineDrawHandle *ld); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_legend.c0000664000175000017500000005160312026340554017476 0ustar dcf21dcf21// eps_plot_legend.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_legend.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains routines for adding legends to plots #define _PPL_EPS_PLOT_LEGEND_C 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "settings/settings.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/unitsDisp.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_legend.h" #include "epsMaker/eps_plot_styles.h" #include "canvasItems.h" #include "texify.h" // Private routines for sorting 3D positions by depth and azimuth when working out where to put a legend on a 3D plot static int SortByDepth(const void *x, const void *y) { const double *xd = (const double *)x; const double *yd = (const double *)y; if (xd[2]>yd[2]) return 1; if (xd[2]2*M_PI) ax-=2*M_PI; if (ax>M_PI) ax = 2*M_PI-ax; while (ay>2*M_PI) ay-=2*M_PI; if (ay>M_PI) ay = 2*M_PI-ay; if (ax>ay) return 1; if (axcurrent->settings.key != SW_ONOFF_ON) return; pd = x->current->plotitems; while (pd != NULL) // loop over all datasets { if (pd->NoTitleSet) { pd=pd->next; continue; } // notitle set else if (pd->TitleSet ) { pd->TitleFinal=pd->title; YIELD_TEXTITEM(pd->title); } // title for dataset manually set else // generate automatic title for dataset { pd->TitleFinal = cptr = (char *)ppl_memAlloc(LSTR_LENGTH); buffer = (char *)ppl_memAlloc(LSTR_LENGTH); if (buffer==NULL) cptr=NULL; if (cptr!=NULL) { k=0; if (pd->parametric) { sprintf(cptr+k, "parametric"); k+=strlen(cptr+k); } if (pd->TRangeSet) { sprintf(cptr+k, " [%s:%s]", ppl_unitsNumericDisplay(x->c,&pd->Tmin,0,SW_DISPLAY_L,0), ppl_unitsNumericDisplay(x->c,&pd->Tmax,1,SW_DISPLAY_L,0)); k+=strlen(cptr+k); } if ( (pd->function) || (pd->vectors!=NULL) ) { for (j=0; jNFunctions; j++) // Print out the list of functions which we are plotting { cptr[k++]=(j!=0)?':':' '; inlen=strlen(pd->functions[j]->ascii); ppl_texify_generic(x->c, pd->functions[j]->ascii, -1, &inlen, cptr+k, LSTR_LENGTH-k, NULL, NULL); k+=strlen(cptr+k); } } else { cptr[k++]=' '; ppl_strEscapify((pd->filenameFinal==NULL)?pd->filename:pd->filenameFinal, buffer); inlen=strlen(buffer); ppl_texify_generic(x->c, buffer, -1, &inlen, cptr+k, LSTR_LENGTH-k, NULL, NULL); k+=strlen(cptr+k); // Filename of datafile we are plotting } if (pd->ContinuitySet) // Print continuous / discontinuous flag { if (pd->continuity == DATAFILE_DISCONTINUOUS) { sprintf(cptr+k, " discontinuous"); k+=strlen(cptr+k); } else { sprintf(cptr+k, " continuous"); k+=strlen(cptr+k); } } if (pd->axis1set || pd->axis2set || pd->axis3set) // Print axes to use { strcpy(cptr+k, " axes "); k+=strlen(cptr+k); if (pd->axis1set) { sprintf(cptr+k, "$%c%d$", "xyzc"[pd->axis1xyz], pd->axis1); k+=strlen(cptr+k); } if (pd->axis2set) { sprintf(cptr+k, "$%c%d$", "xyzc"[pd->axis2xyz], pd->axis2); k+=strlen(cptr+k); } if (pd->axis3set) { sprintf(cptr+k, "$%c%d$", "xyzc"[pd->axis3xyz], pd->axis3); k+=strlen(cptr+k); } } if (pd->EverySet>0) { sprintf(cptr+k, " every $%ld$", pd->EveryList[0]); k+=strlen(cptr+k); } // Print out 'every' clause of plot command if (pd->EverySet>1) { sprintf(cptr+k, ":$%ld$", pd->EveryList[1]); k+=strlen(cptr+k); } if (pd->EverySet>2) { sprintf(cptr+k, ":$%ld$", pd->EveryList[2]); k+=strlen(cptr+k); } if (pd->EverySet>3) { sprintf(cptr+k, ":$%ld$", pd->EveryList[3]); k+=strlen(cptr+k); } if (pd->EverySet>4) { sprintf(cptr+k, ":$%ld$", pd->EveryList[4]); k+=strlen(cptr+k); } if (pd->EverySet>5) { sprintf(cptr+k, ":$%ld$", pd->EveryList[5]); k+=strlen(cptr+k); } if (pd->IndexSet) { sprintf(cptr+k, " index $%d$", pd->index); k+=strlen(cptr+k); } // Print index to use if (pd->label!=NULL) { sprintf(cptr+k, " label "); k+=strlen(cptr+k); inlen=strlen(pd->label->ascii); ppl_texify_generic(x->c, pd->label->ascii, -1, &inlen, cptr+k, LSTR_LENGTH-k, NULL, NULL); k+=strlen(cptr+k); } // Print label string if (pd->SelectCriterion!=NULL) { strcpy(cptr+k, " select "); k+=strlen(cptr+k); inlen=strlen(pd->SelectCriterion->ascii); ppl_texify_generic(x->c, pd->SelectCriterion->ascii, -1, &inlen, cptr+k, LSTR_LENGTH-k, NULL, NULL); k+=strlen(cptr+k); } // Print select criterion if ((pd->NUsing>0)||(pd->UsingRowCols!=DATAFILE_COL)) { sprintf(cptr+k, " using %s", (pd->UsingRowCols==DATAFILE_COL)?"":"rows"); k+=strlen(cptr+k); // Print using list for (j=0; jNUsing; j++) { cptr[k++]=(j!=0)?':':' '; inlen=strlen(pd->UsingList[j]->ascii); ppl_texify_generic(x->c, pd->UsingList[j]->ascii, -1, &inlen, cptr+k, LSTR_LENGTH-k, NULL, NULL); k+=strlen(cptr+k); } } cptr[k]='\0'; YIELD_TEXTITEM(cptr); } } pd=pd->next; } return; } #define LOOP_OVER_DATASETS \ {\ int iDataSet=-1; /* iDataSet counts over all data sets, even ones that we skip because they have no data */\ pd = x->current->plotitems; \ while (pd != NULL) \ { \ iDataSet++; \ if ((pd->NoTitleSet) || (pd->TitleFinal==NULL) || (pd->TitleFinal[0]=='\0')) { pd=pd->next; continue; } /* no title set */ #define END_LOOP_OVER_DATASETS \ pd = pd->next; \ } \ } // Lay out all of the items in the current legend with a maximum allowed column height of TrialHeight. void GraphLegend_ArrangeToHeight(EPSComm *x, double TrialHeight, double *AttainedHeight, int *Ncolumns, double *ColumnX, double *ColumnHeight, int *ColumnNItems) { canvas_plotdesc *pd; int i, ColumnNo = 0; double ColumnYPos = 0.0, ColumnWidth = 0.0; *AttainedHeight = 0.0; for (i=0; i0) && (pd->TitleFinal_height>TrialHeight-ColumnYPos) && (ColumnNoTitleFinal_col = ColumnNo; pd->TitleFinal_xpos = ColumnX[ColumnNo]; pd->TitleFinal_ypos = -ColumnYPos; // Minus sign since postscript measures height from bottom, and legend runs down page ColumnYPos+=pd->TitleFinal_height; if (ColumnWidth < pd->TitleFinal_width) ColumnWidth=pd->TitleFinal_width; if (ColumnYPos > *AttainedHeight) *AttainedHeight=ColumnYPos; END_LOOP_OVER_DATASETS; ColumnHeight[ColumnNo]=ColumnYPos; ColumnX[ColumnNo+1] = ColumnX[ColumnNo] + ColumnWidth; *Ncolumns = ColumnNo+1; return; } void GraphLegend_Render(EPSComm *x, double width, double height, double zdepth) { double fs=x->current->settings.FontSize, CombinedHeight=0.0, MinimumHeight=0.0; double xoff=0, yoff=0; double ColumnX[MAX_LEGEND_COLUMNS], ColumnHeight[MAX_LEGEND_COLUMNS]; double BestHeight, AttainedHeight, TrialHeight; int Ncolumns, ColumnNItems[MAX_LEGEND_COLUMNS]; double height1,height2,bb_top,bb_bottom,ab_left,ab_right,ab_top,ab_bottom; unsigned char hfixed=0, vfixed=0; canvas_plotdesc *pd; int pageno, j, kp=x->current->settings.KeyPos; postscriptPage *dviPage; withWords ww; if (x->current->settings.key != SW_ONOFF_ON) return; // Loop over all legend items to calculate their individual heights and widths, as well as the combined height of all of them pageno = x->LaTeXpageno = x->current->LegendTextID; LOOP_OVER_DATASETS; // Fetch dimensions of requested page of postscript if (x->dvi == NULL) { pd->TitleFinal_width=0; pd->TitleFinal_height=0; pd=pd->next; pageno++; continue; } dviPage = (postscriptPage *)ppl_listGetItem(x->dvi->output->pages, pageno+1); if (dviPage== NULL) { pd->TitleFinal_width=0; pd->TitleFinal_height=0; pd=pd->next; pageno++; continue; } // Such doom will trigger errors later //bb_left = dviPage->boundingBox[0]; bb_bottom = dviPage->boundingBox[1]; //bb_right = dviPage->boundingBox[2]; bb_top = dviPage->boundingBox[3]; ab_left = dviPage->textSizeBox[0]; ab_bottom = dviPage->textSizeBox[1]; ab_right = dviPage->textSizeBox[2]; ab_top = dviPage->textSizeBox[3]; height1 = fabs(ab_top - ab_bottom) * AB_ENLARGE_FACTOR; height2 = fabs(bb_top - bb_bottom) * BB_ENLARGE_FACTOR; pd->TitleFinal_height = ((height2TitleFinal_width = ((ab_right - ab_left) + MARGIN_HSIZE ) * fs; CombinedHeight += pd->TitleFinal_height; if (MinimumHeight < pd->TitleFinal_height) MinimumHeight = pd->TitleFinal_height; pageno++; END_LOOP_OVER_DATASETS; // If number of columns is manually specified, repeatedly reduce height of legend until the desired number of columns is exceeded. if (x->current->settings.KeyColumns > 0) { BestHeight = TrialHeight = CombinedHeight+2; while (TrialHeight>MinimumHeight) { GraphLegend_ArrangeToHeight(x, TrialHeight, &AttainedHeight, &Ncolumns, ColumnX, ColumnHeight, ColumnNItems); if (Ncolumns > x->current->settings.KeyColumns) break; if (AttainedHeight>TrialHeight) break; BestHeight = TrialHeight; TrialHeight = AttainedHeight-1; } } // In ABOVE and BELOW alignment modes, repeatedly reduce height of legend until its width exceeds that of the plot else if ((kp == SW_KEYPOS_ABOVE) || (kp == SW_KEYPOS_BELOW)) { hfixed = 1; BestHeight = TrialHeight = CombinedHeight+2; while (TrialHeight>MinimumHeight) { GraphLegend_ArrangeToHeight(x, TrialHeight, &AttainedHeight, &Ncolumns, ColumnX, ColumnHeight, ColumnNItems); if (ColumnX[Ncolumns] > width-2*LEGEND_MARGIN) break; if (AttainedHeight>TrialHeight) break; BestHeight = TrialHeight; TrialHeight = AttainedHeight-1; } } // In all other modes, make maximum height of legend equal height of plot. else { vfixed = 1; BestHeight = height-2*LEGEND_MARGIN; } // Adjust spacing between legend items to justify them as necessary GraphLegend_ArrangeToHeight(x, BestHeight, &AttainedHeight, &Ncolumns, ColumnX, ColumnHeight, ColumnNItems); TrialHeight = vfixed ? (height-2*LEGEND_MARGIN) : AttainedHeight; // Vertical justification for (j=0; j= TrialHeight-LEGEND_VGAP_MAXIMUM*(ColumnNItems[j]-1)) { double GapPerItem = (TrialHeight-ColumnHeight[j])/(ColumnNItems[j]-1), gap=0.0; if (gsl_finite(GapPerItem)) { LOOP_OVER_DATASETS; if (pd->TitleFinal_col==j) { pd->TitleFinal_ypos-=gap; gap+=GapPerItem; } END_LOOP_OVER_DATASETS; } } AttainedHeight = TrialHeight; // Horizonal justification if (hfixed && (ColumnX[Ncolumns] < width-2*LEGEND_MARGIN) && (Ncolumns>1) && (ColumnX[Ncolumns] >= width-2*LEGEND_MARGIN-LEGEND_HGAP_MAXIMUM*(Ncolumns-1))) { double GapPerColumn = (width - 2*LEGEND_MARGIN - ColumnX[Ncolumns])/Ncolumns; if (gsl_finite(GapPerColumn)) { LOOP_OVER_DATASETS; pd->TitleFinal_xpos+=pd->TitleFinal_col*GapPerColumn; END_LOOP_OVER_DATASETS; for (j=0; jcurrent->ThreeDim) { switch (kp) { case SW_KEYPOS_TR: xoff = width - ColumnX[Ncolumns] - LEGEND_MARGIN; yoff = height - LEGEND_MARGIN; break; case SW_KEYPOS_TM: xoff = width/2 - ColumnX[Ncolumns]/2 ; yoff = height - LEGEND_MARGIN; break; case SW_KEYPOS_TL: xoff = LEGEND_MARGIN; yoff = height - LEGEND_MARGIN; break; case SW_KEYPOS_MR: xoff = width - ColumnX[Ncolumns] - LEGEND_MARGIN; yoff = height/2 + AttainedHeight/2 ; break; case SW_KEYPOS_MM: xoff = width/2 - ColumnX[Ncolumns]/2 ; yoff = height/2 + AttainedHeight/2 ; break; case SW_KEYPOS_ML: xoff = LEGEND_MARGIN; yoff = height/2 + AttainedHeight/2 ; break; case SW_KEYPOS_BR: xoff = width - ColumnX[Ncolumns] - LEGEND_MARGIN; yoff = AttainedHeight + LEGEND_MARGIN; break; case SW_KEYPOS_BM: xoff = width/2 - ColumnX[Ncolumns]/2 ; yoff = AttainedHeight + LEGEND_MARGIN; break; case SW_KEYPOS_BL: xoff = LEGEND_MARGIN; yoff = AttainedHeight + LEGEND_MARGIN; break; case SW_KEYPOS_ABOVE: xoff = width/2 - ColumnX[Ncolumns]/2 ; yoff = AttainedHeight + LEGEND_MARGIN + x->current->PlotTopMargin - x->current->settings.OriginY.real*M_TO_PS; break; case SW_KEYPOS_BELOW: xoff = width/2 - ColumnX[Ncolumns]/2 ; yoff = - LEGEND_MARGIN + x->current->PlotBottomMargin - x->current->settings.OriginY.real*M_TO_PS; break; case SW_KEYPOS_OUTSIDE: xoff = LEGEND_MARGIN; yoff = height - LEGEND_MARGIN; xoff+= x->current->PlotRightMargin - x->current->settings.OriginX.real*M_TO_PS; break; } xoff += x->current->settings.OriginX.real * M_TO_PS; yoff += x->current->settings.OriginY.real * M_TO_PS; } // Translate legend to desired place on canvas (3D case) else { SortByAzimuthTarget = -999; switch (kp) { case SW_KEYPOS_TR: SortByAzimuthTarget = 1*M_PI/4; xoff = LEGEND_MARGIN + x->current->PlotRightMargin; yoff = AttainedHeight + LEGEND_MARGIN; break; case SW_KEYPOS_TM: SortByAzimuthTarget = 0*M_PI/4; xoff = -ColumnX[Ncolumns]/2 ; yoff = AttainedHeight + LEGEND_MARGIN + x->current->PlotTopMargin; break; case SW_KEYPOS_TL: SortByAzimuthTarget = -1*M_PI/4; xoff = -ColumnX[Ncolumns] - LEGEND_MARGIN + x->current->PlotLeftMargin ; yoff = AttainedHeight + LEGEND_MARGIN; break; case SW_KEYPOS_MR: SortByAzimuthTarget = 2*M_PI/4; xoff = LEGEND_MARGIN + x->current->PlotRightMargin; yoff = AttainedHeight/2 ; break; case SW_KEYPOS_MM: xoff = -ColumnX[Ncolumns]/2 + x->current->settings.OriginX.real * M_TO_PS; yoff = AttainedHeight/2 + x->current->settings.OriginY.real * M_TO_PS; break; case SW_KEYPOS_ML: SortByAzimuthTarget = -2*M_PI/4; xoff = -ColumnX[Ncolumns] - LEGEND_MARGIN + x->current->PlotLeftMargin ; yoff = AttainedHeight/2 ; break; case SW_KEYPOS_BR: SortByAzimuthTarget = 3*M_PI/4; xoff = LEGEND_MARGIN + x->current->PlotRightMargin; yoff = - LEGEND_MARGIN; break; case SW_KEYPOS_BM: SortByAzimuthTarget = 4*M_PI/4; xoff = -ColumnX[Ncolumns]/2 ; yoff = - LEGEND_MARGIN + x->current->PlotBottomMargin; break; case SW_KEYPOS_BL: SortByAzimuthTarget = -3*M_PI/4; xoff = -ColumnX[Ncolumns] - LEGEND_MARGIN + x->current->PlotLeftMargin ; yoff = - LEGEND_MARGIN; break; case SW_KEYPOS_ABOVE: xoff = -ColumnX[Ncolumns]/2 + x->current->settings.OriginX.real * M_TO_PS; yoff = AttainedHeight + LEGEND_MARGIN + x->current->PlotTopMargin; break; case SW_KEYPOS_BELOW: xoff = -ColumnX[Ncolumns]/2 + x->current->settings.OriginX.real * M_TO_PS; yoff = - LEGEND_MARGIN + x->current->PlotBottomMargin; break; case SW_KEYPOS_OUTSIDE: xoff = LEGEND_MARGIN + x->current->PlotRightMargin; yoff = -LEGEND_MARGIN + x->current->PlotTopMargin; break; } // Find the vertex of the graph closest to the target azimuth if (SortByAzimuthTarget>-100) { int i; double xap, yap, zap, data[3*8]; double origin_x = x->current->settings.OriginX.real*M_TO_PS; double origin_y = x->current->settings.OriginY.real*M_TO_PS; for (i=0;i<8;i++) { xap=((i&1)!=0); yap=((i&2)!=0); zap=((i&4)!=0); eps_plot_ThreeDimProject(xap,yap,zap,&x->current->settings,origin_x,origin_y,width,height,zdepth,data+3*i,data+3*i+1,data+3*i+2); } SortByAzimuthXCentre = origin_x; SortByAzimuthYCentre = origin_y; qsort((void *)(data ),8,3*sizeof(double),SortByDepth); if ((data[3*0+2]==data[3*1+2])&&(hypot(data[3*0+0]-origin_x,data[3*0+1]-origin_y)>hypot(data[3*1+0]-origin_x,data[3*1+1]-origin_y))) TriSwap(data+3*0,data+3*1); if ((data[3*7+2]==data[3*6+2])&&(hypot(data[3*7+0]-origin_x,data[3*7+1]-origin_y)>hypot(data[3*6+0]-origin_x,data[3*6+1]-origin_y))) TriSwap(data+3*7,data+3*6); qsort((void *)(data+3),6,3*sizeof(double),SortByAzimuthProximity); if ((kp==SW_KEYPOS_TM)||(kp==SW_KEYPOS_BM)) xoff += data[3*1+0]; else yoff += data[3*1+1]; } } xoff += x->current->settings.KeyXOff.real * M_TO_PS; yoff += x->current->settings.KeyYOff.real * M_TO_PS; LOOP_OVER_DATASETS; pd->TitleFinal_xpos += xoff; pd->TitleFinal_ypos += yoff; END_LOOP_OVER_DATASETS; // Finally loop over all datasets to display legend items LOOP_OVER_DATASETS int xyzaxis[3]; pplset_axis *a1, *a2, *a3, *axissets[3]; dataTable *data = x->current->plotdata[iDataSet]; if ((data==NULL) || (data->Nrows<1)) { x->LaTeXpageno++; return; } // No data present axissets[0] = x->current->XAxes; axissets[1] = x->current->YAxes; axissets[2] = x->current->ZAxes; a1 = &axissets[pd->axis1xyz][pd->axis1]; a2 = &axissets[pd->axis2xyz][pd->axis2]; a3 = &axissets[pd->axis3xyz][pd->axis3]; xyzaxis[pd->axis1xyz] = 0; xyzaxis[pd->axis2xyz] = 1; xyzaxis[pd->axis3xyz] = 2; eps_plot_LegendIcon(x, iDataSet, pd, pd->TitleFinal_xpos + MARGIN_HSIZE_LEFT/2, pd->TitleFinal_ypos - pd->TitleFinal_height/2, MARGIN_HSIZE_LEFT, a1, a2, a3, xyzaxis[0], xyzaxis[1], xyzaxis[2]); pageno = x->LaTeXpageno++; ppl_withWordsZero(x->c,&ww); if (x->current->settings.TextColor > 0) { ww.color = x->current->settings.TextColor; ww.USEcolor = 1; } else { ww.Col1234Space = x->current->settings.TextCol1234Space; ww.color1 = x->current->settings.TextColor1; ww.color2 = x->current->settings.TextColor2; ww.color3 = x->current->settings.TextColor3; ww.color4 = x->current->settings.TextColor4; ww.USEcolor1234 = 1; } eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE canvas_EPSRenderTextItem(x, NULL, pageno, (pd->TitleFinal_xpos+MARGIN_HSIZE_LEFT)/M_TO_PS, (pd->TitleFinal_ypos - pd->TitleFinal_height/2)/ M_TO_PS, SW_HALIGN_LEFT, SW_VALIGN_CENT, x->CurrentColor, fs, 0.0, NULL, NULL); END_LOOP_OVER_DATASETS return; } pyxplot-0.9.2/src/epsMaker/bmp_bmpread.c0000664000175000017500000003105312026340554016600 0ustar dcf21dcf21// bmp_bmpread.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_bmpread.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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, -1, -1, or (at your option) any later // version. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from Windows and OS/2 bitmap files. #define _PPL_BMP_BMPREAD_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" #include "epsMaker/bmp_bmpread.h" void ppl_bmp_bmpread(pplerr_context *ec, FILE *in, bitmap_data *image) { unsigned char buff[60],encode,*p,c; unsigned width,height,depth,dw,excess; unsigned long offset,off2,size; int i,j,ncols,os2,rle; if (DEBUG) ppl_log(ec, "Beginning to decode BMP image file"); off2=3; // Read rest of first header if (fread(buff,11,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } off2 += 11; if ((buff[3])||(buff[4])||(buff[5])||(buff[6])) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } offset = buff[7] + (buff[8]<<8) + (buff[9]<<16) + (buff[10]<<24); // Read info header if (fread(buff,12,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } off2 += 12; if ((buff[0]==12)&&(buff[1]==0)) // OS/2 1.x bitmap { os2=1; if ((buff[8]!=1)||(buff[9])) { ppl_error(ec, ERR_FILE, -1, -1,"This OS/2 bitmap file appears to be corrupted"); return; } width = buff[4] + ((unsigned)buff[5]<<8); height = buff[6] + ((unsigned)buff[7]<<8); depth = buff[10]; encode = 0; size = 0; } else // Windows bitmap { os2=0; // Known valid header lengths at this point are 40, 64, 108 and 124 // So accept from 40 to 255 if ((buff[0]<40)||(buff[1])||(buff[2])||(buff[3])) { ppl_error(ec, ERR_FILE, -1, -1,"This Windows bitmap file appears to be corrupted"); return; } excess=buff[0]-40; if (fread(buff+12,40-12,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } off2 += 40-12; if (excess) { off2 += excess; for (;excess;excess--) fgetc(in); // Can't seek stdin } width = buff[4] + ((unsigned)buff[5]<<8) + ((unsigned)buff[ 6]<<16) + ((unsigned)buff[ 7]<<24); height = buff[8] + ((unsigned)buff[9]<<8) + ((unsigned)buff[10]<<16) + ((unsigned)buff[11]<<24); if ((buff[12]!=1)||(buff[13])||(buff[15])) { ppl_error(ec, ERR_FILE, -1, -1,"This Windows bitmap file appears to be corrupted"); return; } depth = buff[14]; encode = buff[16]; size = buff[20] + (((int)(buff[21]))<<8) + (((int)(buff[22]))<<16) + (((int)(buff[23]))<<24); image->XDPI = 0.0254*(buff[24]+(((int)(buff[25]))<<8)+(((int)(buff[26]))<<16)+(((int)(buff[27]))<<24)); image->YDPI = 0.0254*(buff[28]+(((int)(buff[29]))<<8)+(((int)(buff[30]))<<16)+(((int)(buff[31]))<<24)); if (image->XDPI<1) image->XDPI=180; // Sensible default resolution in case of zero input if (image->YDPI<1) image->YDPI=180; } if (DEBUG) { sprintf(ec->tempErrStr, "Size %dx%d depth %d bits",width,height,depth); ppl_log(ec, NULL); } rle=0; if (encode!=0) { if ((encode==1)&&(depth== 8)) rle=8; else if ((encode==2)&&(depth== 4)) rle=4; else if ((encode!=3)||(depth!=16)) { ppl_error(ec, ERR_FILE, -1, -1,"This Windows bitmap file has an invalid encoding"); return; } } if ((depth!=1)&&(depth!=4)&&(depth!=8)&&(depth!=16)&&(depth!=24)) { sprintf(ec->tempErrStr, "Bitmap colour depth of %d not supported\n",depth); ppl_error(ec, ERR_FILE, -1, -1, NULL); return; } if (depth<=8) // We have a palette to read { ncols = 0; if (!os2 ) ncols = buff[32] + (buff[33]<<8) + (buff[34]<<16) + (buff[35]<<24); if (!ncols) ncols = 1< (1<tempErrStr, "Bitmap image has a palette length of %d, which is not possible with a colour depth of %d", ncols, depth); ppl_error(ec, ERR_FILE, -1, -1, NULL); return; } image->pal_len = ncols; image->palette = ppl_memAlloc(3*image->pal_len); off2 += (4-os2)*image->pal_len; if (image->palette == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } p = image->palette; for (i=0; ipal_len; i+=2) { // MS Windows uses BGR0, OS/2 uses BGR if (fread(buff,8-2*os2,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } *(p++)=buff[2]; *(p++)=buff[1]; *(p++)=buff[0]; *(p++)=buff[6-os2]; *(p++)=buff[5-os2]; *(p++)=buff[4-os2]; } image->type = BMP_COLOUR_PALETTE; image->colour = BMP_COLOUR_PALETTE; } else { image->type = BMP_COLOUR_BMP; image->colour = BMP_COLOUR_RGB; } if ((depth==16)&&(encode==3)) // Must read 12 byte pseudopalette { if (fread(buff+40,12,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } off2 += 12; } if (offsetoff2) { if (DEBUG) { sprintf(ec->tempErrStr, "%ld bytes of extra data", offset-off2); ppl_log(ec, NULL); } for ( ; off2height = height; image->width = width; dw = (width*depth+7)/8; image->data_len = dw*height; image->depth = depth; if (depth==16) { ppl_bmp_bmp16read(ec, in, buff, image); return; } if (!rle) { BMP_ALLOC(image->data , image->data_len); if (image->data==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } for (i=1 ; i<=height ; i++) { if (fread(image->data+(height-i)*dw,dw,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } if (dw&3) { if (fread(buff,4-(dw&3),1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } } // Lines are dword aligned } if (depth==24) // BMP is BGR not RGB { p=image->data; for(i=0; idata = NULL; return; } if (fread(p,size,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } if (ppl_bmp_demsrle(ec,image,p,size) != 0) { image->data = NULL; return; } } return; } void ppl_bmp_bmp16read(pplerr_context *ec, FILE *in, unsigned char *header, bitmap_data *image) { unsigned char *palette; unsigned char *rowptr,*ptr; unsigned int width,height,colour; int is15,i,j; is15=1; width=image->width; height=image->height; if (header[16]==3) // Read "palette" and check correct { // Palette can be 7c00 03e0 001f (15 bit) // or f800 07e0 001f (16 bit) // as represents RGB bitmasks. However, // Intel byte ordering afflicts the above, // and the entries are stored as dwords, // not words. palette = header+40; if ((palette[0]!=0) || (palette[4]!=0xe0) || (palette[8]!=0x1f) || (palette[9]!=0)) { ppl_error(ec, ERR_FILE, -1, -1, "This 16-bit bitmap file appears to be corrupted"); return; } if (palette[1]&0x80) is15=0; } else if (header[30]!=0) { ppl_error(ec, ERR_FILE, -1, -1, "This 16-bit bitmap file has invalid compression type"); return; } if (DEBUG) { if (is15) ppl_log(ec, "15 bit 555"); else ppl_log(ec, "16 bit 565"); } image->depth = 24; image->data_len = 3*width*height; BMP_ALLOC(image->data , image->data_len); if (image->data==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } rowptr = ppl_memAlloc(2*width); if (rowptr==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); image->data=NULL; return; } for (i=1; i<=height; i++) { if (fread(rowptr,2*width,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } ptr = image->data+(height-i)*3*width; for (j=0; j>2; } else { *(ptr+1) = (colour&0x07e0)>>3; colour>>=1; } *ptr = (colour&0x7c00)>>7; // red ptr += 3; } if (width&1) { if (fread(rowptr,2,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file appears to be corrupted"); return; } } // rows are dword aligned } return; } int ppl_bmp_demsrle(pplerr_context *ec, bitmap_data *image, unsigned char *in, unsigned long len) { unsigned char *out,*c_in,*c_out,code,*end,odd,even; unsigned long i,j,delta,size,height,width; int eol,rle; height = image->height; width = image->width; rle = image->depth; if ((rle!=4)&&(rle!=8)) { ppl_error(ec, ERR_FILE, -1, -1,"This bitmap file has an impossible MSRLE image depth"); return 1; } if (DEBUG) { sprintf(ec->tempErrStr, "Bitmap image has RLE%d compression\n",rle); ppl_log(ec, NULL); } image->depth = 8; size = height*width; image->data_len = size; BMP_ALLOC(out , image->data_len); if (out == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return 1; } c_in = in; c_out = out; for (i=1; i<=height; i++) { c_out = out + (height-i)*width; end = c_out + width - 1; eol = 0; while ((c_out<=end)&&(eol==0)) { code = *c_in++; if (code) // a run { if (rle==8) odd = even = *c_in++; else { odd = *c_in&0xf; even = (*c_in&0xf0)>>4; c_in++; } for (j=0; (jheight) { ppl_error(ec, ERR_FILE, -1, -1,"Image overflow whilst decoding RLE in bitmap image file"); return 1; } for(j=0; j>4; *c_out++ = (*c_in++)&0xf; } if (code&1) *c_out++ = ((*c_in++)&0xf0)>>4; if ((code+1)&2) c_in++; // Keep word aligned } } } } if (eol) { sprintf(ec->tempErrStr, "Whilst decoding bitmap image file, encountered bad line length in RLE decode line=%ld\n",i); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 1; } // Should now have an EOL or EOD code if (*(c_in++) != 0) { sprintf(ec->tempErrStr, "Whilst decoding bitmap image file, encountered bad line length in RLE decode line=%ld\n",i); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 1; } if ((*c_in!=0)&&((*c_in!=1)&&(i=height))) { sprintf(ec->tempErrStr, "Whilst decoding bitmap image file, encountered bad line length in RLE decode line=%ld\n",i); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 1; } c_in++; } image->data=out; return 0; } pyxplot-0.9.2/src/epsMaker/eps_plot_axespaint.c0000664000175000017500000005576312026340554020247 0ustar dcf21dcf21// eps_plot_axespaint.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_axespaint.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_AXESPAINT 1 #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "epsMaker/canvasDraw.h" #include "settings/settings.h" #include "settings/withWords_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/unitsDisp.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_axespaint.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_settings.h" void eps_plot_LabelAlignment(double theta_pinpoint, int *HALIGN, int *VALIGN) { theta_pinpoint = fmod(theta_pinpoint, 2*M_PI); while (theta_pinpoint < 0.0) theta_pinpoint += 2*M_PI; if (ppl_dblApprox(theta_pinpoint, 0.0 , 1e-6)) { *HALIGN = SW_HALIGN_CENT ; *VALIGN = SW_VALIGN_TOP ; } else if (ppl_dblApprox(theta_pinpoint, M_PI/2, 1e-6)) { *HALIGN = SW_HALIGN_RIGHT; *VALIGN = SW_VALIGN_CENT; } else if (ppl_dblApprox(theta_pinpoint, M_PI , 1e-6)) { *HALIGN = SW_HALIGN_CENT ; *VALIGN = SW_VALIGN_BOT ; } else if (ppl_dblApprox(theta_pinpoint, 3*M_PI/2, 1e-6)) { *HALIGN = SW_HALIGN_LEFT ; *VALIGN = SW_VALIGN_CENT; } else if (theta_pinpoint < M_PI/2) { *HALIGN = SW_HALIGN_RIGHT; *VALIGN = SW_VALIGN_TOP ; } else if (theta_pinpoint < M_PI ) { *HALIGN = SW_HALIGN_RIGHT; *VALIGN = SW_VALIGN_BOT ; } else if (theta_pinpoint < 3*M_PI/2) { *HALIGN = SW_HALIGN_LEFT ; *VALIGN = SW_VALIGN_BOT ; } else { *HALIGN = SW_HALIGN_LEFT ; *VALIGN = SW_VALIGN_TOP ; } return; } void eps_plot_axispaint(EPSComm *x, withWords *ww, pplset_axis *a, const int xyz, const double CP2, const unsigned char Lr, const double x1, const double y1, const double *z1, const double x2, const double y2, const double *z2, const double theta_a, const double theta_b, double *OutputWidth, const unsigned char PrintLabels) { int i, l, m, lt; double TickMaxHeight = 0.0, height, width, theta_axis; int HALIGN, VALIGN, HALIGN_THIS, VALIGN_THIS; double theta, theta_pinpoint; // clockwise rotation double lw, lw_scale; char *last_colstr=NULL; x->LaTeXpageno = a->FirstTextID; *OutputWidth = 0.0; // Set linewidth and linetype if (ww->USElinewidth) lw_scale = ww->linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww->USElinetype) lt = ww->linetype; else lt = 1; // Draw line of axis IF_NOT_INVISIBLE { if (a->ArrowType == SW_AXISDISP_NOARR) eps_primitive_arrow(x, SW_ARROWTYPE_NOHEAD, x1, y1, z1, x2, y2, z2, ww); else if (a->ArrowType == SW_AXISDISP_ARROW) eps_primitive_arrow(x, SW_ARROWTYPE_HEAD , x1, y1, z1, x2, y2, z2, ww); else if (a->ArrowType == SW_AXISDISP_TWOAR) eps_primitive_arrow(x, SW_ARROWTYPE_TWOWAY, x1, y1, z1, x2, y2, z2, ww); else if (a->ArrowType == SW_AXISDISP_BACKA) eps_primitive_arrow(x, SW_ARROWTYPE_HEAD , x2, y2, z2, x1, y1, z1, ww); theta_axis = atan2(x2-x1,y2-y1); if (!gsl_finite(theta_axis)) theta_axis=0.0; // Paint axis ticks for (i=0; i<2; i++) { int TR; double *TLP, TRA, TLEN; char **TLS; if (i==0) { TLP=a-> TickListPositions; TLS=a-> TickListStrings; TRA=a->TickLabelRotate; TR=a->TickLabelRotation; TLEN = EPS_AXES_MAJTICKLEN; } // Major ticks else { TLP=a->MTickListPositions; TLS=a->MTickListStrings; TRA=a->TickLabelRotate; TR=a->TickLabelRotation; TLEN = EPS_AXES_MINTICKLEN; } // Minor ticks // Work out the rotation of the tick labels if (TR == SW_TICLABDIR_HORI) theta = 0.0; else if (TR == SW_TICLABDIR_VERT) theta = -M_PI/2; // the clockwise rotation of the labels relative to upright else theta = -TRA; theta_pinpoint = theta + M_PI/2 + theta_axis + M_PI*(!Lr); // Angle around textboxes where it is anchored eps_plot_LabelAlignment(theta_pinpoint, &HALIGN, &VALIGN); if (TLP != NULL) { for (l=0; TLS[l]!=NULL; l++) { unsigned char state=0; double tic_lab_xoff=0.0; double tic_x1 = x1 + (x2-x1) * TLP[l]; double tic_y1 = y1 + (y2-y1) * TLP[l]; double tic_x2 , tic_y2, tic_x3, tic_y3; for (m=0; ((m<2)&&(!state)); m++) { double theta_ab = m ? theta_a : theta_b; if (!gsl_finite(theta_ab)) continue; tic_x2 = tic_x1 + (a->tics.tickDir==SW_TICDIR_IN ? 0.0 : 1.0) * sin(theta_ab) * TLEN * M_TO_PS; // top of tick tic_y2 = tic_y1 + (a->tics.tickDir==SW_TICDIR_IN ? 0.0 : 1.0) * cos(theta_ab) * TLEN * M_TO_PS; tic_x3 = tic_x1 + (a->tics.tickDir==SW_TICDIR_OUT ? 0.0 : -1.0) * sin(theta_ab) * TLEN * M_TO_PS; // bottom of tick tic_y3 = tic_y1 + (a->tics.tickDir==SW_TICDIR_OUT ? 0.0 : -1.0) * cos(theta_ab) * TLEN * M_TO_PS; // Check for special case of ticks at zero on axes crossed by atzero axes HALIGN_THIS = HALIGN; VALIGN_THIS = VALIGN; if ((a->CrossedAtZero) && (a->atzero)) { double CP1 = TLP[l]; double xl = TLP[l] - 1e-3; double xr = TLP[l] + 1e-3; if (xl<0.0) xl=0.0; if (xl>1.0) xl=1.0; if (xr<0.0) xr=0.0; if (xr>1.0) xr=1.0; xl = eps_plot_axis_InvGetPosition(xl, a); xr = eps_plot_axis_InvGetPosition(xr, a); if ((gsl_finite(xl)) && (gsl_finite(xr)) && ((xl==0)||(xr==0)||((xl<0)&&(xr>0))||((xl>0)&&(xr<0)))) { if (xyz != 0) // y/z-axis -- only put label at zero if axis is at edge of graph { if (!( ((CP2<1e-3)&&( Lr)) || ((CP2>0.999)&&(!Lr)) )) { if (PrintLabels && (TLS[l][0] != '\0')) x->LaTeXpageno++; state=1; continue; } } else // x-axis -- if at edge of graph, put label at zero. If y-axis is labelled at zero, don't put label at zero... { if (!( ((CP2<1e-3)&&(!Lr)) || ((CP2>0.999)&&( Lr)) )) { int Lr1 = (xyz==0) ^ (CP1>0.999); if ( ((CP1<1e-3)&&( Lr1)) || ((CP1>0.999)&&(!Lr1)) ) { if (PrintLabels && (TLS[l][0] != '\0')) x->LaTeXpageno++; state=1; continue; } else // ... otherwise, displace label at zero to one side { double theta_pinpoint = theta + 1.5 * M_PI/2 + theta_axis + M_PI*(!Lr); // Angle around textboxes where it is anchored eps_plot_LabelAlignment(theta_pinpoint, &HALIGN_THIS, &VALIGN_THIS); tic_lab_xoff = -TLEN; // Move label to the left } } } } } // Stroke the tick, unless it is at the end of an axis with an arrowhead if (!( ((TLP[l]<1e-3)&&((a->ArrowType == SW_AXISDISP_BACKA)||(a->ArrowType == SW_AXISDISP_TWOAR))) || ((TLP[l]>0.999)&&((a->ArrowType == SW_AXISDISP_ARROW)||(a->ArrowType == SW_AXISDISP_TWOAR))) )) { if (z1==NULL) fprintf(x->epsbuffer, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", tic_x2, tic_y2, tic_x3, tic_y3); else { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr!=NULL) { strcpy(last_colstr, x->CurrentColor); sprintf(x->c->errcontext.tempErrStr, "newpath %.2f %.2f moveto %.2f %.2f lineto stroke\n", tic_x2, tic_y2, tic_x3, tic_y3); ThreeDimBuffer_writeps(x, *z1 + (*z2-*z1)*TLP[l], lt, lw, 0.0, 1, last_colstr, x->c->errcontext.tempErrStr); } } eps_core_PlotBoundingBox(x, tic_x2, tic_y2, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1); eps_core_PlotBoundingBox(x, tic_x3, tic_y3, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1); } } if (state) continue; // Paint the tick label if (PrintLabels && (TLS[l][0] != '\0')) { int pageno = x->LaTeXpageno++; double xlab, ylab; xlab = tic_x1/M_TO_PS + (Lr ? -1.0 : 1.0) * sin(theta_axis + M_PI/2) * EPS_AXES_TEXTGAP + tic_lab_xoff; ylab = tic_y1/M_TO_PS + (Lr ? -1.0 : 1.0) * cos(theta_axis + M_PI/2) * EPS_AXES_TEXTGAP; IF_NOT_INVISIBLE { char *text=NULL; canvas_EPSRenderTextItem(x, &text, pageno, xlab, ylab, HALIGN_THIS, VALIGN_THIS, x->CurrentColor, x->current->settings.FontSize, theta, &width, &height); if (text!=NULL) { if (z1==NULL) fprintf(x->epsbuffer, "%s", text); else { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr!=NULL) { strcpy(last_colstr, x->CurrentColor); ThreeDimBuffer_writeps(x, *z1 + (*z2-*z1)*TLP[l], lt, lw, 0.0, 1, last_colstr, text); } } } height = height*fabs(cos(theta_pinpoint)) + width*fabs(sin(theta_pinpoint)); if (height > TickMaxHeight) TickMaxHeight = height; } } } } } if (TickMaxHeight>0.0) *OutputWidth = EPS_AXES_TEXTGAP * M_TO_PS + TickMaxHeight; // Allow a gap after axis labels // Write axis label if (PrintLabels && (a->FinalAxisLabel != NULL) && (a->FinalAxisLabel[0]!='\0')) { int pageno = x->LaTeXpageno++; double xlab, ylab; double width, height; // Work out the rotation of the tick label theta = -a->LabelRotate; theta_pinpoint = theta + M_PI*Lr; // Angle around textbox where it is anchored eps_plot_LabelAlignment(theta_pinpoint, &HALIGN, &VALIGN); xlab = (x1+x2)/2/M_TO_PS + (Lr ? -1.0 : 1.0) * (2*EPS_AXES_TEXTGAP+TickMaxHeight/M_TO_PS) * sin(theta_axis+M_PI/2); ylab = (y1+y2)/2/M_TO_PS + (Lr ? -1.0 : 1.0) * (2*EPS_AXES_TEXTGAP+TickMaxHeight/M_TO_PS) * cos(theta_axis+M_PI/2); IF_NOT_INVISIBLE { char *text=NULL; double theta_text = theta + M_PI/2 - theta_axis; theta_text = fmod(theta_text , 2*M_PI); if (theta_text < -M_PI ) theta_text += 2*M_PI; if (theta_text > M_PI ) theta_text -= 2*M_PI; if (theta_text > M_PI/2) theta_text -= M_PI; if (theta_text < -M_PI/2) theta_text += M_PI; canvas_EPSRenderTextItem(x, &text, pageno, xlab, ylab, HALIGN, VALIGN, x->CurrentColor, x->current->settings.FontSize, theta_text, &width, &height); *OutputWidth += (EPS_AXES_TEXTGAP * M_TO_PS + height*fabs(cos(theta_pinpoint)) + width*fabs(sin(theta_pinpoint)) ); // Allow gap after label if (text!=NULL) { if (z1==NULL) fprintf(x->epsbuffer, "%s", text); else { if ((last_colstr==NULL)||(strcmp(last_colstr,x->CurrentColor)!=0)) last_colstr = (char *)ppl_memAlloc(strlen(x->CurrentColor)+1); if (last_colstr!=NULL) { strcpy(last_colstr, x->CurrentColor); ThreeDimBuffer_writeps(x, (*z2+*z1)/2, lt, lw, 0.0, 1, last_colstr, text); } } } } } // Allow a gap before next axis *OutputWidth += EPS_AXES_SEPARATION * M_TO_PS; } } void eps_plot_axespaint(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth, int pass) { int i, j, k; double xc, yc, zc, theta[3]={M_PI/2,0,0}; // Coordinates of centre of graph pplset_axis *axes; withWords ww; if ((pass==0) && (!x->current->ThreeDim)) return; // 2D plots do not have back axes // Set color for painting axes ppl_withWordsZero(x->c,&ww); if (x->current->settings.AxesColor > 0) { ww.color = x->current->settings.AxesColor; ww.USEcolor = 1; } else { ww.Col1234Space = x->current->settings.AxesCol1234Space; ww.color1 = x->current->settings.AxesColor1; ww.color2 = x->current->settings.AxesColor2; ww.color3 = x->current->settings.AxesColor3; ww.color4 = x->current->settings.AxesColor4; ww.USEcolor1234 = 1; } ww.linewidth = EPS_AXES_LINEWIDTH; ww.USElinewidth = 1; ww.linetype = 1; ww.USElinetype = 1; eps_core_SetColor(x, &ww, 1); IF_NOT_INVISIBLE eps_core_SetLinewidth(x, EPS_AXES_LINEWIDTH * EPS_DEFAULT_LINEWIDTH, 1, 0.0); // Reset plot bounding box; we're about to make this sensible below by factoring in plot vertices if ((pass==0)||(!x->current->ThreeDim)) { x->current->PlotLeftMargin = x->current->PlotRightMargin = origin_x; x->current->PlotTopMargin = x->current->PlotBottomMargin = origin_y; } // Fetch coordinates of centre of graph if (x->current->ThreeDim) { eps_plot_ThreeDimProject(0.5,0.5,0.5, &x->current->settings,origin_x,origin_y,width,height,zdepth, &xc,&yc,&zc); } else { xc = origin_x + 0.5*width; yc = origin_y + 0.5*height; zc = 0.0; } // Work out directions of each of the axes if (x->current->ThreeDim) for (j=0; j<3; j++) { double x1,y1,z1,x2,y2,z2; eps_plot_ThreeDimProject( 0 , 0 , 0 , &x->current->settings,origin_x,origin_y,width,height,zdepth, &x1,&y1,&z1); eps_plot_ThreeDimProject((j==0),(j==1),(j==2), &x->current->settings,origin_x,origin_y,width,height,zdepth, &x2,&y2,&z2); theta[j] = atan2(x2-x1,y2-y1); if (!gsl_finite(theta[j])) theta[j] = 0.0; } // Set CrossedAtZero flags for (j=0; j<3; j++) { if (j==0) axes = x->current->XAxes; else if (j==1) axes = x->current->YAxes; else axes = x->current->ZAxes; for (i=0; icurrent->XAxes[1].CrossedAtZero = 1; if (j!=1) x->current->YAxes[1].CrossedAtZero = 1; if (j!=2) x->current->ZAxes[1].CrossedAtZero = 1; break; } } // Loop over all axes to draw. First loop over x, y and z directions. for (j=0; j<2+(x->current->ThreeDim!=0); j++) { int xap, yap, zap, Naxes[4], FirstAutoMirror[4]; unsigned char side_a[4]={0,1,0,1}, side_b[4]={0,0,1,1}; double xpos1[4], ypos1[4], zpos1[4], xpos2[4], ypos2[4], zpos2[4]; int NDIRS = x->current->ThreeDim ? 4 : 2; double theta_a = theta[(j==0)?1:0]; double theta_b = theta[(j==2)?1:2]; // Set count of axes to zero Naxes [0] = Naxes [1] = Naxes [2] = Naxes [3] = 0; FirstAutoMirror[0] = FirstAutoMirror[1] = FirstAutoMirror[2] = FirstAutoMirror[3] = -1; if (!x->current->ThreeDim) theta_b=GSL_NAN; // Loop over vertices of graph factoring into bounding box and setting pos1 and pos2 for (xap=0; xap<=1; xap++) for (yap=0; yap<=1; yap++) for (zap=0; zap<=1; zap++) { double tmp_x, tmp_y, tmp_z; int k=0, l=0; if (x->current->ThreeDim) { eps_plot_ThreeDimProject(xap, yap, zap, &x->current->settings,origin_x,origin_y,width,height,zdepth,&tmp_x,&tmp_y,&tmp_z); } else { tmp_x = origin_x + xap*width; tmp_y = origin_y + yap*height; tmp_z = 0.0; } if (j!=2) k=2*k+zap; else l=zap; if (j!=1) k=2*k+yap; else l=yap; if (j!=0) k=2*k+xap; else l=xap; if (l==0) { xpos1[k] = tmp_x; ypos1[k] = tmp_y; zpos1[k] = tmp_z; } else { xpos2[k] = tmp_x; ypos2[k] = tmp_y; zpos2[k] = tmp_z; } eps_core_PlotBoundingBox(x, tmp_x, tmp_y, 0.0, 0); } // Swap edges of cube around to put edges at (x,y)-extremes first if (x->current->ThreeDim) { #define TSM(A) hypot(xpos1[A]+xpos2[A]-2*origin_x , ypos1[A]+ypos2[A]-2*origin_y) #define TRY_SWAP(A,B) if (TSM(A)<0.9999999*TSM(B)) { double tmp[6]={xpos1[A],ypos1[A],zpos1[A],xpos2[A],ypos2[A],zpos2[A]}; unsigned char tsa=side_a[A], tsb=side_b[A]; xpos1[A]=xpos1[B]; ypos1[A]=ypos1[B]; zpos1[A]=zpos1[B]; xpos2[A]=xpos2[B]; ypos2[A]=ypos2[B]; zpos2[A]=zpos2[B]; xpos1[B]=tmp[0]; ypos1[B]=tmp[1]; zpos1[B]=tmp[2]; xpos2[B]=tmp[3]; ypos2[B]=tmp[4]; zpos2[B]=tmp[5]; side_a[A]=side_a[B]; side_b[A]=side_b[B]; side_a[B]=tsa; side_b[B]=tsb; } TRY_SWAP(2,3); TRY_SWAP(1,2); TRY_SWAP(0,1); TRY_SWAP(2,3); TRY_SWAP(1,2); } // Fetch relevant list of axes if (j==0) axes = x->current->XAxes; else if (j==1) axes = x->current->YAxes; else axes = x->current->ZAxes; // Loop over all axes in this direction and draw any which are active and visible for (i=0; icurrent->settings.projection == SW_PROJ_GNOM) { } // Flat axes else { if (axes[i].atzero) { pplset_axis *PerpAxisX = &(x->current->XAxes[1]); // Put axis at zero of perpendicular x1-, y1- and z1-axes pplset_axis *PerpAxisY = &(x->current->YAxes[1]); pplset_axis *PerpAxisZ = &(x->current->ZAxes[1]); unsigned char LastX, LastY, LastZ, DoneX, DoneY, DoneZ; int xrn, yrn, zrn; double pos[3], xpos1, ypos1, zpos1, xpos2, ypos2, zpos2, dummy; for (DoneX=LastX=0,xrn=0; !LastX; xrn++) { pos[0] = 0.5; LastX = ((j==0)||(!PerpAxisX->FinalActive)||(xrn>PerpAxisX->AxisValueTurnings)); if ((j!=0)&&(PerpAxisX->FinalActive)) pos[0] = eps_plot_axis_GetPosition(0.0, PerpAxisX, xrn, 0); if ((!gsl_finite(pos[0])) && (!DoneX) && LastX) pos[0] = 0.5; if (!gsl_finite(pos[0])) continue; for (DoneY=LastY=0,yrn=0; !LastY; yrn++) { pos[1] = 0.5; LastY = ((j==1)||(!PerpAxisY->FinalActive)||(yrn>PerpAxisY->AxisValueTurnings)); if ((j!=1)&&(PerpAxisY->FinalActive)) pos[1] = eps_plot_axis_GetPosition(0.0, PerpAxisY, yrn, 0); if ((!gsl_finite(pos[1])) && (!DoneY) && LastY) pos[1] = 0.5; if (!gsl_finite(pos[1])) continue; for (DoneZ=LastZ=0,zrn=0; !LastZ; zrn++) { pos[2] = 0.5; LastZ = ((j==2)||(!x->current->ThreeDim)||(!PerpAxisZ->FinalActive)||(zrn>PerpAxisZ->AxisValueTurnings)); if ((j!=2)&&(PerpAxisZ->FinalActive)) pos[2] = eps_plot_axis_GetPosition(0.0, PerpAxisZ, zrn, 0); if ((!gsl_finite(pos[2])) && (!DoneZ) && LastZ) pos[2] = 0.5; if (!gsl_finite(pos[2])) continue; pos[j] = 0.0; if (x->current->ThreeDim) { eps_plot_ThreeDimProject(pos[0],pos[1],pos[2],&x->current->settings,origin_x,origin_y,width,height,zdepth,&xpos1,&ypos1,&zpos1); } else { xpos1=origin_x+pos[0]*width; ypos1=origin_y+pos[1]*height; } pos[j] = 1.0; if (x->current->ThreeDim) { eps_plot_ThreeDimProject(pos[0],pos[1],pos[2],&x->current->settings,origin_x,origin_y,width,height,zdepth,&xpos2,&ypos2,&zpos2); } else { xpos2=origin_x+pos[0]*width; ypos2=origin_y+pos[1]*height; } if ((pass==0)&&(x->current->ThreeDim)) { double b = atan2((xpos2+xpos1)/2-xc , (ypos2+ypos1)/2-yc) - theta[j]; unsigned char Lr = sin(b)<0; eps_plot_axispaint(x, &ww, axes+i, j, GSL_NAN, Lr, xpos1, ypos1, &zpos1, xpos2, ypos2, &zpos2, theta_a+M_PI*((j==0)?(pos[1]<=0.5):(pos[0]<=0.5)), theta_b+M_PI*((j==2)?(pos[1]<=0.5):(pos[2]<=0.5)), &dummy, 1); } else if ((pass==1)&&(!x->current->ThreeDim)) { eps_plot_axispaint(x, &ww, axes+i, j, pos[j==0], (j!=0) ^ (pos[j==0]>0.999), xpos1, ypos1, NULL, xpos2, ypos2, NULL, theta_a, theta_b, &dummy, 1); } }}} // Loop over xrn, yrn and zrn } else // axis is notatzero... i.e. it is either at top or bottom of graph { if (axes[i].MirrorType == SW_AXISMIRROR_AUTO) for (k=0; k<4; k++) if ((k!=axes[i].topbottom) && (FirstAutoMirror[k]<0)) FirstAutoMirror[k] = i; for (k=0; kcurrent->ThreeDim) || (((zpos1[k]+zpos2[k])>0.0)==(pass==0))) { double b = atan2((xpos2[k]+xpos1[k])/2-xc , (ypos2[k]+ypos1[k])/2-yc) - theta[j]; unsigned char Lr = sin(b)<0; unsigned char label = ((k==axes[i].topbottom) || (axes[i].MirrorType == SW_AXISMIRROR_FULLMIRROR)); double IncGap, ang; eps_plot_axispaint(x, &ww, axes+i, j, GSL_NAN, Lr, xpos1[k], ypos1[k], NULL, xpos2[k], ypos2[k], NULL, theta_a+(side_a[k]?0:M_PI), theta_b+(side_b[k]?0:M_PI), &IncGap, label); ang = theta[j] + M_PI/2 * ((Lr==0)*2-1); xpos1[k] += IncGap * sin(ang); ypos1[k] += IncGap * cos(ang); xpos2[k] += IncGap * sin(ang); ypos2[k] += IncGap * cos(ang); Naxes[k]++; } } } } // If there is no axis on any side, but was an auto-mirrored axis on another side, mirror it now for (k=0; k=0)) if ((!x->current->ThreeDim) || (((zpos1[k]+zpos2[k])>0.0)==(pass==0))) { double b = atan2((xpos2[k]+xpos1[k])/2-xc , (ypos2[k]+ypos1[k])/2-yc) - theta[j]; unsigned char Lr = sin(b)<0; double IncGap, ang; eps_plot_axispaint(x, &ww, axes+FirstAutoMirror[k], j, GSL_NAN, Lr, xpos1[k], ypos1[k], NULL, xpos2[k], ypos2[k], NULL, theta_a+(side_a[k]?0:M_PI), theta_b+(side_b[k]?0:M_PI), &IncGap, 0); ang = theta[j] + M_PI/2 * ((Lr==0)*2-1); xpos1[k] += IncGap * sin(ang); ypos1[k] += IncGap * cos(ang); xpos2[k] += IncGap * sin(ang); ypos2[k] += IncGap * cos(ang); Naxes[k]++; } } return; } pyxplot-0.9.2/src/epsMaker/dvi_font.c0000664000175000017500000004313512026340554016144 0ustar dcf21dcf21// dvi_font.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_font.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating dvi files -- font section #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "stringTools/strConstants.h" #include "epsMaker/dvi_read.h" #include "epsMaker/dvi_font.h" #include "epsMaker/kpse_wrap.h" #define N_BUILTIN_FONTS 5 #define L_BUILTIN_FNAME 10 #define L_BUILTIN_FPSNAME 23 char builtinFonts[N_BUILTIN_FONTS][L_BUILTIN_FNAME] = {"ptmb7t", "ptmr7t", "ptmri7t", "phvr7t", "pcrr7t"}; char builtinFontNames[N_BUILTIN_FONTS][L_BUILTIN_FPSNAME] = {"Times-Bold", "Times-Roman", "Times-Italic", "Helvetica", "Courier"}; int dviGetPfa(pplerr_context *ec, dviFontDetails *font, char *filename); int dviGetTFM(pplerr_context *ec, dviFontDetails *font) { char *TFMpath; char *s; char errStr[SSTR_LENGTH]; int err=0; int i; FILE *TFMfp; // Get the TFM file s = (char *)ppl_memAlloc(strlen(font->name)+5); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } sprintf(s, "%s.tfm", font->name); TFMpath = ppl_kpse_wrap_find_tfm(ec, s); if (TFMpath==NULL) { snprintf(errStr, SSTR_LENGTH, "Could not find TFM file '%s'. You may be able to fix this with a more complete installation of tex.", s); ppl_error(ec, ERR_INTERNAL, -1, -1, errStr); return 1; } if (DEBUG) { sprintf(ec->tempErrStr, "Font file %s: TFM path: %s", font->name, TFMpath); ppl_log(ec, NULL); } TFMfp = fopen(TFMpath, "r"); if (TFMfp==NULL) { snprintf(errStr, SSTR_LENGTH, "Could not open TFM file '%s'. You may be able to fix this with a more complete installation of tex.", s); ppl_error(ec, ERR_INTERNAL, -1, -1, errStr); return 1; } font->tfm = dviReadTFM(ec, TFMfp, &err); fclose(TFMfp); if (err) return err; // Find the maximum height and depth of the font err = dviFindMaxSize(ec, font); if (err) return err; // Work out what type of font this is if (strncmp(font->tfm->coding, "TeX text" , 8)==0) font->fontType = FONT_TEX_TEXT; else if (strncmp(font->tfm->coding, "TeX math italic" , 15)==0) font->fontType = FONT_TEX_MATH; else if (strncmp(font->tfm->coding, "TeX math extension", 18)==0) font->fontType = FONT_TEX_MEXT; else if (strncmp(font->tfm->coding, "TeX math symbols" , 16)==0) font->fontType = FONT_TEX_MSYM; else font->fontType = FONT_UNKNOWN; // This is a list of bonkers fonts if (strncmp(font->tfm->family, "WASY", 4)==0) font->fontType = FONT_SYMBOL; if (DEBUG) {sprintf(ec->tempErrStr, "TFM: font type %d", font->fontType); ppl_log(ec, NULL);} // Deal with built-in fonts font->psName = NULL; for (i=0; iname)==strlen(builtinFonts[i]) && strncmp(font->name, builtinFonts[i], L_BUILTIN_FNAME)==0) { font->pfaPath = NULL; font->psName = (char *)ppl_memAlloc(strlen(builtinFontNames[i])+1); if (font->name==NULL) { ppl_error(ec, ERR_MEMORY,-1,-1,"Out of memory"); return DVIE_MEMORY; } strcpy(font->psName, builtinFontNames[i]); if (DEBUG) { snprintf(errStr, SSTR_LENGTH, "Found builtin font %sXXX%sXXX%sXXX %d", builtinFonts[i], font->psName, builtinFontNames[i], i); ppl_log(ec, errStr); } break; } } /* if (strlen(font->name)==6 && strncmp(font->name, "ptmb7t", 6)==0) { // Times-Bold font->pfaPath = NULL; font->psName = (char *)ppl_memAlloc(11); if (font->name==NULL) { ppl_error(ec, ERR_MEMORY,"Out of memory"); return DVIE_MEMORY; } snprintf(font->psName, 11, "Times-Bold"); } else if (strlen(font->name)==6 && strncmp(font->name, "ptmr7t", 6)==0) { // Times-Roman font->pfaPath = NULL; font->psName = (char *)ppl_memAlloc(12); if (font->name==NULL) { ppl_error(ec, ERR_MEMORY,"Out of memory"); return DVIE_MEMORY; } snprintf(font->psName, 12, "Times-Roman"); } else */ if (font->psName == NULL) // Not found a built-in font { // Obtain the pfa file err = dviGetPfa(ec, font, font->name); if (err == DVIE_NOFONT) { err = dviGetPfa(ec, font, font->tfm->family); if (err == DVIE_NOFONT) { snprintf(errStr, SSTR_LENGTH, "dviGetTfm: Cannot find pfa or pfb file for font %s", font->name); ppl_error(ec, ERR_GENERIC, -1, -1, errStr); } } if (err != 0) return err; // Obtain the font name from the PFA file font->psName = psNameFromPFA(ec, font->pfaPath); if (font->psName==NULL) return 1; } return 0; } // Locate and obtain pfa file int dviGetPfa(pplerr_context *ec, dviFontDetails *font, char *filename) { FILE *fpin, *fpout; char errStr[SSTR_LENGTH]; char *s, *PFApath, *PFBpath; int err, i; s = (char *)ppl_memAlloc(strlen(filename)+5); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } sprintf(s, "%s.pfa", filename); // Crude lower-casing for (i=0; i= 'A' && s[i] <= 'Z') s[i] = s[i] + 'a' - 'A'; PFApath = ppl_kpse_wrap_find_pfa(ec, s); if (PFApath != NULL) { font->pfaPath = PFApath; } else { // Make a PFA file from the PFB file (assuming that one exists) sprintf(s, "%s.pfb", filename); // Crude lower-casing for (i=0; i= 'A' && s[i] <= 'Z') s[i] = s[i] + 'a' - 'A'; PFBpath = ppl_kpse_wrap_find_pfb(ec, s); if (PFBpath == NULL) { snprintf(errStr, SSTR_LENGTH, "dviGetTfm: Cannot find pfa or pfb file for font %s using name %s", font->name, filename); ppl_log(ec, errStr); return DVIE_NOFONT; } fpin = fopen(PFBpath, "r"); if (fpin==NULL) { snprintf(errStr, SSTR_LENGTH, "dviGetTfm: Cannot open pfb file %s", PFBpath); ppl_error(ec, ERR_GENERIC, -1, -1,errStr); return DVIE_ACCESS; } // Make a filename for the destination pfa file // free(PFApath); PFApath = (char *)ppl_memAlloc(SSTR_LENGTH); if (PFApath==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); fclose(fpin); return DVIE_MEMORY; } snprintf(PFApath, SSTR_LENGTH, "%s%s%s.pfa", ec->session_default.tempdir, PATHLINK, font->name); fpout = fopen(PFApath, "w"); if (fpout == NULL) { snprintf(errStr, SSTR_LENGTH, "dviGetTfm: Cannot write to pfa file %s", PFApath); ppl_error(ec, ERR_GENERIC, -1, -1,errStr); fclose(fpin); return DVIE_ACCESS; } if ((err=pfb2pfa(ec, fpin, fpout))!=0) { if (DEBUG) { snprintf(errStr, SSTR_LENGTH, "Fail in pfb2pfa: %d", err); ppl_log(ec, errStr); } fclose(fpin); fclose(fpout); return err; } fclose(fpin); fclose(fpout); font->pfaPath = PFApath; } return 0; } // Extract the font name from a PFA file // XXX This is an entirely empirical algorithm and may not be general! // If the font name is longer than SSTR_LENGTH this will fail (safely)... char *psNameFromPFA(pplerr_context *ec, char *PFApath) { FILE *fp; char *s; char buf[SSTR_LENGTH], c; int i; if ((fp = fopen(PFApath, "r"))==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1, "Cannot open pfa file"); return NULL; } // Forward file to the first space c = '\0'; while (c!=' ') c = getc(fp); // Grab characters until the next space i=0; while ((c=getc(fp))!=' ' && ilf = buff[0]; tfm->lh = buff[1]; tfm->bc = buff[2]; tfm->ec = buff[3]; tfm->nw = buff[4]; tfm->nh = buff[5]; tfm->nd = buff[6]; tfm->ni = buff[7]; tfm->nl = buff[8]; tfm->nk = buff[9]; tfm->ne = buff[10]; tfm->np = buff[11]; if (DEBUG) { sprintf(ec->tempErrStr, "TFM: "); j = strlen(ec->tempErrStr); for (i=0; i<12; i++) { sprintf(ec->tempErrStr+j, "%s:%lu ", tit[i], buff[i]); j+=strlen(ec->tempErrStr+j); } ppl_log(ec, NULL); } // We should have lf=6+lh+(ec-bc+1)+nw+nh+nd+ni+nl+nk+ne+np if (tfm->lf != 6 + tfm->lh + tfm->ec - tfm->bc + 1 + tfm->nw + tfm->nh + tfm->nd + tfm->ni + tfm->nl + tfm->nk + tfm->ne + tfm->np) { ppl_error(ec, ERR_INTERNAL, -1, -1,"TFM fail"); *err=1; return NULL; } // Read the header (distinct from the file header...) lh = tfm->lh; ReadLongInt(ec, fp, buff, 4); tfm->checksum = buff[0]; lh--; tfm->ds = ReadFixWord(ec, fp, err); if (*err) return NULL; lh--; if (DEBUG) { sprintf(ec->tempErrStr, "TFM: lh now %d", lh); ppl_log(ec, NULL); } if (lh>=10) { int len; if ((*err=ReadUChar(ec, fp, &len))!=0) return NULL; if (DEBUG) { sprintf(ec->tempErrStr, "TFM: Coding length: %d", len); ppl_log(ec, NULL); } if (len>39) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Malformed DVI header. coding len>40"); len=39; } for (i=0; i<39; i++) { int t; if ((*err=ReadUChar(ec, fp,&t))!=0) return NULL; tfm->coding[i] = t; } tfm->coding[len] = '\0'; lh-=10; } if (lh>=5) { int len; if ((*err=ReadUChar(ec, fp, &len))!=0) return NULL; if (len>19) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Malformed DVI header. coding len>19"); len=19; } if (DEBUG) { sprintf(ec->tempErrStr, "TFM: Family length: %d", len); ppl_log(ec, NULL); } for (i=0; i<19; i++) { int t; if ((*err=ReadUChar(ec, fp,&t))!=0) return NULL; tfm->family[i] = t; } tfm->family[len] = '\0'; lh-=5; } if (DEBUG) { sprintf(ec->tempErrStr, "TFM: coding:%s: family:%s: lh now %d", tfm->coding, tfm->family, lh); ppl_log(ec, NULL); } if (lh>0) { int temp; if ((*err=ReadUChar(ec, fp, &temp))!=0) return NULL; if ((*err=ReadUChar(ec, fp, &temp))!=0) return NULL; tfm->face = temp; if ((*err=ReadUChar(ec, fp, &temp))!=0) return NULL; if ((*err=ReadUChar(ec, fp, &temp))!=0) return NULL; lh--; if (DEBUG) { sprintf(ec->tempErrStr, "TFM: face:%d", tfm->face); ppl_log(ec, NULL); } } while (lh>0) { unsigned long int i; ReadLongInt(ec, fp, &i, 4); lh--; } // Read the char info tables Nchars = tfm->ec - tfm->bc + 1; tfm->charInfo = (TFMcharInfo *)ppl_memAlloc(Nchars*sizeof(TFMcharInfo)); if (tfm->charInfo==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Out of memory"); *err=DVIE_MEMORY; return NULL; } for (i=0; icharInfo+i)->wi = t[0]; (tfm->charInfo+i)->hi = t[1]>>4; (tfm->charInfo+i)->di = t[1]&0xf; (tfm->charInfo+i)->ii = t[2]>>2; (tfm->charInfo+i)->tag = t[2]&0x3; (tfm->charInfo+i)->rem = t[3]; } // Read the width, height, depth & italic tables tfm->width = (double *)ppl_memAlloc(tfm->nw*sizeof(double)); tfm->height = (double *)ppl_memAlloc(tfm->nh*sizeof(double)); tfm->depth = (double *)ppl_memAlloc(tfm->nd*sizeof(double)); tfm->italic = (double *)ppl_memAlloc(tfm->ni*sizeof(double)); if ((tfm->width==NULL)||(tfm->height==NULL)||(tfm->depth==NULL)||(tfm->italic==NULL)) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Out of memory"); *err=DVIE_MEMORY; return NULL; } for (i=0; inw; i++) { tfm->width[i] = ReadFixWord(ec, fp,err); if (*err) return NULL; } for (i=0; inh; i++) { tfm->height[i] = ReadFixWord(ec, fp,err); if (*err) return NULL; } for (i=0; ind; i++) { tfm->depth[i] = ReadFixWord(ec, fp,err); if (*err) return NULL; } for (i=0; ini; i++) { tfm->italic[i] = ReadFixWord(ec, fp,err); if (*err) return NULL; } // Read the lig_kern table tfm->ligKern = (TFMligKern *)ppl_memAlloc(tfm->nl*sizeof(TFMligKern)); if (tfm->ligKern==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Out of memory"); *err=DVIE_MEMORY; return NULL; } for (i=0; inl; i++) { int j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->ligKern+i)->skip_byte = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->ligKern+i)->next_char = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->ligKern+i)->op_byte = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->ligKern+i)->remainder = j; } // Read the kern table tfm->kern = (double *)ppl_memAlloc(tfm->nk*sizeof(double)); if (tfm->kern==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Out of memory"); *err=DVIE_MEMORY; return NULL; } for (i=0; ink; i++) { tfm->kern[i] = ReadFixWord(ec, fp,err); if (*err) return NULL; } // Read the extensible character recipies tfm->extensibleRecipe = (TFMextRec *)ppl_memAlloc(tfm->ne*sizeof(TFMextRec)); if (tfm->extensibleRecipe==NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Out of memory"); *err=DVIE_MEMORY; return NULL; } for (i=0; ine; i++) { int j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->extensibleRecipe+i)->top = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->extensibleRecipe+i)->mid = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->extensibleRecipe+i)->bot = j; if ((*err=ReadUChar(ec, fp, &j))!=0) return NULL; (tfm->extensibleRecipe+i)->rep = j; } // We should read in the param aray at this point, but let's see if we can get away without doing so return tfm; } // Read a TFM "fix_word", a signed four-byte int with the dp after 12 bits double ReadFixWord(pplerr_context *ec, FILE *fp, int *err) { double fw; long signed int li; const double twoP20 = 1048576; // 2**20 if ((*err=ReadSignedInt(ec, fp, &li, 4))!=0) return 0.0; fw = (double) li / twoP20; return fw; } // Find the maximum (unscaled) height and depth of (standard) glyphs within a font int dviFindMaxSize(pplerr_context *ec, dviFontDetails *font) { dviTFM *tfm; // Details of this font int hi, di; // Indices int chnum; // Character number in this font TFMcharInfo *chin; // Character info for this character int i, loopMax, hmax, dmax; double height, depth; if (!font) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Internal font failure!"); return DVIE_INTERNAL; } tfm = font->tfm; font->maxHeight = 0.0; font->maxDepth = 0.0; // Loop over upper-case characters loopMax = tfm->ec > ASCII_CHAR_Z_UP ? ASCII_CHAR_Z_UP : tfm->ec; hmax=0; dmax=0; for (i=ASCII_CHAR_A_UP; i<=loopMax; i++) { chnum = i - tfm->bc; chin = tfm->charInfo+chnum; hi = (int)chin->hi; di = (int)chin->di; height = tfm->height[hi]; depth = tfm->depth[di]; if (font->maxHeight < height) { font->maxHeight = height; hmax=i; } if (font->maxDepth < depth ) { font->maxDepth = depth ; dmax=i; } } // Loop over lower-case characters loopMax = tfm->ec > ASCII_CHAR_Z_DN ? ASCII_CHAR_Z_DN : tfm->ec; for (i=ASCII_CHAR_A_DN; i<=loopMax; i++) { chnum = i - tfm->bc; chin = tfm->charInfo+chnum; hi = (int)chin->hi; di = (int)chin->di; height = tfm->height[hi]; depth = tfm->depth[di]; if (font->maxHeight < height) { font->maxHeight = height; hmax=i; } if (font->maxDepth < depth ) { font->maxDepth = depth ; dmax=i; } } font->maxHeight *= font->useSize; font->maxDepth *= font->useSize; if (DEBUG) { sprintf(ec->tempErrStr, "TFM: Maximum height %f depth %f from characters %d %d %s %s", font->maxHeight, font->maxDepth, hmax, dmax, (char *)(&hmax), (char *)(&dmax)); ppl_log(ec, NULL); } return 0; } pyxplot-0.9.2/src/epsMaker/eps_box.c0000664000175000017500000001011112026340554015757 0ustar dcf21dcf21// eps_box.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_box.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_BOX 1 #include #include #include #include "settings/withWords_fns.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_box.h" #include "epsMaker/eps_settings.h" void eps_box_RenderEPS(EPSComm *x) { int lt; unsigned char filled=0, stroked=0; double lw, lw_scale, x1, x2, y1, y2, xo, yo, r; withWords ww; // Print label at top of postscript description of box fprintf(x->epsbuffer, "%% Canvas item %d [box]\n", x->current->id); eps_core_clear(x); // Calculate positions of two opposite corners of box x1 = x->current->xpos * M_TO_PS; // First corner y1 = x->current->ypos * M_TO_PS; x2 = (x->current->xpos2 + x->current->xpos) * M_TO_PS; // Second corner y2 = (x->current->ypos2 + x->current->ypos) * M_TO_PS; r = x->current->rotation; // Expand any numbered styles which may appear in the with words we are passed ppl_withWordsMerge(x->c, &ww, &x->current->with_data, NULL, NULL, NULL, NULL, 1); // Set fill color of box eps_core_SetFillColor(x, &ww); eps_core_SwitchTo_FillColor(x,1); // Work out the origin that we're rotating about if (!x->current->xpos2set) { xo=(x1+x2)/2.0; yo=(y1+y2)/2.0; } // Rotate about centre of box if specified as 'from .... to ....' else { xo=x1; yo=y1; } // Rotate about pinned corner of box is specified as 'at .... width .... height ....' // Apply rotation fprintf(x->epsbuffer, "gsave\n"); fprintf(x->epsbuffer, "%.2f %.2f translate\n", xo, yo); fprintf(x->epsbuffer, "%.2f rotate\n", r*180/M_PI); // Fill box IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nfill\n", x1-xo,y1-yo,x1-xo,y2-yo,x2-xo,y2-yo,x2-xo,y1-yo); filled=1; } // Set color of outline of box eps_core_SetColor(x, &ww, 1); // Set linewidth and linetype of outline if (ww.USElinewidth) lw_scale = ww.linewidth; else lw_scale = x->current->settings.LineWidth; lw = EPS_DEFAULT_LINEWIDTH * lw_scale; if (ww.USElinetype) lt = ww.linetype; else lt = 1; IF_NOT_INVISIBLE eps_core_SetLinewidth(x, lw, lt, 0.0); // Stroke outline of box IF_NOT_INVISIBLE { fprintf(x->epsbuffer, "newpath\n%.2f %.2f moveto\n%.2f %.2f lineto\n%.2f %.2f lineto\n%.2f %.2f lineto\nclosepath\nstroke\n", x1-xo,y1-yo,x1-xo,y2-yo,x2-xo,y2-yo,x2-xo,y1-yo); stroked=1; } // Undo scaling of postscript axes fprintf(x->epsbuffer, "grestore\n"); x->LastLinewidth = -1; x->LastLinetype = -1; x->LastPSColor[0]='\0'; // Factor four corners of box into EPS file's bounding box if (filled || stroked) { eps_core_BoundingBox(x, (x1-xo)*cos(r) - (y1-yo)*sin(r) + xo, (x1-xo)*sin(r) + (y1-yo)*cos(r) + yo, lw); eps_core_BoundingBox(x, (x1-xo)*cos(r) - (y2-yo)*sin(r) + xo, (x1-xo)*sin(r) + (y2-yo)*cos(r) + yo, lw); eps_core_BoundingBox(x, (x2-xo)*cos(r) - (y2-yo)*sin(r) + xo, (x2-xo)*sin(r) + (y2-yo)*cos(r) + yo, lw); eps_core_BoundingBox(x, (x2-xo)*cos(r) - (y1-yo)*sin(r) + xo, (x2-xo)*sin(r) + (y1-yo)*cos(r) + yo, lw); } // Free with words ppl_withWordsDestroy(x->c, &ww); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_filledregion.h0000664000175000017500000000416712026340554020713 0ustar dcf21dcf21// eps_plot_filledregion.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_filledregion.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_FILLEDREGION_H #define _PPL_EPS_PLOT_FILLEDREGION_H 1 #include "epsMaker/eps_comm.h" #include "coreUtils/list.h" #include "settings/settings.h" #define INCOMING 0 #define OUTGOING 1 typedef struct FilledRegionAxisCrossing { double x, y, x2, y2; double AxisPos; listItem *point; unsigned char AxisFace, sense, singleton, used; int id, twin; } FilledRegionAxisCrossing; typedef struct FilledRegionPoint { double x, y, xa, ya, xap, yap; unsigned char inside; int FillSideFlip_prv, FillSideFlip_fwd; } FilledRegionPoint; typedef struct FilledRegionHandle { EPSComm *x; pplset_graph *sg; pplset_axis *xa, *ya, *za; int xrn, yrn, zrn; unsigned char ThreeDim; double origin_x, origin_y, width, height, zdepth; list *points; int Naxiscrossings; double lastx, lasty, lastxap, lastyap; unsigned char first, EverInside; } FilledRegionHandle; FilledRegionHandle *FilledRegion_Init (EPSComm *x, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, unsigned char ThreeDim, double origin_x, double origin_y, double width, double height, double zdepth); void FilledRegion_Point(EPSComm *X, FilledRegionHandle *fr, double x, double y); void FilledRegion_Finish(EPSComm *X, FilledRegionHandle *fr, int linetype, double linewidth, unsigned char StrokeOutline); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_canvas.h0000664000175000017500000000367612026340554017527 0ustar dcf21dcf21// eps_plot_canvas.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_canvas.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Provides routines for mapping between coordinate positions on axes and // positions on a postscript page. Outputs xpos and ypos are measured in // postscript points. #ifndef _PPL_EPS_PLOT_CANVAS_H #define _PPL_EPS_PLOT_CANVAS_H 1 #include #include #include "settings/settings.h" double eps_plot_axis_GetPosition(double xin, pplset_axis *xa, int xrn, unsigned char AllowOffBounds); double eps_plot_axis_InvGetPosition(double xin, pplset_axis *xa); int eps_plot_axis_InRange(pplset_axis *xa, double xin); void eps_plot_ThreeDimProject(double xap, double yap, double zap, pplset_graph *sg, double origin_x, double origin_y, double width, double height, double zdepth, double *xpos, double *ypos, double *depth); void eps_plot_GetPosition(double *xpos, double *ypos, double *depth, double *xap, double *yap, double *zap, double *theta_x, double *theta_y, double *theta_z, unsigned char ThreeDim, double xin, double yin, double zin, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, double origin_x, double origin_y, double width, double height, double zdepth, unsigned char AllowOffBounds); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto.h0000664000175000017500000000212012026340554020713 0ustar dcf21dcf21// eps_plot_ticking_auto.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_TICKING_AUTO_H #define _PPL_EPS_PLOT_TICKING_AUTO_H 1 #include "epsMaker/eps_comm.h" #include "settings/settings.h" void eps_plot_ticking_auto(EPSComm *x, pplset_axis *axis, double UnitMultiplier, unsigned char *AutoTicks, pplset_axis *linkedto); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_canvas.c0000664000175000017500000001574112026340554017516 0ustar dcf21dcf21// eps_plot_canvas.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_canvas.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Provides routines for mapping between coordinate positions on axes and // positions on a postscript page. Outputs xpos and ypos are measured in // postscript points. #define _PPL_EPS_PLOT_CANVAS_C 1 #include #include #include #include #include "settings/settings.h" #include "settings/settingTypes.h" // Where along this axis, in the range 0 (left) to 1 (right) should the value // xin go? xrn = Region Number for interpolated axes which do not have // monotonically increasing ordinate values. double eps_plot_axis_GetPosition(double xin, pplset_axis *xa, int xrn, unsigned char AllowOffBounds) { int imin, imax, i; if (xa==NULL) return xin; if (xa->AxisLinearInterpolation != NULL) // Axis is linearly interpolated { imin = xa->AxisTurnings[xrn ]; imax = xa->AxisTurnings[xrn+1]; for (i=imin; iAxisLinearInterpolation[i] < xin) && (xa->AxisLinearInterpolation[i+1] >= xin)) || ((xa->AxisLinearInterpolation[i] > xin) && (xa->AxisLinearInterpolation[i+1] <= xin)) ) return (i + (xin-xa->AxisLinearInterpolation[i])/(xa->AxisLinearInterpolation[i+1]-xa->AxisLinearInterpolation[i])) / (AXISLINEARINTERPOLATION_NPOINTS-1); } return GSL_NAN; } if (!AllowOffBounds) { if (xa->MaxFinal > xa->MinFinal) { if ((xinMinFinal) || (xin>xa->MaxFinal)) return GSL_NAN; } else { if ((xin>xa->MinFinal) || (xinMaxFinal)) return GSL_NAN; } } if ((xa->LogFinal==SW_BOOL_TRUE) && (xin <= 0)) return GSL_NAN; if (xa->LogFinal!=SW_BOOL_TRUE) return (xin - xa->MinFinal) / (xa->MaxFinal - xa->MinFinal); // Either linear... else return (log(xin)-log(xa->MinFinal)) / (log(xa->MaxFinal)-log(xa->MinFinal)); // ... or logarithmic } // What is the value of this axis at point xin, in the range 0 (left) to 1 (right)? double eps_plot_axis_InvGetPosition(double xin, pplset_axis *xa) { if (xa->AxisLinearInterpolation != NULL) // Axis is linearly interpolated { int i = floor(xin * (AXISLINEARINTERPOLATION_NPOINTS-1)); double x = xin * (AXISLINEARINTERPOLATION_NPOINTS-1) - i; if (i>=AXISLINEARINTERPOLATION_NPOINTS-1) return xa->AxisLinearInterpolation[AXISLINEARINTERPOLATION_NPOINTS-1]; if (i< 0) return xa->AxisLinearInterpolation[0]; return xa->AxisLinearInterpolation[i]*(1-x) + xa->AxisLinearInterpolation[i+1]*x; } if (xa->LogFinal!=SW_BOOL_TRUE) return xa->MinFinal + xin * (xa->MaxFinal - xa->MinFinal); // Either linear... else return xa->MinFinal * pow(xa->MaxFinal / xa->MinFinal , xin); // ... or logarithmic } // Query whether the value xin occurs within the range of this axis int eps_plot_axis_InRange(pplset_axis *xa, double xin) { int xrn, swapI, xminset=0, xmaxset=0; double xmin=0, xmax=0, swapD; if (xa->AxisLinearInterpolation != NULL) { for (xrn=0; xrn<=xa->AxisValueTurnings; xrn++) if (gsl_finite(eps_plot_axis_GetPosition(xin,xa,xrn,0))) return 1; return 0; } if (xa->HardMinSet) { xminset=1; xmin=xa->HardMin; } if (xa->HardMaxSet) { xmaxset=1; xmax=xa->HardMax; } if (xa->HardAutoMinSet) { xminset=0; } if (xa->HardAutoMaxSet) { xmaxset=0; } if (xa->RangeReversed) { swapI=xminset; xminset=xmaxset; xmaxset=swapI; swapD=xmin; xmin=xmax; xmax=swapD; } if (xminset && xmaxset) return (((xin>=xmin)&&(xin<=xmax))||((xin<=xmin)&&(xin>=xmax))); if (xminset ) return (xin>xmin); if (xmaxset ) return (xinXYview.real) + y*sin(sg->XYview.real); y2 =-x*sin(sg->XYview.real) + y*cos(sg->XYview.real); z2 = z; x3 = x2; y3 = y2*cos(sg->YZview.real) - z2*sin(sg->YZview.real); z3 = y2*sin(sg->YZview.real) + z2*cos(sg->YZview.real); *xpos = origin_x + x3; *ypos = origin_y + z3; *depth = y3; return; } void eps_plot_GetPosition(double *xpos, double *ypos, double *depth, double *xap, double *yap, double *zap, double *theta_x, double *theta_y, double *theta_z, unsigned char ThreeDim, double xin, double yin, double zin, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, double origin_x, double origin_y, double width, double height, double zdepth, unsigned char AllowOffBounds) { // Convert (xin,yin,zin) to axis positions on the range of 0-1 *xap = eps_plot_axis_GetPosition(xin, xa, xrn, 1); *yap = eps_plot_axis_GetPosition(yin, ya, yrn, 1); *zap = 0.5; if (ThreeDim) *zap = eps_plot_axis_GetPosition(zin, za, zrn, 1); if ( (!gsl_finite(*xap)) || (!gsl_finite(*yap)) || (!gsl_finite(*zap)) ) { *xpos = *ypos = GSL_NAN; return; } // Apply non-flat projections to (xap,yap,zap) if (sg->projection == SW_PROJ_GNOM) { } // Crop axis positions to range 0-1 if ((!AllowOffBounds) && ((*xap<0.0)||(*xap>1.0)||(*yap<0.0)||(*yap>1.0)||(*zap<0.0)||(*zap>1.0))) { *xpos = *ypos = GSL_NAN; return; } // 3D plots if (ThreeDim) { eps_plot_ThreeDimProject(*xap,*yap,*zap,sg,origin_x,origin_y,width,height,zdepth,xpos,ypos,depth); if (theta_x != NULL) *theta_x = atan2( cos(sg->XYview.real) ,-sin(sg->XYview.real)*sin(sg->YZview.real) ); if (theta_y != NULL) *theta_y = atan2( sin(sg->XYview.real) , cos(sg->XYview.real)*sin(sg->YZview.real) ); if (theta_z != NULL) *theta_z = atan2( 0 , cos(sg->YZview.real) ); if ((theta_x != NULL) && (!gsl_finite(*theta_x))) *theta_x=0.0; if ((theta_y != NULL) && (!gsl_finite(*theta_y))) *theta_y=0.0; if ((theta_z != NULL) && (!gsl_finite(*theta_z))) *theta_z=0.0; } else // 2D plots { *xpos = origin_x + width * (*xap); *ypos = origin_y + height * (*yap); *depth = 0.0; if (theta_x != NULL) *theta_x = M_PI/2; if (theta_y != NULL) *theta_y = 0.0; if (theta_z != NULL) *theta_z = 0.0; } return; } pyxplot-0.9.2/src/epsMaker/eps_circle.h0000664000175000017500000000164712026340554016453 0ustar dcf21dcf21// eps_circle.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_circle.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_CIRCLE_H #define _PPL_EPS_CIRCLE_H 1 #include "epsMaker/eps_comm.h" void eps_circ_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_image.h0000664000175000017500000000164412026340554016271 0ustar dcf21dcf21// eps_image.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_image.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_IMAGE_H #define _PPL_EPS_IMAGE_H 1 #include "epsMaker/eps_comm.h" void eps_image_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_labelsarrows.h0000664000175000017500000000213012026340554020734 0ustar dcf21dcf21// eps_plot_labelsarrows.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_labelsarrows.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_LABELSARROWS_H #define _PPL_EPS_PLOT_LABELSARROWS_H 1 #include "epsMaker/eps_comm.h" void eps_plot_labelsarrows_YieldUpText(EPSComm *x); void eps_plot_labelsarrows(EPSComm *x, double origin_x, double origin_y, double width, double height, double zdepth); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_ticking.h0000664000175000017500000000246312026340554017675 0ustar dcf21dcf21// eps_plot_ticking.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_TICKING_H #define _PPL_EPS_PLOT_TICKING_H 1 #include "epsMaker/eps_comm.h" #include "expressions/expCompile.h" #include "settings/settings.h" #include "userspace/pplObj.h" void eps_plot_ticking(EPSComm *x, pplset_axis *axis, int AxisUnitStyle, pplset_axis *linkedto); void TickLabelAutoGen(EPSComm *X, char **output, double x, double log_base, int OutContext); void TickLabelFromFormat(EPSComm *X, char **output, pplExpr *FormatExp, double x, pplObj *xunit, int xyz, int OutContext); #endif pyxplot-0.9.2/src/epsMaker/eps_image.c0000664000175000017500000003326712026340554016272 0ustar dcf21dcf21// eps_image.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_image.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_IMAGE 1 #include #include #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "settings/settingTypes.h" #include "epsMaker/bmp_a85.h" #include "epsMaker/bmp_bmpread.h" #include "epsMaker/bmp_gifread.h" #include "epsMaker/bmp_image.h" #include "epsMaker/bmp_jpegread.h" #include "epsMaker/bmp_optimise.h" #include "epsMaker/bmp_pngread.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_image.h" #include "epsMaker/eps_settings.h" void eps_image_RenderEPS(EPSComm *x) { bitmap_data data; FILE *infile; int ImageType, i, j; double xscale, yscale, r; double xanchor=0, yanchor=0, xbotleft, ybotleft; unsigned char buff[10], *imagez; char filename[FNAME_LENGTH]; uLongf zlen; // Length of buffer passed to zlib static unsigned char transparency_buff[3]; data.data = data.palette = data.trans = NULL; data.type = 0; data.XDPI = data.YDPI = 180; data.TargetCompression = BMP_ENCODING_FLATE; fprintf(x->epsbuffer, "%% Canvas item %d [bitmap image]\n", x->current->id); // Expand filename if it contains wildcards { wordexp_t wordExp; glob_t globData; char fName[FNAME_LENGTH]; { int j,k; for (j=k=0; ((x->current->text[j]!='\0')&&(kcurrent->text[j]==' ') fName[k++]='\\'; fName[k++]=x->current->text[j++]; } fName[k++]='\0'; } if ((wordexp(fName, &wordExp, 0) != 0) || (wordExp.we_wordc <= 0)) { sprintf(x->c->errcontext.tempErrStr, "Could not open file '%s'.", fName); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); return; } if ((glob(wordExp.we_wordv[0], 0, NULL, &globData) != 0) || (globData.gl_pathc <= 0)) { sprintf(x->c->errcontext.tempErrStr, "Could not open file '%s'.", fName); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); wordfree(&wordExp); return; } wordfree(&wordExp); snprintf(filename, FNAME_LENGTH, "%s", globData.gl_pathv[0]); filename[FNAME_LENGTH-1]='\0'; globfree(&globData); } // Open input data file infile = fopen(filename, "r"); if (infile==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open input file '%s'", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; return; } // Use magic to determine file type for (i=0; i<3; i++) { j = fgetc(infile); if (j==EOF) { sprintf(x->c->errcontext.tempErrStr, "Could not read any image data from the input file '%s'", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; fclose(infile); return; } buff[i] = (unsigned char)j; } if ((buff[0]=='G' )&&(buff[1]=='I' )&&(buff[2]=='F' )) ImageType = SW_BITMAP_GIF; else if ((buff[0]==0xff)&&(buff[1]==0xd8)&&(buff[2]==0xff)) ImageType = SW_BITMAP_JPG; else if ((buff[0]=='B' )&&(buff[1]=='M' ) ) ImageType = SW_BITMAP_BMP; else if ((buff[0]==137 )&&(buff[1]=='P' )&&(buff[2]=='N' )) ImageType = SW_BITMAP_PNG; else { sprintf(x->c->errcontext.tempErrStr, "Could not determine the file type of input file '%s'. The image command only supports bmp, gif, jpeg and png images. The supplied image does not appear to be in any of these formats.", filename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, x->c->errcontext.tempErrStr); *(x->status) = 1; fclose(infile); return; } // Read data from file using appropriate input filter switch (ImageType) { case SW_BITMAP_BMP: ppl_bmp_bmpread (&x->c->errcontext , infile , &data); break; case SW_BITMAP_GIF: ppl_bmp_gifread (&x->c->errcontext , infile , &data); break; case SW_BITMAP_JPG: ppl_bmp_jpegread(&x->c->errcontext , infile , &data); break; case SW_BITMAP_PNG: ppl_bmp_pngread (&x->c->errcontext , infile , &data); break; default: ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Unrecognised image type"); *(x->status) = 1; fclose(infile); return; } fclose(infile); // Check to see whether reading of data failed if (data.data == NULL) { *(x->status) = 1; return; } // Apply palette optimisations to images if possible if ((data.depth == 8) && (data.type==BMP_COLOUR_PALETTE)) ppl_bmp_palette_check(&x->c->errcontext , &data); // If we did not construct palette, check for trailing unused entries if ((data.depth == 24) && (data.type==BMP_COLOUR_BMP )) ppl_bmp_colour_count(&x->c->errcontext , &data); // Check full color image to ensure more than 256 colors if ((data.depth == 8) && (data.type==BMP_COLOUR_PALETTE)) ppl_bmp_grey_check(&x->c->errcontext , &data); // Check paletted images for greyscale conversion if ((data.type == BMP_COLOUR_PALETTE) && (data.pal_len <= 16) && (data.depth == 8)) ppl_bmp_compact(&x->c->errcontext , &data); // Compact images with few palette entries // If user has specified a transparent color, change transparency properties now if (x->current->CustomTransparency) { data.trans = NULL; // Turn off any transparency which may have been present in the original image if (data.colour == BMP_COLOUR_PALETTE) { for(i=0; icurrent->TransColR == data.palette[3*i ]) && ((unsigned char)x->current->TransColG == data.palette[3*i+1]) && ((unsigned char)x->current->TransColB == data.palette[3*i+2]) ) { data.trans = transparency_buff; *data.trans = (unsigned char)i; break; } } else if (data.colour == BMP_COLOUR_RGB) // RGB { data.trans = transparency_buff; data.trans[0] = (unsigned char)x->current->TransColR; data.trans[1] = (unsigned char)x->current->TransColG; data.trans[2] = (unsigned char)x->current->TransColB; } else if ((data.colour == BMP_COLOUR_GREY) && (x->current->TransColR==x->current->TransColG) && (x->current->TransColR==x->current->TransColB)) // Greyscale { int magic; if (data.depth == 1) { magic=255 ; } // 2-color greyscale else if (data.depth == 2) { magic=255/ 3; } // 4-color greyscale else if (data.depth == 4) { magic=255/15; } // 16-color greyscale else { magic= 1 ; } // 256-color greyscale if ((x->current->TransColR % magic)==0) { data.trans = transparency_buff; data.trans[0] = (unsigned char)(x->current->TransColR / magic); } } } #ifdef FLATE_DISABLE if (data.TargetCompression==BMP_ENCODING_FLATE) data.TargetCompression=BMP_ENCODING_NULL; #endif // Apply compression to image data switch (data.TargetCompression) { case BMP_ENCODING_NULL: break; // No image compression case BMP_ENCODING_DCT: break; // Special case: JPEG data is encoded in DCT, but is already supplied from ppl_bmp_jpegread() in encoded form case BMP_ENCODING_FLATE: zlen = data.data_len*1.01+12; // Nasty guess at size of buffer needed. imagez = (unsigned char *)ppl_memAlloc(zlen); if (imagez == NULL) { ppl_error(&x->c->errcontext, ERR_MEMORY, -1, -1,"Out of memory"); return; } if (DEBUG) { ppl_log(&x->c->errcontext, "Calling zlib to compress image data"); } j = compress2(imagez,&zlen,data.data,data.data_len,9); // Call zlib to do deflation if (j!=0) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "zlib returned error code %d\n",j); ppl_log(&x->c->errcontext, NULL); } data.TargetCompression = BMP_ENCODING_NULL; // Give up trying to compress data break; } if (DEBUG) { sprintf(x->c->errcontext.tempErrStr, "zlib has completed compression. Before flate: %ld bytes. After flate: %ld bytes", data.data_len, (long)zlen); ppl_log(&x->c->errcontext, NULL); } if (zlen >= data.data_len) { if (DEBUG) { ppl_log(&x->c->errcontext, "Using original uncompressed data since zlib made it bigger than it was to start with"); } data.TargetCompression = BMP_ENCODING_NULL; // Give up trying to compress data; result was larger than original data size break; } data.data = imagez; // Replace old data with new compressed data data.data_len = zlen; break; default: ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Unrecognised image compression type requested"); *(x->status) = 1; return; } // Work out dimensions of image if ((x->current->xpos2set) && (x->current->ypos2set)) // Both width and height have been specified { xscale = x->current->xpos2 * M_TO_PS; yscale = x->current->ypos2 * M_TO_PS; } else if (x->current->xpos2set) // Only width has been set { xscale = x->current->xpos2 * M_TO_PS; yscale = x->current->xpos2 * M_TO_PS * ((double)data.height / (double)data.width); } else if (x->current->ypos2set) // Only height has been set { xscale = x->current->ypos2 * M_TO_PS * ((double)data.width / (double)data.height); yscale = x->current->ypos2 * M_TO_PS; } else // Neither height nor width has been set; use DPI information to work out how big image should be { xscale = ((double)data.width ) / data.XDPI * 72; yscale = ((double)data.height) / data.YDPI * 72; } // Work out position of bottom-left corner r = x->current->rotation; if (x->current->settings.TextHAlign == SW_HALIGN_LEFT ) xanchor = 0; else if (x->current->settings.TextHAlign == SW_HALIGN_CENT ) xanchor = (xscale)/2; else if (x->current->settings.TextHAlign == SW_HALIGN_RIGHT) xanchor = (xscale); if (x->current->settings.TextVAlign == SW_VALIGN_TOP ) yanchor = (yscale); else if (x->current->settings.TextVAlign == SW_VALIGN_CENT ) yanchor = (yscale)/2; else if (x->current->settings.TextVAlign == SW_VALIGN_BOT ) yanchor = 0; xbotleft = x->current->xpos*M_TO_PS-(xanchor*cos(r)-yanchor*sin(r)); ybotleft = x->current->ypos*M_TO_PS-(xanchor*sin(r)+yanchor*cos(r)); // Make it into postscript fprintf(x->epsbuffer, "gsave\n"); fprintf(x->epsbuffer, "%.2f %.2f translate\n", xbotleft, ybotleft); fprintf(x->epsbuffer, "%.2f rotate\n", x->current->rotation * 180 / M_PI); fprintf(x->epsbuffer, "%.2f %.2f scale\n", xscale, yscale); // We render image onto a unit square; use scale to make it the size we actually want if (data.colour == BMP_COLOUR_RGB ) fprintf(x->epsbuffer, "/DeviceRGB setcolorspace\n"); // RGB palette else if (data.colour == BMP_COLOUR_GREY) fprintf(x->epsbuffer, "/DeviceGray setcolorspace\n"); // Greyscale palette else if (data.colour == BMP_COLOUR_PALETTE) // Indexed palette { fprintf(x->epsbuffer, "[/Indexed /DeviceRGB %d <~\n", data.pal_len-1); ppl_bmp_A85(&x->c->errcontext, x->epsbuffer, data.palette, 3*data.pal_len); fprintf(x->epsbuffer, "] setcolorspace\n\n"); } fprintf(x->epsbuffer, "<<\n /ImageType %d\n /Width %d\n /Height %d\n /ImageMatrix [%d 0 0 %d 0 %d]\n", ((!x->current->NoTransparency) && (data.trans!=NULL))?4:1, data.width, data.height, data.width, -data.height, data.height); fprintf(x->epsbuffer, " /DataSource currentfile /ASCII85Decode filter"); // Image data is stored in currentfile, but need to apply filters to decode it if (data.TargetCompression == BMP_ENCODING_DCT ) fprintf(x->epsbuffer, " /DCTDecode filter"); else if (data.TargetCompression == BMP_ENCODING_FLATE) fprintf(x->epsbuffer, " /FlateDecode filter"); fprintf(x->epsbuffer, "\n /BitsPerComponent %d\n /Decode [0 %d%s]\n", (data.colour==BMP_COLOUR_RGB)?(data.depth/3):(data.depth), (data.type==BMP_COLOUR_PALETTE)?((1<current->NoTransparency) && (data.trans != NULL)) // If image has transparency, set mask color { fprintf(x->epsbuffer," /MaskColor ["); if (data.colour == BMP_COLOUR_RGB) fprintf(x->epsbuffer, "%d %d %d]\n",(int)data.trans[0], (int)data.trans[1], (int)data.trans[2]); else fprintf(x->epsbuffer, "%d]\n" ,(int)data.trans[0]); } if (x->current->smooth) fprintf(x->epsbuffer, " /Interpolate true\n"); // If image has smooth flag set, tell postscript interpretter to interpolate image fprintf(x->epsbuffer, ">> image\n"); ppl_bmp_A85(&x->c->errcontext, x->epsbuffer, data.data, data.data_len); fprintf(x->epsbuffer, "grestore\n"); // Update postscript bounding box eps_core_BoundingBox(x, xbotleft , ybotleft , 0); eps_core_BoundingBox(x, xbotleft + xscale*cos(r) , ybotleft + xscale*sin(r) , 0); eps_core_BoundingBox(x, xbotleft + yscale*-sin(r) , ybotleft + yscale*cos(r) , 0); eps_core_BoundingBox(x, xbotleft + xscale*cos(r) + yscale*-sin(r) , ybotleft + xscale*sin(r) + yscale*cos(r) , 0); // Final newline at end of canvas item fprintf(x->epsbuffer, "\n"); return; } pyxplot-0.9.2/src/epsMaker/eps_plot_legend.h0000664000175000017500000000434012026340554017477 0ustar dcf21dcf21// eps_plot_legend.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_legend.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_LEGEND_H #define _PPL_EPS_PLOT_LEGEND_H 1 #include "epsMaker/eps_comm.h" #include "epsMaker/eps_settings.h" #define AB_ENLARGE_FACTOR 2.5 #define BB_ENLARGE_FACTOR 1.4 #define MARGIN_HSIZE (0.012*M_TO_PS) #define MARGIN_HSIZE_LEFT (0.009*M_TO_PS) #define LEGEND_HGAP_MAXIMUM (0.006*M_TO_PS) #define LEGEND_VGAP_MAXIMUM (0.003*M_TO_PS) #define LEGEND_MARGIN (0.002*M_TO_PS) #define MAX_LEGEND_COLUMNS 1024 // Adds all of the text items which will be needed to render this plot to the // list x->TextItems. It is vital that they be added in the exact order in // which they will be rendered. #define YIELD_TEXTITEM(X) \ if ((X != NULL) && (X[0]!='\0')) \ { \ CanvasTextItem *i; \ i = (CanvasTextItem *)ppl_memAlloc(sizeof(CanvasTextItem)); \ if (i==NULL) { ppl_error(&x->c->errcontext, ERR_MEMORY, -1, -1, "Out of memory (q)."); *(x->status) = 1; return; } \ i->text = X; \ i->CanvasMultiplotID = x->current->id; \ ppl_listAppend(x->TextItems, i); \ x->NTextItems++; \ } #define YIELD_TEXTITEM_CPY(X) \ { \ char *out = (char *)ppl_memAlloc(strlen(X)+1); \ if (out==NULL) { ppl_error(&x->c->errcontext, ERR_MEMORY, -1, -1, "Out of memory (r)."); *(x->status) = 1; return; } \ strcpy(out, (X)); \ YIELD_TEXTITEM(out); \ } void GraphLegend_YieldUpText(EPSComm *x); void GraphLegend_Render(EPSComm *x, double width, double height, double zdepth); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_ticking_auto3.h0000664000175000017500000000212512026340554021003 0ustar dcf21dcf21// eps_plot_ticking_auto3.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_ticking_auto3.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_TICKING_AUTO3_H #define _PPL_EPS_PLOT_TICKING_AUTO3_H 1 #include "epsMaker/eps_comm.h" #include "settings/settings.h" void eps_plot_ticking_auto3(EPSComm *x, pplset_axis *axis, double UnitMultiplier, unsigned char *AutoTicks, pplset_axis *linkedto); #endif pyxplot-0.9.2/src/epsMaker/eps_text.h0000664000175000017500000000170612026340554016172 0ustar dcf21dcf21// eps_text.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_text.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_TEXT_H #define _PPL_EPS_TEXT_H 1 #include "epsMaker/eps_comm.h" void eps_text_YieldUpText(EPSComm *x); void eps_text_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/canvasDraw.h0000664000175000017500000000261512026340554016430 0ustar dcf21dcf21// canvasDraw.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: canvasDraw.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CANVASDRAW_H #define _CANVASDRAW_H 1 #include "epsMaker/eps_comm.h" #include "userspace/context.h" void ppl_canvas_draw(ppl_context *c, unsigned char *unsuccessful_ops, int iterDepth); void canvas_CallLaTeX(EPSComm *x); void canvas_MakeEPSBuffer(EPSComm *x); void canvas_EPSWrite(EPSComm *x); void canvas_EPSRenderTextItem(EPSComm *x, char **strout, int pageno, double xpos, double ypos, int halign, int valign, char *colstr, double fontsize, double rotate, double *width, double *height); void canvas_EPSLandscapify(EPSComm *x, char *transform); void canvas_EPSEnlarge(EPSComm *x, char *transform); #endif pyxplot-0.9.2/src/epsMaker/canvasDraw.c0000664000175000017500000014414712026340554016432 0ustar dcf21dcf21// canvasDraw.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: canvasDraw.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CANVASDRAW_C 1 #include #include #include #include #include #include #include #include #include #include #include #include "coreUtils/backup.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/dvi_read.h" #include "epsMaker/eps_arrow.h" #include "epsMaker/eps_box.h" #include "epsMaker/eps_circle.h" #include "epsMaker/eps_ellipse.h" #include "epsMaker/eps_eps.h" #include "epsMaker/eps_image.h" #include "epsMaker/eps_piechart.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_threedimbuff.h" #include "epsMaker/eps_point.h" #include "epsMaker/eps_polygon.h" #include "epsMaker/eps_text.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_settings.h" #include "userspace/context.h" #include "canvasItems.h" #include "children.h" #include "datafile.h" // Handy routine for copying files static int filecopy(EPSComm *x, const char *in, const char *out) { int status=0, n; FILE *fi, *fo; ppl_createBackupIfRequired(x->c, out); fi = fopen(in, "rb"); fo = fopen(out, "wb"); if ((fo==NULL)||(fi==NULL)) status=1; while ((!status) && ((n=fread((void *)x->c->errcontext.tempErrStr, 1, FNAME_LENGTH, fi)) > 0)) if (fwrite((void *)x->c->errcontext.tempErrStr, 1, n, fo) < n) status=1; if (fi != NULL) fclose(fi); if (fo != NULL) fclose(fo); return status; } // Run ghostscript to convert postscript output into bitmap graphics #define BITMAP_TERMINAL_CLEANUP(X, Y, CanInvert) \ if (system(c->errcontext.tempErrStr) != 0) /* Run ghostscript */ \ { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Error encountered whilst using " X " to generate " Y " output"); } \ else \ { \ char *src = GSOutputTemp; \ if ((CanInvert) && (c->set->term_current.TermInvert==SW_ONOFF_ON)) \ { \ sprintf(c->errcontext.tempErrStr, "%s %s -negate %s", CONVERT_COMMAND, GSOutputTemp, GSOutputTemp2); \ if (system(c->errcontext.tempErrStr) != 0) /* Run convert to negate image */ \ { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Error encountered whilst using ImageMagick to generate negated " Y " output"); } \ src = GSOutputTemp2; \ remove(GSOutputTemp); \ } \ if (filecopy(&comm, src, comm.FinalFilename) != 0) /* Move ghostscript output to desire target file */ \ { sprintf(c->errcontext.tempErrStr, "Could not write output to file '%s'", comm.FinalFilename); ppl_error(&c->errcontext, ERR_FILE, -1, -1, NULL); } \ remove(src); /* Delete temporary files */ \ } \ remove(comm.EPSFilename); // Standard postscript prolog text for EPS and PS files static char *EPS_PROLOG_TEXT = "\ /BeginEPSF { %def % Prepare for EPS file\n\ /b4_Inc_state save def % Save state for cleanup\n\ /dict_count countdictstack def % Count objects on dict stack\n\ /op_count count 1 sub def % Count objects on operand stack\n\ userdict begin % Push userdict on dict stack\n\ /showpage { } def % Redefine showpage, { } = null proc\n\ 0 setgray 0 setlinecap 1 setlinewidth 0 setlinejoin % Prepare graphics state\n\ 10 setmiterlimit [ ] 0 setdash newpath\n\ /languagelevel where % If level not equal to 1 then set strokeadjust and overprint to their defaults.\n\ {pop languagelevel\n\ 1 ne\n\ {false setstrokeadjust false setoverprint\n\ } if\n\ } if\n\ } bind def\n\ \n\ /EndEPSF { %def % Clean up after including an EPS file\n\ count op_count sub {pop} repeat % Clean up stacks\n\ countdictstack dict_count sub {end} repeat\n\ b4_Inc_state restore\n\ } bind def\n\ "; static char *PS_PROLOG_TEXT = "\ "; // Standard command-line flags to pass to ghostscript static char *GHOSTSCRIPT_STANDARD_FLAGS = "-dQUIET -dSAFER -P- -dBATCH -dNOPAUSE -dEPSCrop"; // Table of the functions we call for each phase of the canvas drawing process for different object types static void(*ArrowHandlers[])(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_arrow_RenderEPS, NULL}; static void(*BoxHandlers[] )(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_box_RenderEPS , NULL}; static void(*CircHandlers[] )(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_circ_RenderEPS , NULL}; static void(*EllpsHandlers[])(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_ellps_RenderEPS, NULL}; static void(*EPSHandlers[] )(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_eps_RenderEPS , NULL}; static void(*ImageHandlers[])(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_image_RenderEPS, NULL}; static void(*PieHandlers[] )(EPSComm *) = {eps_pie_ReadAccessibleData , NULL , NULL , eps_pie_YieldUpText , NULL , eps_pie_RenderEPS , NULL}; static void(*PlotHandlers[] )(EPSComm *) = {eps_plot_ReadAccessibleData, eps_plot_SampleFunctions, eps_plot_DecideAxisRanges, eps_plot_YieldUpText, NULL , eps_plot_RenderEPS , NULL}; static void(*PointHandlers[])(EPSComm *) = {NULL , NULL , NULL , eps_point_YieldUpText,NULL , eps_point_RenderEPS, NULL}; static void(*PolygHandlers[])(EPSComm *) = {NULL , NULL , NULL , NULL , NULL , eps_polygon_RenderEPS,NULL}; static void(*TextHandlers[] )(EPSComm *) = {NULL , NULL , NULL , eps_text_YieldUpText, NULL , eps_text_RenderEPS , NULL}; static void(*AfterHandlers[])(EPSComm *) = {NULL , NULL , NULL , canvas_CallLaTeX , canvas_MakeEPSBuffer, canvas_EPSWrite , NULL}; void ppl_canvas_draw(ppl_context *c, unsigned char *unsuccessful_ops, int iterDepth) { static int lock=0; int i, j, termtype, status=0, CSPCommand=0; static long TempFile_counter=0, TeXFile_counter=0; char EPSFilenameTemp[FNAME_LENGTH], TeXFilenameTemp[FNAME_LENGTH], TitleTemp[FNAME_LENGTH], FinalFilenameTemp[FNAME_LENGTH]; char GSOutputTemp[FNAME_LENGTH], GSOutputTemp2[FNAME_LENGTH]; wordexp_t WordExp; char *EnvDisplay; EPSComm comm; canvas_item *item; void(*ArrowHandler)(EPSComm *); void(*BoxHandler )(EPSComm *); void(*CircHandler )(EPSComm *); void(*EllpsHandler)(EPSComm *); void(*EPSHandler )(EPSComm *); void(*ImageHandler)(EPSComm *); void(*PieHandler )(EPSComm *); void(*PlotHandler )(EPSComm *); void(*PointHandler)(EPSComm *); void(*PolygHandler)(EPSComm *); void(*TextHandler )(EPSComm *); void(*AfterHandler)(EPSComm *); // Try to get lock if (__sync_add_and_fetch(&lock,1) > 1) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Recursive call to the plot command detected."); return; } // Reset 3D rendering buffer comm.iterDepth = iterDepth; comm.c = c; ThreeDimBuffer_Reset(&comm); // By default, we record all operations as having been successful for (i=0;iset->term_current.TermType; comm.FinalFilename = c->set->term_current.output; // The final filename of whatever kind of output we're planning to produce if ((comm.FinalFilename==NULL)||(comm.FinalFilename[0]=='\0')) { comm.FinalFilename = FinalFilenameTemp; // If final target filename is blank, use pyxplot. sprintf(FinalFilenameTemp, "pyxplot.%s", *(char **)ppl_fetchSettingName(&c->errcontext, termtype, SW_TERMTYPE_INT, (void *)SW_TERMTYPE_STR, sizeof(char *))); } // Perform expansion of shell filename shortcuts such as ~ if ((wordexp(comm.FinalFilename, &WordExp, 0) != 0) || (WordExp.we_wordc <= 0)) { sprintf(c->errcontext.tempErrStr, "Could not find directory containing filename '%s'.", comm.FinalFilename); ppl_error(&c->errcontext, ERR_FILE, -1, -1, NULL); lock=0; return; } if (WordExp.we_wordc > 1) { sprintf(c->errcontext.tempErrStr, "Filename '%s' is ambiguous.", comm.FinalFilename); ppl_error(&c->errcontext, ERR_FILE, -1, -1, NULL); lock=0; return; } strcpy(FinalFilenameTemp, WordExp.we_wordv[0]); wordfree(&WordExp); comm.FinalFilename = FinalFilenameTemp; // Create filename for temporary LaTeX document comm.TeXFilename = TeXFilenameTemp; TeXFile_counter++; sprintf(TeXFilenameTemp, "%s%spyxplot_%d_%ld", c->errcontext.session_default.tempdir, PATHLINK, getpid(), TempFile_counter); // Case 1: EPS and PS terminals. Postscript output will be saved immediately in situ. if ((termtype == SW_TERMTYPE_EPS) || (termtype == SW_TERMTYPE_PS)) { comm.EPSFilename = comm.FinalFilename; // eps or ps is actually what we're aiming to make, so save straight to user's chosen target ppl_createBackupIfRequired(c, comm.EPSFilename); comm.title = comm.EPSFilename; // Filename 'foo/bar/myplot.eps' --> title 'myplot.eps' for (i=0; comm.title[i]!='\0'; i++) if ((comm.title[i]==PATHLINK[0])&&((i==0)||(comm.title[i-1]!='\\'))) { comm.title += i+1; i=-1; } } else // Case 2: All other terminals. Create a temporary eps file for subsequent processing. { comm.EPSFilename = EPSFilenameTemp; TempFile_counter++; sprintf(EPSFilenameTemp, "%s%spyxplot_%d_%ld.eps", c->errcontext.session_default.tempdir, PATHLINK, getpid(), TempFile_counter); if ((termtype==SW_TERMTYPE_X11S) || (termtype==SW_TERMTYPE_X11M) || (termtype==SW_TERMTYPE_X11P)) { comm.title = TitleTemp; // In X11 terminals, we give eps files numbered titles sprintf(TitleTemp, "Pyxplot Output %ld", TempFile_counter); } else { comm.title = comm.FinalFilename; // In other terminals, we give eps files filename titles, with path cut off front for (i=0; comm.title[i]!='\0'; i++) if ((comm.title[i]==PATHLINK[0])&&((i==0)||(comm.title[i-1]!='\\'))) { comm.title += i; i=0; } } } // Make GSOutputTemp a temporary file that ghostscript can spit data out to (with a shell-safe filename) sprintf(GSOutputTemp , "%s%spyxplot_%d_%ld%s", c->errcontext.session_default.tempdir, PATHLINK, getpid(), TempFile_counter, (termtype==SW_TERMTYPE_GIF)?".gif":".tmp"); sprintf(GSOutputTemp2, "%s%spyxplot_%d_%ld_%s", c->errcontext.session_default.tempdir, PATHLINK, getpid(), TempFile_counter, (termtype==SW_TERMTYPE_GIF)?".gif":".tmp"); // Set up communications data structure for objects we are rendering comm.itemlist = (canvas_itemlist *)c->canvas_items; comm.bb_left = comm.bb_right = comm.bb_top = comm.bb_bottom = 0.0; comm.bb_set = 0; comm.epsbuffer = NULL; comm.status = &status; comm.NTextItems = 0; // Used to count items as we add them to text buffer comm.TextItems = ppl_listInit(0); // Empty list of pieces of text we are going to put on canvas comm.LastPSColor[0] = '\0'; comm.CurrentColor[0] = '\0'; comm.CurrentFillColor[0] = '\0'; comm.LastLinewidth = -1.0; comm.LastLinetype = 0; comm.LaTeXpageno = 0; // Used to count items off as we render them to postscript comm.dvi = NULL; for (i=0; ifirst; item!=NULL; item=item->next) { item->PlotLeftMargin = 0.0; item->PlotRightMargin = 0.0; item->PlotTopMargin = 0.0; item->PlotBottomMargin = 0.0; } // Rendering of EPS occurs in a series of phases which we now loop over for (j=0 ; ; j++) { ArrowHandler = ArrowHandlers[j]; // Each object type has a handler for each phase of postscript generation BoxHandler = BoxHandlers [j]; CircHandler = CircHandlers [j]; EllpsHandler = EllpsHandlers[j]; EPSHandler = EPSHandlers [j]; ImageHandler = ImageHandlers[j]; PlotHandler = PlotHandlers [j]; PieHandler = PieHandlers [j]; PointHandler = PointHandlers[j]; PolygHandler = PolygHandlers[j]; TextHandler = TextHandlers [j]; AfterHandler = AfterHandlers[j]; if ((j>4)&&(ArrowHandler==NULL)&&(CircHandler==NULL)&&(EllpsHandler==NULL)&&(EPSHandler==NULL)&&(ImageHandler==NULL)&&(PieHandler==NULL)&&(PlotHandler==NULL)&&(PointHandler==NULL)&&(PolygHandler==NULL)&&(TextHandler==NULL)&&(AfterHandler==NULL)) break; // Loop over all of the items on the canvas if (comm.itemlist != NULL) for (item=comm.itemlist->first; item!=NULL; item=item->next) { if (item->deleted) continue; // ... except those which have been deleted if (unsuccessful_ops[item->id]) continue; // ... or which have already failed comm.LastPSColor[0] = '\0'; // Make each item produce free-standing postscript for easy editing comm.CurrentColor[0] = '\0'; comm.CurrentFillColor[0] = '\0'; comm.LastLinewidth = -1.0; comm.LastLinetype = 0; comm.current = item; if ((item->type == CANVAS_ARROW ) && (ArrowHandler != NULL)) (*ArrowHandler)(&comm); // Call the relevant handler for each one else if ((item->type == CANVAS_BOX ) && (BoxHandler != NULL)) (*BoxHandler )(&comm); else if ((item->type == CANVAS_CIRC ) && (CircHandler != NULL)) (*CircHandler )(&comm); else if ((item->type == CANVAS_ELLPS ) && (EllpsHandler != NULL)) (*EllpsHandler)(&comm); else if ((item->type == CANVAS_EPS ) && (EPSHandler != NULL)) (*EPSHandler )(&comm); else if ((item->type == CANVAS_IMAGE ) && (ImageHandler != NULL)) (*ImageHandler)(&comm); else if ((item->type == CANVAS_PIE ) && (PieHandler != NULL)) (*PieHandler )(&comm); else if ((item->type == CANVAS_PLOT ) && (PlotHandler != NULL)) (*PlotHandler )(&comm); else if ((item->type == CANVAS_POINT ) && (PointHandler != NULL)) (*PointHandler)(&comm); else if ((item->type == CANVAS_POLYGON) && (PolygHandler != NULL)) (*PolygHandler)(&comm); else if ((item->type == CANVAS_TEXT ) && (TextHandler != NULL)) (*TextHandler )(&comm); if (status) { unsuccessful_ops[item->id] = 1; } // If something went wrong... flag it up and give up on this object status = 0; } if (AfterHandler != NULL) (*AfterHandler)(&comm); // At the end of each phase, a canvas-wide handler may be called if (status) { if (comm.epsbuffer!=NULL) fclose(comm.epsbuffer); lock=0; return; } // The failure of a canvas-wide handler is fatal } // Now convert eps output to bitmaped graphics if requested if ((termtype==SW_TERMTYPE_X11S) || (termtype==SW_TERMTYPE_X11M) || (termtype==SW_TERMTYPE_X11P)) // X11 terminals { EnvDisplay = getenv("DISPLAY"); // Check whether the environment variable DISPLAY is set if (c->set->term_current.viewer==SW_VIEWER_NULL) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "An attempt is being made to use an X11 terminal for output, but the required package 'ghostview' could not be found when Pyxplot was installed. If you have recently install ghostview, please reconfigure and recompile Pyxplot."); } else if ((EnvDisplay==NULL) || (EnvDisplay[0]=='\0')) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "An attempt is being made to use an X11 terminal for output, but your DISPLAY environment variable is not set; there is no accessible X11 display."); } else { if (!c->willBeInteractive) { if (termtype!=SW_TERMTYPE_X11P) { sprintf(c->errcontext.tempErrStr, "An attempt is being made to use the %s terminal in a non-interactive Pyxplot session. This won't work, as the window will close as soon as Pyxplot exits. Reverting to the X11_persist terminal instead.", *(char **)ppl_fetchSettingName(&c->errcontext, termtype, SW_TERMTYPE_INT, (void *)SW_TERMTYPE_STR, sizeof(char *))); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); } CSPCommand = 2; } else { if (termtype==SW_TERMTYPE_X11S) CSPCommand = 0; else if (termtype==SW_TERMTYPE_X11M) CSPCommand = 1; else if (termtype==SW_TERMTYPE_X11P) CSPCommand = 2; } if (c->set->term_current.viewer==SW_VIEWER_GV) sprintf(c->errcontext.tempErrStr, "%d%s %swatch %s\n", CSPCommand, GHOSTVIEW_COMMAND, GHOSTVIEW_OPT, comm.EPSFilename); else if (c->set->term_current.viewer==SW_VIEWER_GGV) sprintf(c->errcontext.tempErrStr, "%d%s --watch %s\n", CSPCommand, GGV_COMMAND, comm.EPSFilename); else sprintf(c->errcontext.tempErrStr, "%d%s %s\n", CSPCommand, c->set->term_current.ViewerCmd, comm.EPSFilename); pplcsp_sendCommand(c, c->errcontext.tempErrStr); // Pause after launching an X11 ghostview viewer to give stderr error messages a moment to come back to us for (i=0;i<7;i++) { struct timespec waitperiod, waitedperiod; waitperiod.tv_sec = 0; waitperiod.tv_nsec = 40000000; nanosleep(&waitperiod,&waitedperiod); } } } else if (termtype==SW_TERMTYPE_PDF) // PDF terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=pdfwrite -sOutputFile=%s %s", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "pdf", 0); } else if (termtype==SW_TERMTYPE_PNG) // PNG terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=%s -r%d %s -sOutputFile=%s %s", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, (c->set->term_current.TermTransparent==SW_ONOFF_ON)?"pngalpha":"png16m", (int)floor(c->set->term_current.dpi), (c->set->term_current.TermAntiAlias==SW_ONOFF_ON)?"-dGraphicsAlphaBits=4 -dTextAlphaBits=4":"-dGraphicsAlphaBits=0 -dTextAlphaBits=0", GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "png", 1) } else if (termtype==SW_TERMTYPE_JPG) // JPEG terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=jpeg -dJPEGQ=100 -r%d %s -sOutputFile=%s %s", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, (int)floor(c->set->term_current.dpi), (c->set->term_current.TermAntiAlias==SW_ONOFF_ON)?"-dGraphicsAlphaBits=4 -dTextAlphaBits=4":"-dGraphicsAlphaBits=0 -dTextAlphaBits=0", GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "jpeg", 1) } else if (termtype==SW_TERMTYPE_GIF) // GIF terminal { sprintf(c->errcontext.tempErrStr, "%s -density %d %s %s %s %s", CONVERT_COMMAND, (int)floor(c->set->term_current.dpi), (c->set->term_current.TermTransparent==SW_ONOFF_ON)?"-alpha activate":"-alpha deactivate", (c->set->term_current.TermAntiAlias==SW_ONOFF_ON)?"-antialias":"+antialias", comm.EPSFilename, GSOutputTemp); BITMAP_TERMINAL_CLEANUP("ImageMagick", "gif", 1); } else if (termtype==SW_TERMTYPE_BMP) // BMP terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=bmp16m -r%d %s -sOutputFile=%s %s", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, (int)floor(c->set->term_current.dpi), (c->set->term_current.TermAntiAlias==SW_ONOFF_ON)?"-dGraphicsAlphaBits=4 -dTextAlphaBits=4":"-dGraphicsAlphaBits=0 -dTextAlphaBits=0", GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "bmp", 1) } else if (termtype==SW_TERMTYPE_TIF) // TIF terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=tiff24nc -r%d %s -sOutputFile=%s %s", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, (int)floor(c->set->term_current.dpi), (c->set->term_current.TermAntiAlias==SW_ONOFF_ON)?"-dGraphicsAlphaBits=4 -dTextAlphaBits=4":"-dGraphicsAlphaBits=0 -dTextAlphaBits=0", GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "tif", 1) } else if (termtype==SW_TERMTYPE_SVG) // SVG terminal { sprintf(c->errcontext.tempErrStr, "%s %s -sDEVICE=svg -sOutputFile=%s %s > /dev/null 2> /dev/null", GHOSTSCRIPT_COMMAND, GHOSTSCRIPT_STANDARD_FLAGS, GSOutputTemp, comm.EPSFilename); BITMAP_TERMINAL_CLEANUP("ghostscript", "svg", 0) } // Return to user's current working directory if (chdir(c->errcontext.session_default.cwd) < 0) { ppl_fatal(&c->errcontext, __FILE__,__LINE__,"chdir into cwd failed."); } lock=0; return; } // Run LaTeX to turn set of strings for typesetting into eps code #define FPRINTF_LINECOUNT( X ) \ fprintf(output, "%s", X); \ for (i=0; X[i]!='\0'; i++) if (X[i]=='\n') linecount++; void canvas_CallLaTeX(EPSComm *x) { int linecount=1, i, j, pid, LatexStatus, LatexStdIn, LatexOut; char filename[FNAME_LENGTH], *str_buffer; FILE *output; listIterator *ListIter; CanvasTextItem *TempTextItem, *SuspectTextItem=NULL; struct timespec waitperiod; // A time.h timespec specifier for a wait of zero seconds unsigned char FirstIter; fd_set readable; sigset_t sigs; int ErrLineNo=0, ErrReadState=0, ErrReadPos=0, NCharsRead=0, ReadErrorState=0, TrialNumber; char ErrFilename[FNAME_LENGTH]="", ErrMsg[FNAME_LENGTH]=""; char TempErrFilename[FNAME_LENGTH], TempErrLineNo[FNAME_LENGTH], TempErrMsg[FNAME_LENGTH]; if (ppl_listLen(x->TextItems) < 1) return; // We have no text to give to latex, and so don't need to fork sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); const char TextHeader1[] = "\\documentclass{article}\n\\pagestyle{empty}\n\\usepackage{upgreek}\n"; const char TextHeader2[] = "\\begin{document}\n\\begin{center}{\\bf This page has been left deliberately blank.}\\end{center}\n\\newpage\n"; const char ItemHeader [] = "\\vbox{\\hbox{\n"; const char ItemFooter [] = "\n\\hskip 0pt plus 1filll minus 1filll}\n\\vskip 0pt plus 1filll minus 1filll}\n\\newpage\n"; const char TextFooter [] = "\\end{document}\n"; // chdir into temporary directory so that LaTeX's mess goes into /tmp if (chdir(x->c->errcontext.session_default.tempdir) < 0) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1,"Could not chdir into temporary directory."); *(x->status)=1; return; } // Make string buffer str_buffer = (char *)ppl_memAlloc(LSTR_LENGTH); if (str_buffer==NULL) { ppl_error(&x->c->errcontext, ERR_MEMORY,-1,-1,"Out of memory (y)."); return; } // Start writing LaTeX document sprintf(filename, "%s.tex", x->TeXFilename); output = fopen(filename, "w"); if (output == NULL) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Could not create temporary LaTeX document"); *(x->status)=1; return; } FPRINTF_LINECOUNT(TextHeader1); FPRINTF_LINECOUNT(x->c->set->term_current.LatexPreamble); FPRINTF_LINECOUNT(TextHeader2); // Sequentially print out text strings ListIter = ppl_listIterateInit(x->TextItems); while (ListIter != NULL) { TempTextItem = (CanvasTextItem *)ListIter->data; TempTextItem->LaTeXstartline = linecount; FPRINTF_LINECOUNT(ItemHeader); FPRINTF_LINECOUNT(TempTextItem->text); FPRINTF_LINECOUNT(ItemFooter); TempTextItem->LaTeXendline = linecount; ppl_listIterate(&ListIter); } // Finish writing LaTeX document FPRINTF_LINECOUNT(TextFooter); fclose(output); // Fork LaTeX process pplcsp_forkLaTeX(x->c, filename, &pid, &LatexStdIn, &LatexOut); // Wait for latex process's stdout to become readable. Get bored if this takes too long. FirstIter = 1; LatexStatus = 0; while (1) { for (TrialNumber=1;;) { waitperiod.tv_sec = FirstIter ? 15 : 4; // Wait 15 seconds first time around; otherwise wait 4 seconds waitperiod.tv_nsec = 0; if (ReadErrorState) { waitperiod.tv_nsec = 500000000; waitperiod.tv_sec = 0; } // If we've had an error message, only wait 0.5 sec if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"pselect waiting for %ld seconds and %ld nanoseconds",waitperiod.tv_sec,waitperiod.tv_nsec); ppl_log(&x->c->errcontext, x->c->errcontext.tempErrStr); } FD_ZERO(&readable); FD_SET(LatexOut, &readable); if (pselect(LatexOut+1, &readable, NULL, NULL, &waitperiod, NULL) == -1) { if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"pselect returned -1. errno=%d",errno); ppl_log(&x->c->errcontext, x->c->errcontext.tempErrStr); } if ((errno==EINTR) && (TrialNumber<3)) { TrialNumber++; continue; } LatexStatus=1; break; } if (DEBUG) { sprintf(x->c->errcontext.tempErrStr,"pipe is %s",(FD_ISSET(LatexOut , &readable))?"readable":"unreadable"); ppl_log(&x->c->errcontext, x->c->errcontext.tempErrStr); } break; } if (LatexStatus) break; FirstIter = 0; if (!FD_ISSET(LatexOut , &readable)) { LatexStatus=1; if (DEBUG) ppl_log(&x->c->errcontext, "latex's output pipe has not become readable within time limit"); break; } else { if ((NCharsRead = read(LatexOut, str_buffer, LSTR_LENGTH)) > 0) { for (j=0; jc->errcontext.tempErrStr,"Received LaTeX error on line %d of file <%s>",ErrLineNo,ErrFilename); ppl_log(&x->c->errcontext, x->c->errcontext.tempErrStr); sprintf(x->c->errcontext.tempErrStr,"Error message: <%s>",ErrMsg); ppl_log(&x->c->errcontext, x->c->errcontext.tempErrStr); } } ErrReadState = ErrReadPos = 0; } else if (str_buffer[j]==':') { if (ErrReadState==0) { TempErrFilename[ErrReadPos]='\0'; ErrReadPos=0; if (strcmp(TempErrFilename,"! LaTeX Error")==0) { strcpy(TempErrFilename, filename); strcpy(TempErrLineNo , "-1"); ErrReadState = 2; ReadErrorState = 1; if (DEBUG) ppl_log(&x->c->errcontext, "Encountered line beginning \"! LaTeX Error\""); } else { ErrReadState = 1; } } else if (ErrReadState==1) { TempErrLineNo [ErrReadPos]='\0'; ErrReadPos=0; ErrReadState++; if (!ppl_validFloat(TempErrLineNo, NULL)) ErrReadState++; else ReadErrorState = 1; } else if (ErrReadState==2) { TempErrMsg[ErrReadPos++]=str_buffer[j]; } } else { if (ErrReadState==0) { TempErrFilename[ErrReadPos++] = str_buffer[j]; } else if (ErrReadState==1) { TempErrLineNo [ErrReadPos++] = str_buffer[j]; } else if (ErrReadState==2) { TempErrMsg [ErrReadPos++] = str_buffer[j]; } } if (ErrReadPos > FNAME_LENGTH-1) ErrReadPos=FNAME_LENGTH-1; } } else { break; } // read function returned zero; indicates EOF } } // Finish talking to LaTeX process close(LatexStdIn); // This has the effect of killing latex close(LatexOut); sigprocmask(SIG_UNBLOCK, &sigs, NULL); // Return error message if latex has failed if (LatexStatus) { ppl_strStrip(ErrMsg,ErrMsg); if (strcmp(filename, ErrFilename)==0) // Case 1: Error in the LaTeX file which we just generated { unsigned char ExactHit=0; // Cycle through all text items and see whether error line number is in the middle of one of them ListIter = ppl_listIterateInit(x->TextItems); while (ListIter != NULL) { TempTextItem = (CanvasTextItem *)ListIter->data; if (TempTextItem->LaTeXstartline > ErrLineNo) break; // We have gone past the line number where the error happened SuspectTextItem = TempTextItem; ExactHit = (TempTextItem->LaTeXendline >= ErrLineNo); // If this is zero, then error was after the end of the item we just looked at ppl_listIterate(&ListIter); } if (SuspectTextItem==NULL) sprintf(x->c->errcontext.tempErrStr, "LaTeX error encountered in an unidentifiable canvas item."); else if (ExactHit) sprintf(x->c->errcontext.tempErrStr, "LaTeX error encountered in text string in canvas item %d.", SuspectTextItem->CanvasMultiplotID); else sprintf(x->c->errcontext.tempErrStr, "LaTeX error encountered at the end of text string in canvas item %d.", SuspectTextItem->CanvasMultiplotID); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1,x->c->errcontext.tempErrStr); sprintf(x->c->errcontext.tempErrStr, "Error was: %s", ErrMsg); // Output the actual error which LaTeX returned to us ppl_error(&x->c->errcontext, ERR_PREFORMED, -1, -1,x->c->errcontext.tempErrStr); if (SuspectTextItem!=NULL) { canvas_item *ptr = ((canvas_itemlist *)x->c->canvas_items)->first; // Cycle through all canvas items to find the culprit for (ptr = ((canvas_itemlist *)x->c->canvas_items)->first; ((ptr!=NULL)&&(ptr->id!=SuspectTextItem->CanvasMultiplotID)); ptr = ptr->next); if (ptr!=NULL) { sprintf(x->c->errcontext.tempErrStr, "\nInput Pyxplot command was:\n\n"); // Now tell the user what Pyxplot command produced the culprit i = strlen(x->c->errcontext.tempErrStr); ppl_canvas_item_textify(x->c, ptr, x->c->errcontext.tempErrStr+i); i += strlen(x->c->errcontext.tempErrStr+i); strcpy(x->c->errcontext.tempErrStr+i, "\n"); ppl_error(&x->c->errcontext, ERR_PREFORMED, -1, -1,x->c->errcontext.tempErrStr); } // Then output the LaTeX string which produced the error sprintf(x->c->errcontext.tempErrStr, "\nOffending input to LaTeX was:\n\n%s\n", SuspectTextItem->text); ppl_error(&x->c->errcontext, ERR_PREFORMED, -1, -1,x->c->errcontext.tempErrStr); } } else if ((ErrFilename[0]=='\0')&&(ErrMsg[0]=='\0')) // Case 2: Error encountered, but we didn't catch error message { sprintf(x->c->errcontext.tempErrStr, "Unidentified LaTeX error encountered."); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1,x->c->errcontext.tempErrStr); } else // Case 3: Error in another file which the user seems to have imported { sprintf(x->c->errcontext.tempErrStr, "LaTeX error encountered in imported file <%s> on line %d.", ErrFilename, ErrLineNo); ppl_error(&x->c->errcontext, ERR_GENERIC, -1, -1,x->c->errcontext.tempErrStr); sprintf(x->c->errcontext.tempErrStr, "Error was: %s", ErrMsg); ppl_error(&x->c->errcontext, ERR_PREFORMED, -1, -1,x->c->errcontext.tempErrStr); } if (chdir(x->c->errcontext.session_default.cwd) < 0) { ppl_fatal(&x->c->errcontext,__FILE__,__LINE__,"chdir into cwd failed."); } *(x->status) = 1; return; } // Convert dvi into postscript fragments sprintf(filename, "%s.dvi", x->TeXFilename); x->dvi = ReadDviFile(&x->c->errcontext, filename, x->status); if (*(x->status)) return; // DVI interpreter failed // Return to user's current working directory after LaTeX has finished making a mess if (chdir(x->c->errcontext.session_default.cwd) < 0) { ppl_fatal(&x->c->errcontext,__FILE__,__LINE__,"chdir into cwd failed."); } return; } // Make a temporary buffer file into which the eps fragments for objects is temporarily stored void canvas_MakeEPSBuffer(EPSComm *x) { x->epsbuffer = tmpfile(); if (x->epsbuffer == NULL) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1,"Could not create temporary eps buffer file."); *(x->status)=1; return; } return; } // Finally output postscript file, once all of the eps fragments are written to temporary buffer and bounding box is known void canvas_EPSWrite(EPSComm *x) { int i; double PAGEwidth, PAGEheight, margin_left, margin_top, margin_bottom; FILE *epsout, *PFAfile; char LandscapifyText[FNAME_LENGTH], EnlargementText[FNAME_LENGTH], *PaperName, *PFAfilename; listIterator *ListIter; // Check that we have a bounding box if (!x->bb_set) { x->bb_left = x->bb_right = x->bb_bottom = x->bb_top = 0.0; } // Apply enlarge and landscape terminals as required LandscapifyText[0] = EnlargementText[0] = '\0'; if (x->c->set->term_current.landscape == SW_ONOFF_ON) canvas_EPSLandscapify(x, LandscapifyText); if ((x->c->set->term_current.TermEnlarge == SW_ONOFF_ON) && (x->termtype == SW_TERMTYPE_PS)) canvas_EPSEnlarge (x, EnlargementText); // Work out name to call papersize PaperName = x->c->set->term_current.PaperName; if (strcmp(PaperName,"User-defined papersize")==0) PaperName = "CustomPageSize"; // Return to user's current working directory if (chdir(x->c->errcontext.session_default.cwd) < 0) { ppl_fatal(&x->c->errcontext, __FILE__,__LINE__,"chdir into cwd failed."); } // Work out some sensible margins for page PAGEwidth = x->c->set->term_current.PaperWidth.real; PAGEheight = x->c->set->term_current.PaperHeight.real; margin_left = PAGEwidth / 14; margin_top = PAGEheight / 14; margin_left *= M_TO_PS; margin_top *= M_TO_PS; margin_bottom = 2*margin_top; // Open output postscript file for writing if ((epsout=fopen(x->EPSFilename,"w"))==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open file '%s' for writing.", x->EPSFilename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); *(x->status)=1; return; } // Write EPS header if (x->c->set->term_current.TermType != SW_TERMTYPE_PS) { fprintf(epsout, "%s%s\n", "%!PS-Adobe-3.0", " EPSF-3.0"); fprintf(epsout, "%%%%BoundingBox: %d %d %d %d\n", (int)floor(x->bb_left), (int)floor(x->bb_bottom), (int)ceil(x->bb_right), (int)ceil(x->bb_top)); fprintf(epsout, "%%%%HiResBoundingBox: %f %f %f %f\n", x->bb_left, x->bb_bottom, x->bb_right, x->bb_top); } else { fprintf(epsout, "%s%s\n", "%!PS-Adobe-3.0", ""); fprintf(epsout, "%%%%BoundingBox: %d %d %d %d\n", (int)floor(margin_left), (int)floor(margin_bottom), (int)ceil(x->bb_right-x->bb_left+margin_left), (int)ceil(x->bb_top-x->bb_bottom+margin_bottom)); fprintf(epsout, "%%%%HiResBoundingBox: %f %f %f %f\n", margin_left, margin_bottom, x->bb_right-x->bb_left+margin_left, x->bb_top-x->bb_bottom+margin_bottom); } fprintf(epsout, "%%%%Creator: (Pyxplot %s)\n", VERSION); fprintf(epsout, "%%%%Title: (%s)\n", x->title); fprintf(epsout, "%%%%CreationDate: (%s)\n", ppl_strStrip(ppl_friendlyTimestring(), x->c->errcontext.tempErrStr)); if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) fprintf(epsout, "%%%%Pages: 1\n"); fprintf(epsout, "%%%%DocumentData: Clean7Bit\n"); if (x->c->set->term_current.landscape == SW_ONOFF_ON) fprintf(epsout, "%%%%Orientation: Landscape\n"); else fprintf(epsout, "%%%%Orientation: Portrait\n"); if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) fprintf(epsout, "%%%%DocumentMedia: %s %d %d white { }\n", PaperName, (int)(x->c->set->term_current.PaperWidth.real * M_TO_PS), (int)(x->c->set->term_current.PaperHeight.real * M_TO_PS)); fprintf(epsout, "%%%%DocumentFonts:"); // %%DocumentFonts has a list of all of the fonts that we use if (x->dvi != NULL) ListIter = ppl_listIterateInit(x->dvi->fonts); else ListIter = NULL; while (ListIter != NULL) { fprintf(epsout, " %s", ((dviFontDetails *)ListIter->data)->psName); ppl_listIterate(&ListIter); } fprintf(epsout, "\n"); fprintf(epsout, "%%%%EndComments\n\n"); // In postscript files, now set up page size if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) { fprintf(epsout, "%%%%BeginDefaults\n"); fprintf(epsout, "%%%%PageMedia: %s\n", PaperName); fprintf(epsout, "%%%%EndDefaults\n"); } // Write EPS prolog fprintf(epsout, "%%%%BeginProlog\n"); // Output all of the fonts which we're going to use if (chdir(x->c->errcontext.session_default.tempdir) < 0) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1,"Could not chdir into temporary directory."); *(x->status)=1; fclose(epsout); return; } if (x->dvi != NULL) ListIter = ppl_listIterateInit(x->dvi->fonts); else ListIter = NULL; while (ListIter != NULL) { PFAfilename = ((dviFontDetails *)ListIter->data)->pfaPath; if (PFAfilename != NULL) // PFAfilename==NULL indicates that this is a built-in font that doesn't require a fontdef { fprintf(epsout, "%%%%BeginFont: %s\n", ((dviFontDetails *)ListIter->data)->psName); PFAfile = fopen(PFAfilename,"r"); if (PFAfile==NULL) { sprintf(x->c->errcontext.tempErrStr, "Could not open pfa file '%s'", PFAfilename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); *(x->status)=1; fclose(epsout); return; } while (fgets(x->c->errcontext.tempErrStr, FNAME_LENGTH, PFAfile) != NULL) if (fputs(x->c->errcontext.tempErrStr, epsout) == EOF) { sprintf(x->c->errcontext.tempErrStr, "Error while writing to file '%s'.", x->EPSFilename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); *(x->status)=1; fclose(PFAfile); fclose(epsout); return; } fclose(PFAfile); fprintf(epsout, "\n%%%%EndFont\n"); } ppl_listIterate(&ListIter); } if (chdir(x->c->errcontext.session_default.cwd) < 0) { ppl_fatal(&x->c->errcontext, __FILE__,__LINE__,"chdir into cwd failed."); } // Output macros which Pyxplot needs if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) fprintf(epsout, "%s", PS_PROLOG_TEXT); fprintf(epsout, "%s", EPS_PROLOG_TEXT); fprintf(epsout, "/ps { 1 } def\n/ps75 { ps .75 mul } def\n"); // Pointsize variables if (x->PointTypesUsed[28]) { x->PointTypesUsed[14]=x->PointTypesUsed[ 0]=1; } // pt6 depends upon pt4 and pt5 if (x->PointTypesUsed[29]) { x->PointTypesUsed[15]=x->PointTypesUsed[ 1]=1; } // pt9 depends upon pt7 and pt8 if (x->PointTypesUsed[30]) { x->PointTypesUsed[16]=x->PointTypesUsed[ 2]=1; } // pt12 depends upon pt10 and pt11 if (x->PointTypesUsed[31]) { x->PointTypesUsed[17]=x->PointTypesUsed[ 3]=1; } // pt15 depends upon pt13 and pt14 if (x->PointTypesUsed[32]) { x->PointTypesUsed[18]=x->PointTypesUsed[ 4]=1; } // pt18 depends upon pt16 and pt17 if (x->PointTypesUsed[33]) { x->PointTypesUsed[19]=x->PointTypesUsed[ 5]=1; } // pt21 depends upon pt19 and pt20 if (x->PointTypesUsed[34]) { x->PointTypesUsed[20]=x->PointTypesUsed[ 6]=1; } // pt24 depends upon pt22 and pt23 if (x->PointTypesUsed[35]) { x->PointTypesUsed[21]=x->PointTypesUsed[ 7]=1; } // pt27 depends upon pt25 and pt26 if (x->PointTypesUsed[36]) { x->PointTypesUsed[22]=x->PointTypesUsed[ 8]=1; } // pt30 depends upon pt28 and pt29 if (x->PointTypesUsed[37]) { x->PointTypesUsed[23]=x->PointTypesUsed[ 9]=1; } // pt33 depends upon pt31 and pt32 if (x->PointTypesUsed[38]) { x->PointTypesUsed[24]=x->PointTypesUsed[10]=1; } // pt36 depends upon pt34 and pt35 if (x->PointTypesUsed[39]) { x->PointTypesUsed[25]=x->PointTypesUsed[11]=1; } // pt33 depends upon pt37 and pt38 if (x->PointTypesUsed[40]) { x->PointTypesUsed[26]=x->PointTypesUsed[12]=1; } // pt3 depends upon pt1 and pt2 if (x->PointTypesUsed[41]) { x->PointTypesUsed[27]=x->PointTypesUsed[13]=1; } // pt6 depends upon pt4 and pt5 if (x->StarTypesUsed [6]) { x->StarTypesUsed [5]=1; } // st7 depends upon st6 for (i=0; iPointTypesUsed[i]) fprintf(epsout, "%s\n", eps_PointTypes[i]); for (i=0; iStarTypesUsed [i]) { fprintf(epsout, "%s\n", eps_StarCore); break; } for (i=0; iStarTypesUsed [i]) fprintf(epsout, "%s\n", eps_StarTypes [i]); fprintf(epsout, "%%%%EndProlog\n\n"); // In postscript files, now set up page 1 if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) { fprintf(epsout, "<< /PageSize [ %d %d ] >> setpagedevice\n", (int)(x->c->set->term_current.PaperWidth.real * M_TO_PS), (int)(x->c->set->term_current.PaperHeight.real * M_TO_PS)); fprintf(epsout, "%%%%Page: 1 1\n"); fprintf(epsout, "%%%%BeginPageSetup\n"); fprintf(epsout, "/pgsave save def\n"); fprintf(epsout, "%%%%EndPageSetup\n\n"); } // Now write any global transformations needed by the enlarge and landscape terminals. if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) fprintf(epsout, "%.2f %.2f translate\n", margin_left-x->bb_left, margin_bottom-x->bb_bottom); if ((LandscapifyText[0]!='\0')||(EnlargementText[0]!='\0')) { fprintf(epsout, "%% Global transformations to give %soutput%s\n", (LandscapifyText[0]!='\0')?"landscape ":"", (EnlargementText[0]!='\0')?" which fills the page":""); fprintf(epsout, "%s", EnlargementText); fprintf(epsout, "%s", LandscapifyText); fprintf(epsout, "\n"); } // Copy contents of eps buffer into postscript output fflush(x->epsbuffer); rewind(x->epsbuffer); while (fgets(x->c->errcontext.tempErrStr, FNAME_LENGTH, x->epsbuffer) != NULL) if (fputs(x->c->errcontext.tempErrStr, epsout) == EOF) { sprintf(x->c->errcontext.tempErrStr, "Error while writing to file '%s'.", x->EPSFilename); ppl_error(&x->c->errcontext, ERR_FILE, -1, -1, NULL); *(x->status)=1; fclose(epsout); return; } // Write postscript footer and finish if (x->c->set->term_current.TermType == SW_TERMTYPE_PS) fprintf(epsout, "pgsave restore\n"); // End of page fprintf(epsout, "showpage\n%%%%EOF\n"); // End of document fclose(x->epsbuffer); x->epsbuffer=NULL; fclose(epsout); return; } // Write a text item out from dvi buffer void canvas_EPSRenderTextItem(EPSComm *x, char **strout, int pageno, double xpos, double ypos, int halign, int valign, char *colstr, double fontsize, double rotate, double *width, double *height) { postscriptPage *dviPage; listIterator *ListIter; char *cptr, *out; static char *buffer=NULL; const long BUFLEN=131072; long bufpos=0; double bb_left, bb_right, bb_top, bb_bottom, xanchor, yanchor; double ab_left, ab_right, ab_top, ab_bottom; // The align box is different from the bounding box in that it gives the baseline height of the lowest line of text and the cap height of the highest line of text // If colstr is blank, we are painting with null ink if (colstr[0]=='\0') return; // Write output to text buffer initially if (buffer==NULL) buffer = malloc(BUFLEN); // memory leak here! if (buffer==NULL) return; out=buffer; if (x->dvi == NULL) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Attempting to display a text item before latex has generated it"); return; } // Fetch requested page of postscript dviPage = (postscriptPage *)ppl_listGetItem(x->dvi->output->pages, pageno+1); if (dviPage==NULL) { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Not all text items were rendered by LaTeX"); *(x->status)=1; return; } bb_left = dviPage->boundingBox[0]; bb_bottom = dviPage->boundingBox[1]; bb_right = dviPage->boundingBox[2]; bb_top = dviPage->boundingBox[3]; ab_left = dviPage->textSizeBox[0]; ab_bottom = dviPage->textSizeBox[1]; ab_right = dviPage->textSizeBox[2]; ab_top = dviPage->textSizeBox[3]; // Return dimensions of text item if (width != NULL) *width = (bb_right - bb_left)*fontsize; if (height != NULL) *height = (bb_top - bb_bottom)*fontsize; // Work out where our anchor point is on postscript if (halign == SW_HALIGN_LEFT ) xanchor = ab_left; else if (halign == SW_HALIGN_CENT ) xanchor = (ab_left + ab_right)/2.0; else if (halign == SW_HALIGN_RIGHT) xanchor = ab_right; else { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Illegal halign value passed to canvas_EPSRenderTextItem"); *(x->status)=1; return; } if (valign == SW_VALIGN_TOP ) yanchor = bb_top; else if (valign == SW_VALIGN_CENT ) yanchor = (ab_top + ab_bottom)/2.0; else if (valign == SW_VALIGN_BOT ) yanchor = ab_bottom; else { ppl_error(&x->c->errcontext, ERR_INTERNAL, -1, -1, "Illegal valign value passed to canvas_EPSRenderTextItem"); *(x->status)=1; return; } // Update bounding box of canvas. For this, use BOUNDING box, not ALIGNMENT box. eps_core_PlotBoundingBox(x, xpos*M_TO_PS + (bb_left - xanchor)*fontsize*cos(rotate) + (bb_bottom - yanchor)*fontsize*-sin(rotate), ypos*M_TO_PS + (bb_left - xanchor)*fontsize*sin(rotate) + (bb_bottom - yanchor)*fontsize* cos(rotate), 0, 1); eps_core_PlotBoundingBox(x, xpos*M_TO_PS + (bb_right - xanchor)*fontsize*cos(rotate) + (bb_bottom - yanchor)*fontsize*-sin(rotate), ypos*M_TO_PS + (bb_right - xanchor)*fontsize*sin(rotate) + (bb_bottom - yanchor)*fontsize* cos(rotate), 0, 1); eps_core_PlotBoundingBox(x, xpos*M_TO_PS + (bb_left - xanchor)*fontsize*cos(rotate) + (bb_top - yanchor)*fontsize*-sin(rotate), ypos*M_TO_PS + (bb_left - xanchor)*fontsize*sin(rotate) + (bb_top - yanchor)*fontsize* cos(rotate), 0, 1); eps_core_PlotBoundingBox(x, xpos*M_TO_PS + (bb_right - xanchor)*fontsize*cos(rotate) + (bb_top - yanchor)*fontsize*-sin(rotate), ypos*M_TO_PS + (bb_right - xanchor)*fontsize*sin(rotate) + (bb_top - yanchor)*fontsize* cos(rotate), 0, 1); // Perform translation such that postscript text appears in the right place on the page snprintf(out+bufpos, BUFLEN-bufpos, "gsave\n"); bufpos+=strlen(out+bufpos); snprintf(out+bufpos, BUFLEN-bufpos, "%.2f %.2f translate\n", xpos * M_TO_PS, ypos * M_TO_PS); bufpos+=strlen(out+bufpos); snprintf(out+bufpos, BUFLEN-bufpos, "%.2f rotate\n", rotate * 180 / M_PI); bufpos+=strlen(out+bufpos); snprintf(out+bufpos, BUFLEN-bufpos, "%f %f scale\n", fontsize, fontsize); bufpos+=strlen(out+bufpos); snprintf(out+bufpos, BUFLEN-bufpos, "%.2f %.2f translate\n", -xanchor, -yanchor); bufpos+=strlen(out+bufpos); // Copy postscript description of page out of dvi buffer ListIter = ppl_listIterateInit(dviPage->text); while (ListIter!=NULL) { cptr = (char *)ListIter->data; while (*cptr!='\0') { if (*cptr!='\x01') snprintf(out+bufpos, BUFLEN-bufpos, "%c", *cptr); else snprintf(out+bufpos, BUFLEN-bufpos, "%s", colstr); // ASCII x01 is a magic code to tell us to revert to default color bufpos+=strlen(out+bufpos); cptr++; } ppl_listIterate(&ListIter); } // Undo translation and we're finished snprintf(out+bufpos, BUFLEN-bufpos, "grestore\n"); bufpos+=strlen(out+bufpos); // Either return string, or write output to file if (strout==NULL) fprintf(x->epsbuffer, "%s", buffer); else *strout=buffer; return; } // Convert a portrait EPS file to landscape by changing its bounding box and adding a linear transformation to the top void canvas_EPSLandscapify(EPSComm *x, char *transform) { double width, height; width = x->bb_right - x->bb_left; height = x->bb_top - x->bb_bottom; sprintf(transform, "90 rotate\n%f %f translate\n", -x->bb_left, -x->bb_top); x->bb_left = 0.0; x->bb_bottom = 0.0; x->bb_right = height; x->bb_top = width; return; } // Enlarge an EPS file to fill a page by changing its bounding box and adding a linear transformation to the top void canvas_EPSEnlarge(EPSComm *x, char *transform) { double EPSwidth, EPSheight, PAGEwidth, PAGEheight; double margin_left, margin_right, margin_top, margin_bottom; double scaling_x, scaling_y, translate_x, translate_y; // Read dimensions of page PAGEwidth = x->c->set->term_current.PaperWidth .real; PAGEheight = x->c->set->term_current.PaperHeight.real; // Calculate dimensions of EPS image EPSwidth = x->bb_right - x->bb_left; EPSheight = x->bb_top - x->bb_bottom; if ((EPSwidth<=0.0)||(EPSheight<=0.0)) return; // Don't attempt to enlarge pages of size zero // Work out some sensible margins for page margin_left = PAGEwidth / 14; margin_top = PAGEheight / 14; if (margin_left > 15e-3) margin_left = 15e-3; // mm if (margin_top > 15e-3) margin_top = 15e-3; // mm margin_right = margin_left; margin_bottom = 2*margin_top; // Work out what scaling factors will make page fit scaling_x = (PAGEwidth - margin_left - margin_right ) / EPSwidth * M_TO_PS; scaling_y = (PAGEheight - margin_top - margin_bottom) / EPSheight * M_TO_PS; if ((!gsl_finite(scaling_x))||(!gsl_finite(scaling_y))) return; // Don't attempt to enlarge pages of size zero if (scaling_y < scaling_x) scaling_x = scaling_y; // Lowest scaling factor is biggest enlargement we can do // Work out how to translate origin to (0,0) translate_x = margin_left * M_TO_PS - x->bb_left * scaling_x; translate_y = PAGEheight * M_TO_PS - margin_top * M_TO_PS - x->bb_top * scaling_x; // Write out transformation sprintf(transform, "%f %f translate\n%f %f scale\n", translate_x, translate_y, scaling_x, scaling_x); x->bb_left = margin_left * M_TO_PS; x->bb_right = margin_left * M_TO_PS + EPSwidth * scaling_x; x->bb_top = (PAGEheight - margin_top) * M_TO_PS; x->bb_bottom = (PAGEheight - margin_top) * M_TO_PS - EPSheight * scaling_x; return; } pyxplot-0.9.2/src/epsMaker/bmp_optimise.c0000664000175000017500000002075312026340554017024 0ustar dcf21dcf21// bmp_optimise.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_optimise.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It checks paletted images for possible optimisations of the // palette size if there are unused entries, and checks RGB images to see if // they can efficiently be reduced to paletted images. #define _PPL_BMP_OPTIMISE_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/bmp_optimise.h" #include "epsMaker/bmp_image.h" void ppl_bmp_colour_count(pplerr_context *ec, bitmap_data *image) { unsigned long size, i; int ncols,j,colour; int palette[257]; unsigned char *p; size = (long)image->height * (long)image->width; ncols = 0; p = image->data; // Count the number of colours in the image for (i=0; i 256) { if (DEBUG) ppl_log(ec, "Image contains more than 256 colours"); return; } if (DEBUG) { sprintf(ec->tempErrStr, "Image contains only %d colours: reducing to paletted image",ncols); ppl_log(ec, NULL); } // Reduce to paletted image if possible image->palette = (unsigned char *)ppl_memAlloc(3*ncols); if (image->palette == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } // Copy colours we found into palette for (i=0; ipalette[3*i ]=(palette[i]&0xff0000)>>16; image->palette[3*i+1]=(palette[i]&0xff00)>>8; image->palette[3*i+2]=(palette[i]&0xff); } // Replace RGB data with paletted colours p = image->data; for (i=0; itrans != NULL) { p = image->trans; colour= (((int)p[0])<<16) + (((int)p[1])<<8) + p[2]; for (j=0; jtrans=NULL; // Transparent colour not present in image else p[0]=j; } // Set up image headers to show that it is now a paletted image image->data_len = size; image->depth = 8; image->colour = BMP_COLOUR_PALETTE; image->type = BMP_COLOUR_PALETTE; image->pal_len = ncols; return; } void ppl_bmp_palette_check(pplerr_context *ec, bitmap_data *image) { int i; unsigned long size; unsigned char ncols; if (image->type != BMP_COLOUR_PALETTE) return; if (image->depth != 8) return; // Find highest used palette entry ncols = 0; size = image->data_len; for (i=0; iimage->data[i] ? ncols : image->data[i]); if (ncols < (image->pal_len-1)) { if (DEBUG) { sprintf(ec->tempErrStr, "Palette length reduced from %d to %d", image->pal_len, 1+ncols); ppl_log(ec, NULL); } image->pal_len = 1+ncols; if ((image->trans!=NULL)&&(image->trans[0]>ncols)) image->trans=NULL; // Transparent colour is not used in image } return; } void ppl_bmp_grey_check(pplerr_context *ec, bitmap_data *image) { int i,grey,depth=8,magic,test; unsigned int ncols; unsigned long size; if (image->type != BMP_COLOUR_PALETTE) return; if (image->depth!= 8) return; ncols = image->pal_len; size = image->data_len; // See if palette is greyscale. If not, we cannot reduce it to greyscale. grey=1; for (i=0; ipal_len; i++) if ( (image->palette[3*i]!=image->palette[3*i+1]) || (image->palette[3*i]!=image->palette[3*i+2]) ) { grey=0; break; } if (!grey) return; if (DEBUG) { sprintf(ec->tempErrStr, "Image is greyscale"); ppl_log(ec, NULL); } if (ncols<=16) // Investigate whether we can reduce colour depth below 8 { if (ncols==2) // We have only two colours { magic=255; depth=1; } else if (ncols<=4) // We have only four colours { magic=255/3; depth=2; } else // We have sixteen colours { magic=255/15; depth=4; } test=1; // Test whether the colours we have are all evenly spaced between 0 and 255 for (i=0; ipalette[3*i] % magic) != 0) { test=0; break; } } if (test) // If so, we can reduce colour depth { for (i=0; ipalette[3*i] /= magic; if (DEBUG) { sprintf(ec->tempErrStr,"Greyscale depth is %d bit",depth); ppl_log(ec, NULL); } } else { // We have a <=4 bit image, but cannot use a 4-bit greyscale representation. Give up and use palette! if (DEBUG) { sprintf(ec->tempErrStr, "ncols=%d, but not %d bit greyscale\n", ncols, depth); ppl_log(ec, NULL); } return; } } // See if palette is already ordered for (i=0; ipal_len; i++) if (image->palette[3*i] != i) { grey=0; break; } if (!grey) // Need to order things { if (DEBUG) ppl_log(ec, "Greyscale palette being reordered"); for (i=0; idata[i] = image->palette[3*image->data[i]]; if (image->trans != NULL) image->trans[0] = image->palette[3*image->trans[0]]; // Reorder transparent colour as well } // Now we can ditch palette etc. image->palette = NULL; if (depth <= 4) { image->pal_len = 1<type = BMP_COLOUR_PALETTE; ppl_bmp_compact(ec, image); } image->type = BMP_COLOUR_BMP; image->colour = BMP_COLOUR_GREY; image->pal_len = 0; return; } void ppl_bmp_compact(pplerr_context *ec, bitmap_data *image) { int ncols,i,j,height,width; unsigned char *p,*p2,ctmp; if (image->type != BMP_COLOUR_PALETTE) return; if (image->depth != 8) return; if (image->pal_len > 16) return; ncols = image->pal_len; height = image->height; width = image->width; if (ncols==2) { if (DEBUG) ppl_log(ec, "Compacting to 1 bit per pixel"); image->depth = 1; p = p2 = image->data; for (i=0; idata_len = ((long)height)*((width+7)>>3); } else if (ncols<=4) { if (DEBUG) ppl_log(ec, "Compacting to 2 bits per pixel"); image->depth = 2; p = p2 = image->data; for (i=0; idata_len = ((long)height)*((width+3)>>2); } else if (ncols<=16) { if (DEBUG) ppl_log(ec, "Compacting to 4 bits per pixel"); image->depth = 4; p = p2 = image->data; for (i=0; idata_len = ((long)height)*((width+1)>>1); } return; } pyxplot-0.9.2/src/epsMaker/bmp_gifread.c0000664000175000017500000002704212026340554016572 0ustar dcf21dcf21// bmp_gifread.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Michael Rutter // // $Id: bmp_gifread.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file is edited from code which was kindly contributed to Pyxplot by // Michael Rutter. It reads in data from GIF files. #define _PPL_BMP_GIFREAD_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/bmp_image.h" #include "epsMaker/bmp_gifread.h" void ppl_bmp_gifread(pplerr_context *ec, FILE *in, bitmap_data *image) { unsigned char buff[8],flags,len,*rawz; int gcm,ncols,interlaced; long lxoff,lyoff,lw,lh,lzwcs; unsigned long datalen,width,height; static unsigned char trans; if (DEBUG) ppl_log(ec, "Beginning to decode GIF image file"); if (fread(buff,3,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } buff[3]=0; if (!strcmp((char *)buff,"87a")) { if (DEBUG) ppl_log(ec, "GIF image in format GIF87a"); } else if (!strcmp((char *)buff,"89a")) { if (DEBUG) ppl_log(ec, "GIF image in format GIF89a"); } else { ppl_error(ec, ERR_FILE, -1, -1,"GIF image file is in an unrecognised format"); return; } if (fread(buff,4,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } width = ((unsigned)buff[1]<<8) + buff[0]; height = ((unsigned)buff[3]<<8) + buff[2]; if (DEBUG) { sprintf(ec->tempErrStr, "Size %ldx%ld",width,height); ppl_log(ec, NULL); } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (DEBUG) { sprintf(ec->tempErrStr, "Global colour map=%d",(flags&0x80)>>7); ppl_log(ec, NULL); } if (DEBUG) { sprintf(ec->tempErrStr, "Colour resolution=%d",(flags&0x70)>>4); ppl_log(ec, NULL); } if (DEBUG) { sprintf(ec->tempErrStr, "Colour depth =%d",(flags&0x7)); ppl_log(ec, NULL); } gcm=((flags&0x80)>>7); ncols=2<<(flags&0x7); if (DEBUG) { sprintf(ec->tempErrStr, "Global number of colours=%d",ncols); ppl_log(ec, NULL); } if (fread(buff,2,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (gcm) { image->palette = (unsigned char *)ppl_memAlloc(ncols*3); if (image->palette == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } if (fread(image->palette,ncols*3,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } image->pal_len = ncols; } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } while (flags==0x21) { if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (DEBUG) { sprintf(ec->tempErrStr, "Extension block %d",(int)flags); ppl_log(ec, NULL); } if ((int)flags==249){ if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (flags!=4) { ppl_error(ec, ERR_FILE, -1, -1, "GIF image file has an unexpected extension length"); return; } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (flags&1) { image->trans = &trans; fseek(in,2,SEEK_CUR); if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } *image->trans = flags; if (DEBUG) { sprintf(ec->tempErrStr, "Transparent colour index at %d", (int)flags); ppl_log(ec, NULL); } } else { fseek(in,3,SEEK_CUR); } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (flags) { ppl_error(ec, ERR_FILE, -1, -1, "GIF image file has unexpected extension data"); return; } } else { do { if (!fread(&flags,1,1,in)) { ppl_error(ec, ERR_FILE, -1, -1, "GIF image file ends prematurely"); return; } fseek(in,(long)flags,SEEK_CUR); } while(flags); } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } } if ((flags==0x2c) && DEBUG) { sprintf(ec->tempErrStr, "Local descriptor"); ppl_log(ec, NULL); } if (fread(buff,4,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } lxoff = ((unsigned)buff[1]<<8) + buff[0]; lyoff = ((unsigned)buff[3]<<8) + buff[2]; if (DEBUG) { sprintf(ec->tempErrStr, "Local offset %ldx%ld",lxoff,lyoff); ppl_log(ec, NULL); } if (fread(buff,4,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } lw = ((unsigned)buff[1]<<8) + buff[0]; lh = ((unsigned)buff[3]<<8) + buff[2]; if (DEBUG) { sprintf(ec->tempErrStr, "Local size %ldx%ld",lw,lh); ppl_log(ec, NULL); } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } if (flags&0x80) { if (DEBUG) { sprintf(ec->tempErrStr, "Local colour map"); ppl_log(ec, NULL); } ncols=2<<(flags&0x7); if (DEBUG) { sprintf(ec->tempErrStr, "Local number of colours=%d",ncols); ppl_log(ec, NULL); } if (gcm) free (image->palette); image->palette=ppl_memAlloc(ncols*3); if (image->palette == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } if (fread(image->palette,ncols*3,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } image->pal_len=ncols; } interlaced=flags&0x40; if (interlaced && DEBUG) { sprintf(ec->tempErrStr, "Interlaced"); ppl_log(ec, NULL); } if (lxoff || lyoff || (lw!=width) || (lh!=height)) { ppl_error(ec, ERR_FILE, -1, -1, "GIF image file cannot be processed because local and global sizes differ; file appears to be corrupt"); return; } if (fread(&flags,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } lzwcs = flags+1; if (DEBUG) { sprintf(ec->tempErrStr, "Initial code size=%ld",lzwcs); ppl_log(ec, NULL); } rawz = (unsigned char *)ppl_memAlloc((width*height*3)/2); if (rawz == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } datalen = 0; if (fread(&len,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } while(len) { if (fread(rawz+datalen,len,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } datalen += len; if (fread(&len,1,1,in)!=1) { ppl_error(ec, ERR_FILE, -1, -1,"This GIF image file appears to be corrupted"); return; } } if (DEBUG) { sprintf(ec->tempErrStr, "Total GIF data length=%ld",datalen); ppl_log(ec, NULL); } BMP_ALLOC(image->data , width*height); if (image->data == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return; } datalen = ppl_bmp_de_lzw(ec,rawz,image->data,width*height,lzwcs); if (datalen == 0) { image->data = NULL; return; } // Subroutine failed if (datalen != width*height) { sprintf(ec->tempErrStr, "Decoding error whilst processing GIF image file. Expecting %ld bytes of decoded data, but received %ld.",width*height,datalen); ppl_error(ec, ERR_FILE, -1, -1, NULL); return; } image->data_len = width*height; image->height = height; image->width = width; image->type = BMP_COLOUR_PALETTE; image->colour = BMP_COLOUR_PALETTE; image->depth = 8; if (interlaced) { if (ppl_bmp_de_gifinterlace(ec,image)) { image->data = NULL; return; } // Subroutine failed } return; } int ppl_bmp_de_gifinterlace(pplerr_context *ec, bitmap_data *image) { int i,j; unsigned char *out,*in,*outp; BMP_ALLOC(out , image->height*image->width); if (out == NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return 1; } in = image->data; // First pass is eights outp = out; for (i=0; iheight; i+=8) { for (j=0; jwidth; j++) *outp++ = *in++; outp += 7*image->width; } // Next is fours outp = out + 4*image->width; for (i=4; iheight; i+=8) { for (j=0; jwidth; j++) *outp++ = *in++; outp += 7*image->width; } // Next is twos outp = out+2*image->width; for (i=2; iheight; i+=4) { for (j=0; jwidth; j++) *outp++ = *in++; outp += 3*image->width; } // Next is ones outp=out+image->width; for (i=1; iheight; i+=2) { for (j=0; jwidth; j++) *outp++ = *in++; outp += image->width; } image->data=out; return 0; } #define MAXCS 12 unsigned long ppl_bmp_de_lzw(pplerr_context *ec, unsigned char *buff, unsigned char *out, unsigned long len, int cs) { unsigned char store[256], *start, *end; unsigned int off,tpos,eoi,clr; struct str {unsigned char *s; unsigned len;} table[1<MAXCS) { sprintf(ec->tempErrStr, "Whilst decoding GIF image file, encountered de_lzw error: initial token size of %d too large",cs); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 0; } // Init table off = 0; ccs = cs; clr = (1<<(cs-1)); eoi = clr+1; tpos = clr+2; for (i=0; itempErrStr, "Whilst decoding GIF image file, encountered de_lzw error: ClearCode not first code, but instead got %x",i); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 0; } while(1) { i = ppl_bmp_de_lzw_bits(ec,buff+(off>>3),off&7,ccs); off += ccs; if (i==clr) { ccs = cs; tpos = clr+2; continue; } if (i==eoi) return(out-start); if (i>=tpos) { sprintf(ec->tempErrStr, "Whilst decoding GIF image file, encountered de_lzw error: token erroneously large"); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 0; } if (out>end) { sprintf(ec->tempErrStr, "Whilst decoding GIF image file, encountered de_lzw error: output buffer full"); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 0; } if (tpos<=tmax) { table[tpos].len = table[i].len + 1; table[tpos].s = out; tpos++; } for (j=0; (jtempErrStr, "Whilst decoding GIF image file, encountered unidentified de_lzw error"); ppl_error(ec, ERR_FILE, -1, -1, NULL); return 0; } unsigned int ppl_bmp_de_lzw_bits(pplerr_context *ec, unsigned char *c,int st, int len) { unsigned tmp,mask; tmp = ((unsigned)(*(c+2))<<16) + ((unsigned)(*(c+1))<<8) + *(c); mask = ((1<>st); } pyxplot-0.9.2/src/epsMaker/eps_point.h0000664000175000017500000000171412026340554016336 0ustar dcf21dcf21// eps_point.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_point.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_POINT_H #define _PPL_EPS_POINT_H 1 #include "epsMaker/eps_comm.h" void eps_point_YieldUpText(EPSComm *x); void eps_point_RenderEPS(EPSComm *x); #endif pyxplot-0.9.2/src/epsMaker/kpse_wrap.h0000664000175000017500000000212512026340554016326 0ustar dcf21dcf21// kpse_wrap.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: kpse_wrap.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _KPSE_WRAP_H #define _KPSE_WRAP_H 1 #include "userspace/context.h" void ppl_kpse_wrap_init (ppl_context *c); char *ppl_kpse_wrap_find_pfa(pplerr_context *ec, char *s); char *ppl_kpse_wrap_find_pfb(pplerr_context *ec, char *s); char *ppl_kpse_wrap_find_tfm(pplerr_context *ec, char *s); #endif pyxplot-0.9.2/src/epsMaker/eps_plot_styles.h0000664000175000017500000000412612026340554017566 0ustar dcf21dcf21// eps_plot_styles.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_styles.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_EPS_PLOT_STYLES_H #define _PPL_EPS_PLOT_STYLES_H 1 #include "canvasItems.h" #include "datafile.h" #include "epsMaker/eps_comm.h" #include "settings/settings.h" #include "settings/withWords.h" void eps_withwords_default(EPSComm *x, withWords *output, pplset_graph *sg, unsigned char functions, int Ccounter, int LTcounter, int PTcounter, unsigned char colour); void eps_withwords_default_counterinc(EPSComm *x, int *Ccounter, int *LTcounter, int *PTcounter, unsigned char colour, withWords *ww_final, pplset_graph *sg); int eps_plot_styles_NDataColumns(pplerr_context *ec, int style, unsigned char ThreeDim); int eps_plot_styles_UpdateUsage(EPSComm *x, dataTable *data, int style, unsigned char ThreeDim, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, pplset_graph *sg, int xyz1, int xyz2, int xyz3, int n1, int n2, int n3, int id); int eps_plot_dataset(EPSComm *x, dataTable *data, int style, unsigned char ThreeDim, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, int xn, int yn, int zn, pplset_graph *sg, canvas_plotdesc *pd, double origin_x, double origin_y, double width, double height, double zdepth); void eps_plot_LegendIcon(EPSComm *x, int i, canvas_plotdesc *pd, double xpos, double ypos, double scale, pplset_axis *a1, pplset_axis *a2, pplset_axis *a3, int xn, int yn, int zn); #endif pyxplot-0.9.2/src/epsMaker/dvi_interpreter.c0000664000175000017500000011311212026340554017532 0ustar dcf21dcf21// dvi_interpreter.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_interpreter.c 1270 2012-07-18 22:02:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating dvi interpreters #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "stringTools/strConstants.h" #include "epsMaker/dvi_interpreter.h" #include "epsMaker/dvi_font.h" #include "epsMaker/dvi_read.h" // Table of the operator functions to allow quick lookup without a long if ... else if ... statement int (*dviOpTable[58])(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); void makeDviOpTable(pplerr_context *ec) { dviOpTable[0] = dviInOpSet1234; dviOpTable[1] = dviInOpSet1234; dviOpTable[2] = dviInOpSet1234; dviOpTable[3] = dviInOpSet1234; dviOpTable[4] = dviInOpSetRule; dviOpTable[5] = dviInOpPut1234; dviOpTable[6] = dviInOpPut1234; dviOpTable[7] = dviInOpPut1234; dviOpTable[8] = dviInOpPut1234; dviOpTable[9] = dviInOpPutRule; dviOpTable[10] = dviInOpNop; dviOpTable[11] = dviInOpBop; dviOpTable[12] = dviInOpEop; dviOpTable[13] = dviInOpPush; dviOpTable[14] = dviInOpPop; dviOpTable[15] = dviInOpRight1234; dviOpTable[16] = dviInOpRight1234; dviOpTable[17] = dviInOpRight1234; dviOpTable[18] = dviInOpRight1234; dviOpTable[19] = dviInOpW0; dviOpTable[20] = dviInOpW1234; dviOpTable[21] = dviInOpW1234; dviOpTable[22] = dviInOpW1234; dviOpTable[23] = dviInOpW1234; dviOpTable[24] = dviInOpX0; dviOpTable[25] = dviInOpX1234; dviOpTable[26] = dviInOpX1234; dviOpTable[27] = dviInOpX1234; dviOpTable[28] = dviInOpX1234; dviOpTable[29] = dviInOpDown1234; dviOpTable[30] = dviInOpDown1234; dviOpTable[31] = dviInOpDown1234; dviOpTable[32] = dviInOpDown1234; dviOpTable[33] = dviInOpY0; dviOpTable[34] = dviInOpY1234; dviOpTable[35] = dviInOpY1234; dviOpTable[36] = dviInOpY1234; dviOpTable[37] = dviInOpY1234; dviOpTable[38] = dviInOpZ0; dviOpTable[39] = dviInOpZ1234; dviOpTable[40] = dviInOpZ1234; dviOpTable[41] = dviInOpZ1234; dviOpTable[42] = dviInOpZ1234; // Big hole here where we ignore FONTi dviOpTable[43] = dviInOpFnt1234; dviOpTable[44] = dviInOpFnt1234; dviOpTable[45] = dviInOpFnt1234; dviOpTable[46] = dviInOpFnt1234; dviOpTable[47] = dviInOpSpecial1234; dviOpTable[48] = dviInOpSpecial1234; dviOpTable[49] = dviInOpSpecial1234; dviOpTable[50] = dviInOpSpecial1234; dviOpTable[51] = dviInOpFntdef1234; dviOpTable[52] = dviInOpFntdef1234; dviOpTable[53] = dviInOpFntdef1234; dviOpTable[54] = dviInOpFntdef1234; dviOpTable[55] = dviInOpPre; dviOpTable[56] = dviInOpPost; dviOpTable[57] = dviInOpPostPost; return; } // Function to interpret an operator. This is a wrapper round the functions below. int dviInterpretOperator(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int (*func)(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) = NULL; int i=0; int err; char errStr[SSTR_LENGTH]; // Deal with the processing of DVI extensions (DIV_XXX/SPECIAL) if (interp->special > 0) { if ((op->op <= DVI_CHARMAX) && (interp->specialLen-->0)) { return dviSpecialChar(ec, interp, op); } else { // The following function turns the special flag off, and hence op is evaluated below if ((err=dviSpecialImplement(ec, interp)) != 0) return err; } } // This if statement extends the lookup table of operator functions if (op->op <= DVI_CHARMAX) { func = dviInOpChar; } else if (op->op < DVI_FNTNUMMIN) { i = op->op-DVI_CHARMAX-1; func = (dviOpTable[i]); } else if (op->op < DVI_FNTNUMMAX) { func = dviInOpFnt; } else if (op->op <= DVI_POSTPOST) { i = op->op-DVI_CHARMAX-1-(DVI_FNTNUMMAX-DVI_FNTNUMMIN+1); func = (dviOpTable[i]); } else { ppl_error(ec, ERR_INTERNAL, -1, -1,"dvi interpreter found an illegal operator"); return DVIE_CORRUPT; } if (func==NULL) { snprintf(errStr, SSTR_LENGTH, "Failed to find handler for dvi operator %d i=%d", op->op, i); ppl_error(ec, ERR_INTERNAL, -1, -1,errStr); return DVIE_CORRUPT; } // If we are not typesetting a character and moving right, check if we need to set accumulated text if (op->op > DVI_SET1234+3 && interp->currentString != NULL) if ((err=dviTypeset(ec, interp))!=0) return err; // Call the function to interpret the operator return (*func)(ec, interp, op); } // ---------------------------------- // Functions that implement operators // ---------------------------------- // Typeset a special character int dviNonAsciiChar(pplerr_context *ec, dviInterpreterState *interp, int c, char move) { char s[64]; int err; dviStackState *postPos, *dviPos; // Current positions in dvi and postscript code double width, height, depth, italic, size[4]; postPos = interp->output->currentPosition; dviPos = interp->state; // First check if we need to move before typesetting if (postPos== NULL) { dviPostscriptMoveto(ec, interp); interp->output->currentPosition = dviCloneInterpState(ec, dviPos); } else if (postPos->h != dviPos->h || postPos->v != dviPos->v) { dviPostscriptMoveto(ec, interp); } // Update bounding box dviGetCharSize(ec, interp, (char)c, size); width = size[0] / interp->scale; // Convert back into dvi units height = size[1] / interp->scale; depth = size[2] / interp->scale; italic = size[3] / interp->scale; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: width of glyph %g height of glyph %g", width, height); ppl_log(ec, NULL); } if ((err=dviUpdateBoundingBox(ec, interp, width+italic, height, depth))!=0) return err; // Count the number of characters to write to the ps string snprintf(s, 64, "(\\%o) show\n", c); // Send the string off to the postscript routine and clean up memory if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; //free(interp->currentString); interp->currentString = NULL; interp->currentStrlen = 0; // Adjust the current position if (move == DVI_YES) { interp->state->h += width; interp->output->currentPosition->h += width; } return 0; } // Interpreter functions for various types of dvi operators int dviInOpChar(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int charToTypeset = op->op; int err; char *s; // Typeset non-printable characters separately if ( (charToTypeset< 48) || ((charToTypeset> 57) && (charToTypeset<65)) || ((charToTypeset> 90) && (charToTypeset<97)) || (charToTypeset>126) ) { // Clear the queue if there's anything on it if (interp->currentString != NULL) if ((err=dviTypeset(ec, interp))!=0) return err; if ((err=dviNonAsciiChar(ec, interp, charToTypeset, DVI_YES))!=0) return err; return 0; } // See if we have anywhere to put the character if (interp->currentString == NULL) { interp->currentString = (char *)ppl_memAlloc(SSTR_LENGTH); if (interp->currentString==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } *(interp->currentString) = '\0'; interp->currentStrlen = LSTR_LENGTH; } else if (strlen(interp->currentString) == interp->currentStrlen-2) // If the string is full, extend it { if ((err=dviTypeset(ec, interp))!=0) return err; interp->currentString = (char *)ppl_memAlloc(SSTR_LENGTH); if (interp->currentString==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } *(interp->currentString) = '\0'; interp->currentStrlen = LSTR_LENGTH; } // Write the character to the string s = interp->currentString+strlen(interp->currentString); // s now points to the \0 if (charToTypeset == 40) snprintf(s, 3, "%s", "\\("); else if (charToTypeset == 41) snprintf(s, 3, "%s", "\\)"); else snprintf(s, 2, "%c", charToTypeset); return 0; } // DVI_SET1234 int dviInOpSet1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { return dviNonAsciiChar(ec, interp, op->ul[0], DVI_YES); } // DVI_SETRULE // Set a rule and move right int dviInOpSetRule(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int err=0; // Don't set a rule if movements are -ve if (op->sl[0]<0 || op->sl[1]<0) { if (DEBUG) ppl_log(ec, "DVI: silent rule"); interp->state->h += op->sl[1]; if ((err=dviPostscriptMoveto(ec, interp))!=0) return err; } else { if ((err=dviUpdateBoundingBox(ec, interp, (int)op->sl[1], (int)op->sl[0], 0.0))!=0) return err; if ((err=dviPostscriptMoveto (ec, interp) )!=0) return err; interp->state->v -= op->sl[0]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; interp->state->h += op->sl[1]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; interp->state->v += op->sl[0]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; if ((err=dviPostscriptClosepathFill(ec, interp))!=0) return err; } return err; } // DVI_PUT int dviInOpPut1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { return dviNonAsciiChar(ec, interp, op->ul[0], DVI_NO); } // DVI_PUTRULE // Set a rule and don't move right int dviInOpPutRule(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int err=0; // Don't set a rule if movements are -ve if (op->sl[0]<0 || op->sl[1]<0) { if (DEBUG) ppl_log(ec, "DVI: silent rule"); } else { if ((err=dviUpdateBoundingBox(ec, interp, (int)op->sl[1], (int)op->sl[0], 0.0))!=0) return err; if ((err=dviPostscriptMoveto (ec, interp) )!=0) return err; interp->state->v -= op->sl[0]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; interp->state->h += op->sl[1]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; interp->state->v += op->sl[0]; if ((err=dviPostscriptLineto (ec, interp))!=0) return err; if ((err=dviPostscriptClosepathFill(ec, interp))!=0) return err; interp->state->h -= op->sl[1]; } return err; } // DVI_NOP int dviInOpNop(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { return 0; } // DVI_BOP int dviInOpBop(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { // Generate a new page postscriptPage *p; p = dviNewPostscriptPage(ec); if (p == NULL) return DVIE_MEMORY; ppl_listAppend(interp->output->pages, (void *)p); interp->output->currentPage = p; interp->output->Npages++; // Check that the stack is empty if (ppl_listLen(interp->stack)>0) { ppl_warning(ec,ERR_INTERNAL,"malformed DVI file: stack not empty at start of new page"); interp->stack = ppl_listInit(0); } // There should not be a string in progress on the stack if (interp->currentStrlen != 0) { ppl_warning(ec,ERR_INTERNAL,"error in DVI interpreter: string on stack at newpage"); interp->currentStrlen = 0; //free(interp->currentString); interp->currentString = NULL; } // Set the default state values interp->state->h = 0; interp->state->v = 0; interp->state->w = 0; interp->state->x = 0; interp->state->y = 0; interp->state->z = 0; // Leave f as it is undefined after a new page return 0; } // DVI_EOP int dviInOpEop(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { double *bb; // Set appropriate postscript bounding box from dvi bb // left bottom right top bb = interp->boundingBox; // If we have not typeset anything then the bounding box will be empty. if (bb == NULL) { bb = (double *)ppl_memAlloc(4*sizeof(double)); if (bb==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } bb[0] = interp->state->h; bb[1] = interp->state->v; bb[2] = interp->state->h; bb[3] = interp->state->v; } // Convert bounding box from DVI to PS units bb[0] *= interp->scale; bb[1] = 765 - bb[1] * interp->scale; bb[2] *= interp->scale; bb[3] = 765 - bb[3] * interp->scale; // Move pointer to postscript interp->output->currentPage->boundingBox = bb; interp->boundingBox = NULL; if (DEBUG) { sprintf(ec->tempErrStr, "Postscript page: bounding box %f %f %f %f", bb[0], bb[1], bb[2], bb[3]); ppl_log(ec, NULL); } // Now repeat for text size box bb = interp->textSizeBox; // If we have not typeset anything then the box will be empty. if (bb == NULL) { bb = (double *)ppl_memAlloc(4*sizeof(double)); if (bb==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } bb[0] = interp->state->h; bb[1] = interp->state->v; bb[2] = interp->state->h; bb[3] = interp->state->v; } bb[0] *= interp->scale; bb[1] = 765 - bb[1] * interp->scale; bb[2] *= interp->scale; bb[3] = 765 - bb[3] * interp->scale; // Move pointer to postscript interp->output->currentPage->textSizeBox = bb; interp->textSizeBox = NULL; if (DEBUG) { sprintf(ec->tempErrStr, "Postscript page: text size box %f %f %f %f", bb[0], bb[1], bb[2], bb[3]); ppl_log(ec, NULL); } return 0; } // DVI_PUSH int dviInOpPush(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { // Push the current state on to the stack dviStackState *new; new = dviCloneInterpState(ec, interp->state); if (new == NULL) return DVIE_MEMORY; ppl_listAppend(interp->stack, (void *)new); return 0; } // DVI_POP int dviInOpPop(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { // Pop the previous state off the stack dviStackState *new; new = (dviStackState *)ppl_listPop(interp->stack); if (new == NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"corrupt dvi file -- attempt to pop off empty stack"); return 1; } interp->state = new; // Unset the special flag interp->special = 0; return 0; } // DVI_RIGHT1234 int dviInOpRight1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->h += op->sl[0]; return 0; } // DVI_W0 int dviInOpW0(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->h += interp->state->w; return 0; } // DVI_W1234 int dviInOpW1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->w = op->sl[0]; interp->state->h += interp->state->w; return 0; } // DVI_X0 int dviInOpX0(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->h += interp->state->x; return 0; } // DVI_X1234 int dviInOpX1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->x = op->sl[0]; interp->state->h += interp->state->x; return 0; } // DVI_DOWN1234 int dviInOpDown1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->v += op->sl[0]; return 0; } // DVI_Y0 int dviInOpY0(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->v += interp->state->y; return 0; } // DVI_Y1234 int dviInOpY1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->y = op->sl[0]; interp->state->v += interp->state->y; return 0; } // DVI_Z0 int dviInOpZ0(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->v += interp->state->z; return 0; } // DVI_Z1234 int dviInOpZ1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { interp->state->z = op->sl[0]; interp->state->v += interp->state->z; return 0; } // DVI_FNTi int dviInOpFnt(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int fn; fn = op->op - DVI_FNTNUMMIN; return dviChngFnt(ec, interp, fn); } // DVI_FNT1234 int dviInOpFnt1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { dviChngFnt(ec, interp, op->ul[0]); return 0; } // DVI_SPECIAL1234 int dviInOpSpecial1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { int spesh; spesh = op->op - DVI_SPECIAL1234+1; interp->special = spesh; interp->specialLen = op->ul[0]; interp->spString = (char *)ppl_memAlloc(SSTR_LENGTH); if (interp->spString==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1,"Out of memory"); return DVIE_MEMORY; } *(interp->spString) = '\0'; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: dvi special: %d %lu %d", spesh, op->ul[0], (int)strlen(interp->spString)); ppl_log(ec, NULL); } // NOP return 0; } // DVI_FNTDEF1234 int dviInOpFntdef1234(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { // XXX Should perhaps check that we're not re-defining an existing font here // XXX Could check that we're not after POST and hence that we need to do this dviFontDetails *font; int i; font = (dviFontDetails *)ppl_memAlloc(sizeof(dviFontDetails)); if (font==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } ppl_listAppend(interp->fonts, (void *)font); // Populate with information from operator font->number = op->ul[0]; font->area = (char *)ppl_memAlloc(op->ul[4]+1); if (font->area==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } for (i=0; iul[4]; i++) font->area[i] = op->s[0][i]; font->area[op->ul[4]] = '\0'; font->name = (char *)ppl_memAlloc(op->ul[5]+1); if (font->name==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } for (i=0; iul[5]; i++) font->name[i] = op->s[0][op->ul[4]+i]; font->name[op->ul[5]] = '\0'; font->useSize = op->ul[2]; font->desSize = op->ul[3]; // parse the TFM file for useful data return dviGetTFM(ec, font); } // DVI_PRE int dviInOpPre(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { unsigned long i, num, den, mag; i = op->ul[0]; num = op->ul[1]; den = op->ul[2]; mag = op->ul[3]; if (i != 2) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Error interpreting dvi file: not dvi version 2"); return 1; } // Convert mag, num and den into points (for ps) interp->scale = (double)mag / 1000.0 * (double)num / (double)den / 1.0e3 * 72.0 / 254; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: Scale %g V=%lu num=%lu den=%lu mag=%lu", interp->scale,i,num,den,mag); ppl_log(ec, NULL); } return 0; } // DVI_POST -- nop int dviInOpPost(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { return 0; } // DVI_POSTPOST -- nop int dviInOpPostPost(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { return 0; } // ---------------------------------------------------------- // Functions for implementing special operators (DVI_SPECIAL) // ---------------------------------------------------------- // Accumulate characters output in special mode into a string int dviSpecialChar(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op) { char *s; s = interp->spString+strlen(interp->spString); snprintf(s, SSTR_LENGTH, "%c", op->op); return 0; } // Implement an accumulated special-mode command int dviSpecialImplement(pplerr_context *ec, dviInterpreterState *interp) { int err = 0; char errString[SSTR_LENGTH]; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: dvi special. Final string=%s", interp->spString); ppl_log(ec, NULL); } // Test for a colour string if (strncmp(interp->spString, "color ", 6) == 0) { if ((err=dviSpecialColourCommand(ec, interp, interp->spString+6))!=0) return err; } else { // Unhandled special command (e.g. includegraphics) snprintf(errString, SSTR_LENGTH, "ignoring unhandled DVI special string %s", interp->spString); ppl_warning(ec, ERR_GENERIC, errString); } // Clean up //free(interp->spString); interp->spString = NULL; interp->special = 0; return err; } // Handle latex colour commands int dviSpecialColourCommand(pplerr_context *ec, dviInterpreterState *interp, char *command) { char psText[SSTR_LENGTH]; // Skip over any leading spaces while (command[0] == ' ') command++; // See what sort of colour command it is if (strncmp(command, "push ", 4)==0) { // New colour to push onto stack if (DEBUG) { sprintf(ec->tempErrStr, "DVI: %s says push", command); ppl_log(ec, NULL); } command += 5; while (command[0] == ' ') command++; if (strncmp(command, "cmyk ", 5)==0) { command += 5; snprintf(psText, SSTR_LENGTH, "%s setcmykcolor\n", command); // CMKY colour } else if (strncmp(command, "rgb ", 4)==0) { command += 4; snprintf(psText, SSTR_LENGTH, "%s setrgbcolor\n", command); // rgb colour } else if (strncmp(command, "Black", 5)==0) { snprintf(psText, SSTR_LENGTH, "0 0 0 setrgbcolor\n"); // black } else if (strncmp(command, "gray ", 5)==0 || strncmp(command, "grey ", 5)==0) // grey colour { command += 5; snprintf(psText, SSTR_LENGTH, "%s %s %s setrgbcolor\n", command, command, command); } else { snprintf(psText, SSTR_LENGTH, "failed to interpret dvi colour %s", command); ppl_warning(ec,ERR_INTERNAL,psText); return 0; } return dviSpecialColourStackPush(ec, interp, psText); } else if (strncmp(command, "pop", 3)==0) { return dviSpecialColourStackPop(ec, interp); // Pop a colour off the stack } else { snprintf(psText, SSTR_LENGTH, "ignoring incomprehensible dvi colour command %s", command); ppl_warning(ec,ERR_INTERNAL,psText); return 0; } return 0; } // Pop a colour instruction off the end of the stack int dviSpecialColourStackPop(pplerr_context *ec, dviInterpreterState *interp) { int err=0; char *item; // Lop last colour off the end of the colour stack item = (char *)ppl_listPop(interp->colStack); if (item==NULL) { ppl_warning(ec,ERR_INTERNAL,"dvi colour pop from empty stack"); return 0; } // Read last colour from stack item = (char *)ppl_listLast(interp->colStack); // Set colour to item on top of stack if (item==NULL) { // Hit the bottom of the colour stack; returning to default colour. Spit out ASCII x01, and this will be dealt with later if ((err=dviPostscriptAppend(ec, interp, "\x01\n"))!=0) return err; } else { if ((err=dviPostscriptAppend(ec, interp, item))!=0) return err; } return 0; } // Push a colour onto the colour stack int dviSpecialColourStackPush(pplerr_context *ec, dviInterpreterState *interp, char *psText) { char *s; int len, err=0; // Stick the string onto the stack len = strlen(psText)+1; s = (char *)ppl_memAlloc(len); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } snprintf(s, len, "%s", psText); ppl_listAppend(interp->colStack, (void *)s); // Also append to the postscript stack if ((err=dviPostscriptAppend(ec, interp, psText))!=0) return err; return 0; } // --------------------------------------- // Functions for manipulating interpreters // --------------------------------------- // Produce a new dvi interpreter (for a new dvi file, say) dviInterpreterState *dviNewInterpreter(pplerr_context *ec) { dviInterpreterState *interp; interp = (dviInterpreterState *)ppl_memAlloc(sizeof(dviInterpreterState)); if (interp==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } // Initially the stack is empty interp->stack = ppl_listInit(0); if (interp->stack==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } interp->output = (postscriptState *)ppl_memAlloc(sizeof(postscriptState)); if (interp->output==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } // No postscript yet interp->output->pages = ppl_listInit(0); if (interp->output->pages==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } interp->output->Npages = 0; interp->output->currentPage = NULL; interp->output->currentPosition = NULL; // Set default positional variables etc. interp->state = (dviStackState *)ppl_memAlloc(sizeof(dviStackState)); if (interp->state==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } interp->state->h=0; interp->state->v=0; interp->state->w=0; interp->state->x=0; interp->state->y=0; interp->state->z=0; interp->f=0; interp->curFnt = NULL; interp->boundingBox = NULL; interp->textSizeBox = NULL; interp->scale=0.0; // No string currently being assembled interp->currentString = NULL; interp->currentStrlen = 0; // No fonts currently interp->fonts = ppl_listInit(0); if (interp->fonts==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } // Nothing special occuring interp->special = 0; // Not in special mode interp->spString = NULL; interp->colStack = ppl_listInit(0); if (interp->colStack==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } // Make the big table of operators makeDviOpTable(ec); return interp; } // Delete an interpreter int dviDeleteInterpreter(pplerr_context *ec, dviInterpreterState *interp) { //free(interp->state); if (interp->currentStrlen != 0) { //free(interp->currentString); interp->currentStrlen=0; } // Delete anything on the stack interp->stack = ppl_listInit(0); if (interp->stack==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } // Delete any remaining postscript output if (interp->output != NULL) dviDeletePostscriptState(ec, interp->output); // Delete the interpreter shell //free(interp); return 0; } // Clone an interpreter state, returning a pointer to the new version // XXX Make the name of this function consistent with usage elsewhere or vice versa dviStackState *dviCloneInterpState(pplerr_context *ec, dviStackState *orig) { void *clone; clone = ppl_memAlloc(sizeof(dviStackState)); if (clone != NULL) memcpy(clone, (void *)orig, sizeof(dviStackState)); return (dviStackState *) clone; } // --------------------------------------------------------- // Functions for producing and manipulating postscript pages // --------------------------------------------------------- // Produce a new page of postscript postscriptPage *dviNewPostscriptPage(pplerr_context *ec) { postscriptPage *page; page = (postscriptPage *)ppl_memAlloc(sizeof(postscriptPage)); if (page==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } page->boundingBox = NULL; page->textSizeBox = NULL; //page->position[0] = 0; //page->position[1] = 0; page->text = ppl_listInit(0); if (page->text==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return NULL; } //page->currentPosition = NULL; // No position set initially return page; } // Delete a page of postscript output. If we didn't have lt_memory, we'd need to free things at this point. int dviDeletePostscriptPage(pplerr_context *ec, postscriptPage *page) { if (page->boundingBox != NULL) { //free(page->boundingBox); page->boundingBox = NULL; } if (page->textSizeBox != NULL) { page->textSizeBox = NULL; } // free page->text //free(page); return 0; } // Clear a set of postscript pages and state int dviDeletePostscriptState(pplerr_context *ec, postscriptState *state) { // free state->pages state->Npages = 0; state->currentPage = NULL; //free(state); return 0; } // ------------------------------------------- // Functions for producing postscript commands // ------------------------------------------- // Append a string to the set of postscript strings int dviPostscriptAppend(pplerr_context *ec, dviInterpreterState *interp, char *new) { char *s; // A temporary string pointer int len; // Grab the new string and copy it into place len = strlen(new)+1; s = (char *)ppl_memAlloc(len); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } strncpy(s, new, len); ppl_listAppend(interp->output->currentPage->text, (void *)s); return 0; } // Write some postscript to move to the current co-ordinates int dviPostscriptMoveto(pplerr_context *ec, dviInterpreterState *interp) { int err=0; char s[SSTR_LENGTH]; double x, y; x = interp->state->h * interp->scale; y = 765 - interp->state->v * interp->scale; snprintf(s, SSTR_LENGTH, "newpath\n%f %f moveto\n", x, y); if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; // If we don't have a current position make one, else set the current ps position to the dvi one if (interp->output->currentPosition == NULL) { interp->output->currentPosition = dviCloneInterpState(ec, interp->state); if (interp->output->currentPosition == NULL) return DVIE_MEMORY; } else { interp->output->currentPosition->h = interp->state->h; interp->output->currentPosition->v = interp->state->v; } return 0; } // Write some postscript to draw a line to the current co-ordinates int dviPostscriptLineto(pplerr_context *ec, dviInterpreterState *interp) { int err=0; char s[SSTR_LENGTH]; double x, y; x = interp->state->h * interp->scale; y = 765 - interp->state->v * interp->scale; snprintf(s, SSTR_LENGTH, "%f %f lineto\n", x, y); if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; // If we don't have a current position make one, else set the current ps position to the dvi one if (interp->output->currentPosition == NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"postscript error: lineto command issued with NULL current state!"); return DVIE_INTERNAL; } else { interp->output->currentPosition->h = interp->state->h; interp->output->currentPosition->v = interp->state->v; } return 0; } // Write some postscript to close a path int dviPostscriptClosepathFill(pplerr_context *ec, dviInterpreterState *interp) { int err=0; char s[SSTR_LENGTH]; //double x, y; //x = interp->state->h * interp->scale; //y = 765 - interp->state->v * interp->scale; snprintf(s, SSTR_LENGTH, "closepath fill\n"); if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; if (interp->output->currentPosition == NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"postscript error: closepath command issued with NULL current state!"); return DVIE_INTERNAL; } else { //free(interp->output->currentPosition); interp->output->currentPosition = NULL; } return 0; } // Typeset the current buffered text int dviTypeset(pplerr_context *ec, dviInterpreterState *interp) { // This subroutine does the bulk of the actual postscript work, typesetting runs of characters dviStackState *postPos, *dviPos; // Current positions in dvi and postscript code char *s; double width, height, depth, italic; double size[4]; // Width, height, depth int chars, err=0; postPos = interp->output->currentPosition; dviPos = interp->state; // First check if we need to move before typesetting if (postPos== NULL) { if ((err=dviPostscriptMoveto(ec, interp))!=0) return err; interp->output->currentPosition = dviCloneInterpState(ec, dviPos); if (interp->output->currentPosition == NULL) return DVIE_MEMORY; } else if (postPos->h != dviPos->h || postPos->v != dviPos->v) { if ((err=dviPostscriptMoveto(ec, interp))!=0) return err; } s = interp->currentString; width = 0.0; height = 0.0; depth = 0.0; italic = 0.0; while (*s != '\0') { if ((err=dviGetCharSize(ec, interp, (unsigned char) *s, size))!=0) return err; width += size[0]; height = size[1]>height ? size[1] : height; depth = size[2]>depth ? size[2] : depth; italic = size[3]; s++; } // Convert back into dvi units width /= interp->scale; height /= interp->scale; depth /= interp->scale; italic /= interp->scale; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: width of glyph %g height of glyph %g", width, height); ppl_log(ec, NULL); } // Only need to consider extra italic width for the final glyph if ((err=dviUpdateBoundingBox(ec, interp, width+italic, height, depth))!=0) return err; // Count the number of characters to write to the ps string chars = strlen(interp->currentString)+9; s = (char *)ppl_memAlloc(chars); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } snprintf(s, chars, "(%s) show\n", interp->currentString); // Send the string off to the postscript routine and clean up memory if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; //free(s); //free(interp->currentString); interp->currentString = NULL; interp->currentStrlen = 0; // Adjust the current position interp->state->h += width; interp->output->currentPosition->h += width; return 0; } // Change to a new font int dviChngFnt(pplerr_context *ec, dviInterpreterState *interp, int fn) { listIterator *listIter; int len, err=0; char *s; dviFontDetails *font; double size; interp->f = fn; // Find the font in the list interp->curFnt = NULL; listIter = ppl_listIterateInit(interp->fonts); while (listIter != NULL) { if (((dviFontDetails *)listIter->data)->number == fn) { interp->curFnt = (dviFontDetails *)listIter->data; break; } ppl_listIterate(&listIter); } // See whether we found the font, and if not, throw an error if (interp->curFnt == NULL) { ppl_error(ec, ERR_INTERNAL, -1, -1,"Corrupt DVI file: failed to find current font"); return DVIE_CORRUPT; } // Produce an appropriate postscript command font = (dviFontDetails *)listIter->data; len = strlen(font->psName) + 20; s = (char *)ppl_memAlloc(len); if (s==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } size = font->useSize*interp->scale; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: Font useSize %d size %g changed to %d", font->useSize, size, (int)ceil(size-.5)); ppl_log(ec, NULL); } snprintf(s, len, "/%s %d selectfont\n", font->psName, (int)ceil(size-.5)); if ((err=dviPostscriptAppend(ec, interp, s))!=0) return err; //free(s); return 0; } // Get the size (width, height, depth) of a glyph int dviGetCharSize(pplerr_context *ec, dviInterpreterState *interp, unsigned char s, double *size) { dviTFM *tfm; // Details of this font int chnum; // Character number in this font TFMcharInfo *chin; // Character info for this character int wi, hi, di, ii; // Indices dviFontDetails *font; // Font information (for tfm and use size) double scale; // Font use size * unit scaling font = (dviFontDetails *)interp->curFnt; tfm = font->tfm; chnum = s - tfm->bc; chin = tfm->charInfo+chnum; scale = font->useSize * interp->scale; wi = (int)chin->wi; hi = (int)chin->hi; di = (int)chin->di; ii = (int)chin->ii; size[0] = tfm->width[wi] * scale; size[1] = tfm->height[hi] * scale; size[2] = tfm->depth[di] * scale; size[3] = tfm->italic[ii] * scale; // The following loop adds a small quantity of padding as the supplied sizes appear to be somewhat insufficient size[1] += 0.05*scale; size[2] += 0.05*scale; if (DEBUG) { sprintf(ec->tempErrStr, "DVI: Character %d chnum %d has indices %d %d %d %d width %g height %g depth %g italic %g useSize %g desSize %g", s, chnum, wi, di, hi, ii, size[0], size[1], size[2], size[3], font->useSize*interp->scale, font->desSize*interp->scale); ppl_log(ec, NULL); } return 0; } // Update a bounding box with the position and size of the current object to be typeset int dviUpdateBoundingBox(pplerr_context *ec, dviInterpreterState *interp, double width, double height, double depth) { double *bb; double bbObj[4]; // Bounding box of the object that we are typeseting // left bottom right top // DVI counts down from the top (and this is all DVI units) bbObj[0] = interp->state->h; bbObj[1] = interp->state->v + depth; bbObj[2] = interp->state->h + width; bbObj[3] = interp->state->v - height; // Check to see if we already have a bounding box if (interp->boundingBox == NULL) { bb = (double *)ppl_memAlloc(4*sizeof(double)); if (bb==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } bb[0] = bbObj[0]; bb[1] = bbObj[1]; bb[2] = bbObj[2]; bb[3] = bbObj[3]; interp->boundingBox = bb; } else { // Check against current bounding box bb = interp->boundingBox; bb[0] = bb[0] < bbObj[0] ? bb[0] : bbObj[0]; bb[1] = bb[1] > bbObj[1] ? bb[1] : bbObj[1]; bb[2] = bb[2] > bbObj[2] ? bb[2] : bbObj[2]; bb[3] = bb[3] < bbObj[3] ? bb[3] : bbObj[3]; } // Now repeat the process for the text size box // This is the baseline and 70% of the use height, which we take to be the cap height bbObj[1] = interp->state->v; bbObj[3] = interp->state->v - interp->curFnt->useSize * 0.70; // Check to see if we already have a text size box if (interp->textSizeBox == NULL) { bb = (double *)ppl_memAlloc(4*sizeof(double)); if (bb==NULL) { ppl_error(ec, ERR_MEMORY, -1, -1, "Out of memory"); return DVIE_MEMORY; } bb[0] = bbObj[0]; bb[1] = bbObj[1]; bb[2] = bbObj[2]; bb[3] = bbObj[3]; interp->textSizeBox = bb; } else { // Check against current bounding box bb = interp->textSizeBox; bb[0] = bb[0] < bbObj[0] ? bb[0] : bbObj[0]; bb[1] = bb[1] > bbObj[1] ? bb[1] : bbObj[1]; bb[2] = bb[2] > bbObj[2] ? bb[2] : bbObj[2]; bb[3] = bb[3] < bbObj[3] ? bb[3] : bbObj[3]; } return 0; } pyxplot-0.9.2/src/epsMaker/dvi_read.h0000664000175000017500000001464612026340554016123 0ustar dcf21dcf21// dvi_read.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dvi_read.h 1270 2012-07-18 22:02:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating dvi files #ifndef _PPL_DVI_READ_H #define _PPL_DVI_READ_H 1 #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "epsMaker/dvi_font.h" // Structure to store a DVI operator and the data that goes with it typedef struct DVIOperator { unsigned char op; unsigned long int ul[10]; signed long int sl[2]; char *s[2]; } DVIOperator; // Structure to store the state of a dvi interpreter that can be pushed onto the stack typedef struct dviStackState { signed long int h,v,w,x,y,z; } dviStackState; // Structure to store a page of postscript typedef struct postscriptPage { double *boundingBox; // The current bounding box double *textSizeBox; // The current text size box (b.box plus oversize text) list *text; // The big list of strings of postscript } postscriptPage; // Structure to store the state of some postscript in the process of being produced typedef struct postscriptState { list *pages; // List of pages of postscript int Npages; // The number of pages postscriptPage *currentPage; // The current page dviStackState *currentPosition; // The current position in dvi units } postscriptState; // Structure to store the entire internal state of a dvi interpreter typedef struct dviInterpreterState { dviStackState *state; // h,v,w,x,y,z; // Positions unsigned int f; // Current font dviFontDetails *curFnt; // and a pointer to it char *currentString; // The string, if any, currently being rendered int currentStrlen; // and its current length double scale; // Scale from dvi->ps units list *stack; // The stack list *fonts; // The fonts currently defined postscriptState *output; // The output postscript int special; // A magic flag for special actions int specialLen; // Number of characters in special command char *spString; // String to store special information list *colStack; // Stack of colour items double *boundingBox; // Current bounding box double *textSizeBox; // Current text size box } dviInterpreterState; // Functions allowing dvi interpreters to be manipulated dviInterpreterState *ReadDviFile(pplerr_context *ec, char *filename, int *status); dviInterpreterState *dviNewInterpreter(pplerr_context *ec); int dviInterpretOperator(pplerr_context *ec, dviInterpreterState *interp, DVIOperator *op); int dviDeleteInterpreter(pplerr_context *ec, dviInterpreterState *interp); int dviTypeset(pplerr_context *ec, dviInterpreterState *interp); dviStackState *dviCloneInterpState(pplerr_context *ec, dviStackState *state); postscriptPage *dviNewPostscriptPage(pplerr_context *ec); int dviDeletePostscriptPage(pplerr_context *ec, postscriptPage *page); int dviDeletePostscriptState(pplerr_context *ec, postscriptState *state); int dviPostscriptMoveto(pplerr_context *ec, dviInterpreterState *interp); int dviPostscriptAppend(pplerr_context *ec, dviInterpreterState *interp, char *s); int dviGetCharSize(pplerr_context *ec, dviInterpreterState *interp, unsigned char s, double *size); // Routines for reading from files int ReadUChar(pplerr_context *ec, FILE *fp, int *uc); int ReadLongInt(pplerr_context *ec, FILE *fp, unsigned long int *uli, int n); int ReadSignedInt(pplerr_context *ec, FILE *fp, signed long int *sli, int n); double ReadFixWord(pplerr_context *ec, FILE *fp, int *err); int DisplayDVIOperator(pplerr_context *ec, DVIOperator *op); int GetDVIOperator(pplerr_context *ec, DVIOperator *op, FILE *fp); // The following definitions are taken from PyX #define DVI_CHARMIN 0 // typeset a character and move right (range min) #define DVI_CHARMAX 127 // typeset a character and move right (range max) #define DVI_SET1234 128 // typeset a character and move right #define DVI_SETRULE 132 // typeset a rule and move right #define DVI_PUT1234 133 // typeset a character #define DVI_PUTRULE 137 // typeset a rule #define DVI_NOP 138 // no operation #define DVI_BOP 139 // beginning of page #define DVI_EOP 140 // ending of page #define DVI_PUSH 141 // save the current positions (h, v, w, x, y, z) #define DVI_POP 142 // restore positions (h, v, w, x, y, z) #define DVI_RIGHT1234 143 // move right #define DVI_W0 147 // move right by w #define DVI_W1234 148 // move right and set w #define DVI_X0 152 // move right by x #define DVI_X1234 153 // move right and set x #define DVI_DOWN1234 157 // move down #define DVI_Y0 161 // move down by y #define DVI_Y1234 162 // move down and set y #define DVI_Z0 166 // move down by z #define DVI_Z1234 167 // move down and set z #define DVI_FNTNUMMIN 171 // set current font (range min) #define DVI_FNTNUMMAX 234 // set current font (range max) #define DVI_FNT1234 238 // set current font #define DVI_SPECIAL1234 239 // special (dvi extention) #define DVI_FNTDEF1234 243 // define the meaning of a font number #define DVI_PRE 247 // preamble #define DVI_POST 248 // postamble beginning #define DVI_POSTPOST 249 // postamble ending #define DVI_VERSION 2 // dvi version // true and false #define DVI_YES 1 #define DVI_NO 0 // Error states // Errors related to file operations #define DVIE_NOENT 10 #define DVIE_EOF 11 #define DVIE_ACCESS 12 // Errors related to malformed/corrupted/missing files #define DVIE_CORRUPT 20 #define DVIE_NOFONT 21 // Internal errors (inconsistent internal state => bug!) #define DVIE_MEMORY 30 #define DVIE_INTERNAL 31 #endif pyxplot-0.9.2/src/epsMaker/eps_plot_filledregion.c0000664000175000017500000005017012026340554020701 0ustar dcf21dcf21// eps_plot_filledregion.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eps_plot_filledregion.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_EPS_PLOT_FILLEDREGION_C 1 #include #include #include #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "coreUtils/errorReport.h" #include "epsMaker/eps_comm.h" #include "epsMaker/eps_core.h" #include "epsMaker/eps_plot_canvas.h" #include "epsMaker/eps_plot_filledregion.h" #include "epsMaker/eps_plot_linedraw.h" #include "epsMaker/eps_settings.h" FilledRegionHandle *FilledRegion_Init (EPSComm *x, pplset_axis *xa, pplset_axis *ya, pplset_axis *za, int xrn, int yrn, int zrn, pplset_graph *sg, unsigned char ThreeDim, double origin_x, double origin_y, double width, double height, double zdepth) { FilledRegionHandle *output; output = (FilledRegionHandle *)ppl_memAlloc(sizeof(FilledRegionHandle)); if (output==NULL) return NULL; output->x = x; output->xa = xa; output->ya = ya; output->za = za; output->xrn = xrn; output->yrn = yrn; output->zrn = zrn; output->sg = sg; output->ThreeDim = ThreeDim; output->origin_x = origin_x; output->origin_y = origin_y; output->width = width; output->height = height; output->zdepth = zdepth; output->Naxiscrossings = 0; output->first = 1; output->EverInside = 0; output->points = ppl_listInit(0); return output; } void FilledRegion_Point(EPSComm *X, FilledRegionHandle *fr, double x, double y) { FilledRegionPoint p; double xpos, ypos, depth, xap, yap, zap, ap1, ap2; unsigned char f1, f2; int NCrossings, i1, i2; double cx1,cy1,cz1,cx2,cy2,cz2; // Work out where (x,y) in coordinate space lies on the canvas eps_plot_GetPosition(&xpos, &ypos, &depth, &xap, &yap, &zap, NULL, NULL, NULL, fr->ThreeDim, x, y, 0, fr->xa, fr->ya, fr->za, fr->xrn, fr->yrn, fr->zrn, fr->sg, fr->origin_x, fr->origin_y, fr->width, fr->height, fr->zdepth, 1); if ((!gsl_finite(xpos))||(!gsl_finite(ypos))||(!gsl_finite(depth))) { return; } // Add this to a list of points describing the outline of the region which we are going to fill p.inside = ((xap>=0)&&(xap<=1)&&(yap>=0)&&(yap<=1)&&(zap>=0)&&(zap<=1)); p.FillSideFlip_fwd = 0; p.FillSideFlip_prv = 0; p.x = xpos; p.y = ypos; p.xa = x; p.ya = y; p.xap = xap; p.yap = yap; ppl_listAppendCpy(fr->points, (void *)&p, sizeof(p)); // Count the number of times which the path crosses the boundary of the clip region if (!fr->first) { LineDraw_FindCrossingPoints(X, fr->lastx,fr->lasty,0,fr->lastxap,fr->lastyap,0.5, xpos,ypos,0,xap,yap,0.5,&i1,&i2,&cx1,&cy1,&cz1,&cx2,&cy2,&cz2,&f1,&ap1,&f2,&ap2,&NCrossings); fr->Naxiscrossings += NCrossings; fr->EverInside = (fr->EverInside) || (NCrossings>0) || i1 || i2; } fr->lastx = xpos; fr->lasty = ypos; fr->lastxap = xap; fr->lastyap = yap; fr->first = 0; return; } static int frac_sorter(const void *av, const void *bv) { const FilledRegionAxisCrossing *a = (const FilledRegionAxisCrossing *)av; const FilledRegionAxisCrossing *b = (const FilledRegionAxisCrossing *)bv; if (b->AxisFace > a->AxisFace) return -1; if (b->AxisFace < a->AxisFace) return 1; if (b->AxisFace < FACE_BOTTOM) // Sort top from right to left, and left from top to bottom { if (b->AxisPos > a->AxisPos) return 1; else if (b->AxisPos < a->AxisPos) return -1; } else // Sort bottom from left to right, and right from bottom to top { if (b->AxisPos > a->AxisPos) return -1; else if (b->AxisPos < a->AxisPos) return 1; } return 0; } static unsigned char TestPointInside(FilledRegionHandle *fr, double X, double Y, int dir_x, int dir_y) { unsigned char inside; double x_intersect, y_intersect; int i, n, Npoints; listItem *li1, *li2; FilledRegionPoint *p1, *p2; // Move fractionally off test point if (dir_x==-1) X -= fabs(1e-15*X); else if (dir_x== 1) X += fabs(1e-15*X); else if (dir_y==-1) Y -= fabs(1e-15*X); else if (dir_y== 1) Y += fabs(1e-15*X); Npoints = fr->points->length; li2 = fr->points->first; p2 = (FilledRegionPoint *)(li2->data); // Loop around perimeter of region which we are going to fill for (i=n=0; inext; if (li2==NULL) li2=fr->points->first; p2 = (FilledRegionPoint *)(li2->data); // p1 -> p2 is a line segment of perimeter // Count how many segments cross lines travelling out up/left/down/right from (X,Y) if (dir_x==0) { y_intersect = (p2->y - p1->y)/(p2->x - p1->x)*(X - p1->x) + p1->y; // y point where line p1->p2 intersects x=X if ((gsl_finite(y_intersect)) && (((X>=p1->x)&&(Xx)) || ((X<=p1->x)&&(X>p2->x))) && (((dir_y>0)&&(y_intersect>Y)) || ((dir_y<0)&&(y_intersectx - p1->x)/(p2->y - p1->y)*(Y - p1->y) + p1->x; // x point where line p1->p2 intersects y=Y if ((gsl_finite(x_intersect)) && (((Y>=p1->y)&&(Yy)) || ((Y<=p1->y)&&(Y>p2->y))) && (((dir_x>0)&&(x_intersect>X)) || ((dir_x<0)&&(x_intersectx->c->errcontext.tempErrStr,"Hopping to (%e,%e).",X,Y); ppl_log(&fr->x->c->errcontext,NULL); } \ if (first_subpath) { fprintf(fr->x->epsbuffer, "newpath "); first_subpath=0; } \ if (first_point) { fprintf(fr->x->epsbuffer, "%.2f %.2f moveto\n", X, Y); first_point=0; } \ else { fprintf(fr->x->epsbuffer, "%.2f %.2f lineto\n", X, Y); } \ eps_core_BoundingBox(fr->x, X, Y, linewidth * EPS_DEFAULT_LINEWIDTH); \ } static void OutputPath(FilledRegionHandle *fr, FilledRegionAxisCrossing *CrossPointList, int nac, char *EndText, double linewidth) { unsigned char face, sense, inside_ahead, FillSide, CurrentFace, first_point=1, first_subpath=1, fail=0; int i, inew, j, k, l, dir_x, dir_y; listItem *li, *lil=NULL; FilledRegionPoint *p; // Clear used flags for (i=0; ix->c->errcontext,"New filled region."); } while (!fail) { // Find an axis crossing point which is unique l=-1; for (i=0; ix->c->errcontext,"All axis-crossing points used."); } break; } i=l; // Debugging lines if (DEBUG) { int i; ppl_log(&fr->x->c->errcontext,"New segment of filled region."); ppl_log(&fr->x->c->errcontext,"Summary of axis crossing points:"); for (i=0; ix->c->errcontext.tempErrStr,"%d %s (%e,%e) face %d position %.4f sense %s %s",i, CrossPointList[i].used?"[used]":" ", CrossPointList[i].x, CrossPointList[i].y, (int)CrossPointList[i].AxisFace, CrossPointList[i].AxisPos, (CrossPointList[i].sense==INCOMING)?"incoming":"outgoing", CrossPointList[i].singleton?"[singleton]":""); ppl_log(&fr->x->c->errcontext,NULL); } } // Work out which face first axis crossing is on, and which direction we're moving going to next item in crossing point list face = CrossPointList[i].AxisFace; if (face==FACE_TOP ) { dir_x=-1; dir_y= 0; } else if (face==FACE_LEFT ) { dir_x= 0; dir_y=-1; } else if (face==FACE_BOTTOM) { dir_x= 1; dir_y= 0; } else { dir_x= 0; dir_y= 1; } inside_ahead = TestPointInside(fr, CrossPointList[i].x, CrossPointList[i].y, dir_x, dir_y); // Decide whether we are proceeding clockwise or anticlockwise around the region we're going to fill FillSide = inside_ahead; if (DEBUG) { sprintf(fr->x->c->errcontext.tempErrStr,"Starting from %d; filling on %s.",i,FillSide?"right":"left"); ppl_log(&fr->x->c->errcontext,NULL); } while (1) { CrossPointList[i].used = 1; if (CrossPointList[i].singleton) // Move along a line segment which streaks across canvas in one step { PS_POINT(CrossPointList[i].x , CrossPointList[i].y ); // Cut point where line enters canvas PS_POINT(CrossPointList[i].x2, CrossPointList[i].y2); // Cut point where line leaves canvas if (((FilledRegionPoint *)CrossPointList[i].point->data)->FillSideFlip_prv%2) FillSide = !FillSide; for (inew=0; inew=nac) { ppl_error(&fr->x->c->errcontext,ERR_INTERNAL, -1, -1, "Failure within FilledRegion"); fail=1; break; } if (DEBUG) { sprintf(fr->x->c->errcontext.tempErrStr,"Twin of %d is %d.",i,inew); ppl_log(&fr->x->c->errcontext,NULL); } i = inew; CrossPointList[i].used = 1; } else // Follow a path across the canvas, step by step { PS_POINT(CrossPointList[i].x, CrossPointList[i].y); // Cut point where line enters canvas li = CrossPointList[i].point; sense = CrossPointList[i].sense; if (sense == OUTGOING) { li=li->prev; if (li==NULL) li=fr->points->last; } p = (FilledRegionPoint *)(li->data); while (p->inside) { PS_POINT(p->x, p->y); if ((sense == OUTGOING) && (p->FillSideFlip_fwd%2)) FillSide = !FillSide; else if ((sense == INCOMING) && (p->FillSideFlip_prv%2)) FillSide = !FillSide; lil=li; if (sense == OUTGOING) { li=li->prev; if (li==NULL) li=fr->points->last; } // Moving against flow in which line was originally drawn else { li=li->next; if (li==NULL) li=fr->points->first; } // Moving with flow in which line was originally drawn p=(FilledRegionPoint *)(li->data); } if ((sense == OUTGOING) && (p->FillSideFlip_fwd%2)) FillSide = !FillSide; else if ((sense == INCOMING) && (p->FillSideFlip_prv%2)) FillSide = !FillSide; for (i=0; ix->c->errcontext,ERR_INTERNAL, -1, -1, "Failure within FilledRegion"); fail=1; break; } PS_POINT(CrossPointList[i].x, CrossPointList[i].y); // Cut point where line leaves canvas if (DEBUG) { sprintf(fr->x->c->errcontext.tempErrStr, "Departed canvas at crossing point %d.", i); ppl_log(&fr->x->c->errcontext,NULL); } CrossPointList[i].used = 1; } // Skirt along edge of clip region to find next entry point for (k=i; ((CrossPointList[i].x==CrossPointList[k].x)&&(CrossPointList[i].y==CrossPointList[k].y)); k=(k+1)%nac) if (!CrossPointList[k].used) { i=k; FillSide = !FillSide; continue; } for (k=i; ((CrossPointList[i].x==CrossPointList[k].x)&&(CrossPointList[i].y==CrossPointList[k].y)); k=(k+nac-1)%nac) if (!CrossPointList[k].used) { i=k; FillSide = !FillSide; continue; } if (FillSide) j=(i+nac-1)%nac; // Move anticlockwise around path else j=(i+1)%nac; // Move clockwise around path CurrentFace = CrossPointList[i].AxisFace; if (DEBUG) { sprintf(fr->x->c->errcontext.tempErrStr, "Move along edge of canvas from %d to %d; filling on %s; moving from axis face %d to %d.",i,j,FillSide?"right":"left",(int)CrossPointList[i].AxisFace,(int)CrossPointList[j].AxisFace); ppl_log(&fr->x->c->errcontext,NULL); } while (CurrentFace != CrossPointList[j].AxisFace) // If we've changed side of clip region, add corner to path { double xap,yap; const double xaps[6] = {9,1,0,0,1,1}; const double yaps[6] = {9,1,1,0,0,1}; if (!FillSide) { xap=xaps[CurrentFace+1]; yap=yaps[CurrentFace+1]; CurrentFace= (CurrentFace %4)+1; } else { xap=xaps[CurrentFace ]; yap=yaps[CurrentFace ]; CurrentFace=((CurrentFace+2)%4)+1; } if (DEBUG) { sprintf(fr->x->c->errcontext.tempErrStr, "Corner (%e,%e)", xap, yap); ppl_log(&fr->x->c->errcontext,NULL); } if (!fr->ThreeDim) { PS_POINT(fr->origin_x + fr->width * xap, fr->origin_y + fr->height * yap); } else { PS_POINT(fr->origin_x + fr->width/2 + (xap-0.5)*fr->width*cos(fr->sg->XYview.real) + (yap-0.5)*fr->height*sin(fr->sg->XYview.real), fr->origin_y + fr->height/2 - (xap-0.5)*fr->width*cos(fr->sg->YZview.real)*sin(fr->sg->XYview.real) + (yap-0.5)*fr->height*cos(fr->sg->YZview.real)*cos(fr->sg->XYview.real)); } } i=j; if (CrossPointList[i].used) break; } if (!first_point) { fprintf(fr->x->epsbuffer, "closepath\n"); } first_point=1; if (DEBUG) { ppl_log(&fr->x->c->errcontext,"End segment."); } } if (DEBUG) { ppl_log(&fr->x->c->errcontext,"End filled region."); } if (!first_point) { fprintf(fr->x->epsbuffer, "closepath\n"); } fprintf(fr->x->epsbuffer, "%s\n", EndText); return; } void FilledRegion_Finish(EPSComm *X, FilledRegionHandle *fr, int linetype, double linewidth, unsigned char StrokeOutline) { unsigned char f1, f2, first_point=1, first_subpath=1; int i, j, k, kn, l, NCrossings, i1, i2; double lastx, lasty, lastxap, lastyap; double cx1,cy1,cz1,cx2,cy2,cz2,ap1,ap2; listItem *li; FilledRegionPoint *p, *last_p; FilledRegionAxisCrossing *CrossPointList; double ct_y_m1, ct_y_c1, ct_x_m1, ct_x_c1, ct_y_m2, ct_y_c2, ct_x_m2, ct_x_c2, ct_xi, ct_yi; listItem *ct_li; FilledRegionPoint *ct_pA, *ct_pB; const EPSComm *x = fr->x; // Makes IF_NOT_INVISIBLE macro work l = fr->points->length; li = fr->points->first; if (l < 2) return; // No points on outline to stroke if (!fr->EverInside) return; // Path never ventures within clip region eps_core_WritePSColor(fr->x); // Path never goes outside the clip region if (fr->Naxiscrossings < 1) { if (DEBUG) { ppl_log(&fr->x->c->errcontext,"New filled region never leaves clip region."); } if (DEBUG) { ppl_log(&fr->x->c->errcontext,"1. Fill it."); } IF_NOT_INVISIBLE { for (i=0; idata); PS_POINT(p->x, p->y); li=li->next; } fprintf(fr->x->epsbuffer, "closepath eofill\n"); } eps_core_SwitchFrom_FillColor(fr->x,1); if (!StrokeOutline) return; eps_core_SetLinewidth(fr->x, linewidth, linetype, 0.0); li = fr->points->first; first_point=first_subpath=1; if (DEBUG) { ppl_log(&fr->x->c->errcontext,"2. Stroke its outline."); } IF_NOT_INVISIBLE { for (i=0; idata); PS_POINT(p->x, p->y); li=li->next; } fprintf(fr->x->epsbuffer, "closepath stroke\n"); } return; } // Close path to get potential final axis crossing p = (FilledRegionPoint *)(li->data); FilledRegion_Point(fr->x, fr, p->xa, p->ya); // Add first point to end of point list l = fr->points->length; lastx = p->x; lasty = p->y; lastxap = p->xap; lastyap = p->yap; last_p = p; li=li->next; // Malloc a structure to hold the positions of all of the points where we cross the boundary of the clip region CrossPointList = (FilledRegionAxisCrossing *)ppl_memAlloc(fr->Naxiscrossings * 2 * sizeof(FilledRegionAxisCrossing)); if (CrossPointList == NULL) return; for (i=1,j=0; idata); LineDraw_FindCrossingPoints(fr->x,lastx,lasty,0,lastxap,lastyap,0.5,p->x,p->y,0,p->xap,p->yap,0.5,&i1,&i2,&cx1,&cy1,&cz1,&cx2,&cy2,&cz2,&f1,&ap1,&f2,&ap2,&NCrossings); // Check for whether line crosses a previous line segment; if so, flip fill side ct_y_m1 = (cy2-cy1)/(cx2-cx1); ct_y_c1 = cy1 - ct_y_m1 * cx1; ct_x_m1 = (cx2-cx1)/(cy2-cy1); ct_x_c1 = cx1 - ct_x_m1 * cy1; ct_li = fr->points->first; ct_pB = (FilledRegionPoint *)(ct_li->data); ct_li = ct_li->next; for (k=1,kn=0; k<(i-1); k++) { ct_pA = ct_pB; ct_pB = (FilledRegionPoint *)(ct_li->data); ct_li = ct_li->next; ct_y_m2 = (ct_pB->y-ct_pA->y)/(ct_pB->x-ct_pA->x); ct_y_c2 = ct_pA->y - ct_y_m2 * ct_pA->x; ct_x_m2 = (ct_pB->x-ct_pA->x)/(ct_pB->y-ct_pA->y); ct_x_c2 = ct_pA->x - ct_x_m2 * ct_pA->y; ct_xi = (ct_y_c2-ct_y_c1)/(ct_y_m1-ct_y_m2); ct_yi = (ct_x_c2-ct_x_c1)/(ct_x_m1-ct_x_m2); if ((gsl_finite(ct_xi))&&(((ct_xi>=cx1 )&&(ct_xicx2 ))) &&(((ct_xi>=ct_pA->x)&&(ct_xix)) || ((ct_xi<=ct_pA->x)&&(ct_xi>ct_pB->x))) ) { kn++; ct_pB->FillSideFlip_prv++; ct_pB->FillSideFlip_fwd++; } else if ((gsl_finite(ct_yi))&&(((ct_yi>=cy1 )&&(ct_yicy2 ))) &&(((ct_yi>=ct_pA->y)&&(ct_yiy)) || ((ct_yi<=ct_pA->y)&&(ct_yi>ct_pB->y))) ) { kn++; ct_pB->FillSideFlip_prv++; ct_pB->FillSideFlip_fwd++; } } p ->FillSideFlip_prv = kn; last_p->FillSideFlip_fwd = kn; if ( ((!i1)||(!i2)) && (NCrossings>0) ) // We have crossed boundary { if (!i1) { CrossPointList[j].x = cx1; CrossPointList[j].y = cy1; CrossPointList[j].AxisFace = f1; CrossPointList[j].AxisPos = ap1; } else { CrossPointList[j].x = cx2; CrossPointList[j].y = cy2; CrossPointList[j].AxisFace = f2; CrossPointList[j].AxisPos = ap2; } if ((!i1)&&(!i2)) { CrossPointList[j].x2 = cx2; CrossPointList[j].y2 = cy2; } CrossPointList[j].id = j; CrossPointList[j].singleton = ((!i1)&&(!i2)); CrossPointList[j].twin = j+1; CrossPointList[j].sense = (i1) ? OUTGOING : INCOMING; CrossPointList[j].point = li; CrossPointList[j].used = 0; j++; } if ( ((!i1)&&(!i2)) && (NCrossings>0) ) { CrossPointList[j] = CrossPointList[j-1]; CrossPointList[j].x = cx2; CrossPointList[j].y = cy2; CrossPointList[j].x2= cx1; CrossPointList[j].y2= cy1; CrossPointList[j].id = j; CrossPointList[j].AxisFace = f2; CrossPointList[j].AxisPos = ap2; CrossPointList[j].sense = OUTGOING; CrossPointList[j].twin = j-1; j++; } lastx = p->x; lasty = p->y; lastxap = p->xap; lastyap = p->yap; last_p = p; li=li->next; } // Sort list into order around perimeter of clipping area qsort((void *)CrossPointList, j, sizeof(FilledRegionAxisCrossing), &frac_sorter); // Output path if (DEBUG) { ppl_log(&fr->x->c->errcontext,"New filled region which crosses edge of clip region."); } if (DEBUG) { ppl_log(&fr->x->c->errcontext,"1. Fill it."); } IF_NOT_INVISIBLE OutputPath(fr, CrossPointList, j, "eofill", linewidth); eps_core_SwitchFrom_FillColor(fr->x,1); if (!StrokeOutline) return; eps_core_SetLinewidth(fr->x, linewidth, linetype, 0.0); li = fr->points->first; if (DEBUG) { ppl_log(&fr->x->c->errcontext,"2. Stroke its outline."); } IF_NOT_INVISIBLE OutputPath(fr, CrossPointList, j, "stroke", linewidth); return; } pyxplot-0.9.2/src/parser/0000775000175000017500000000000012026340554013707 5ustar dcf21dcf21pyxplot-0.9.2/src/parser/parser.h0000664000175000017500000000777512026340554015374 0ustar dcf21dcf21// parser.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: parser.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PARSER_H #define _PARSER_H 1 #include "coreUtils/list.h" #include "expressions/expCompile.h" #include "userspace/context.h" #include "userspace/pplObj.h" #define PN_TYPE_SEQ 21000 #define PN_TYPE_OPT 21001 #define PN_TYPE_REP 21002 // Must have at least one repeat item #define PN_TYPE_REP2 21003 // Can have zero items #define PN_TYPE_PER 21004 #define PN_TYPE_ORA 21005 #define PN_TYPE_ITEM 21006 #define PN_TYPE_CONFIRM 21007 // The = token in RE++ #define PN_TYPE_DATABLK 21008 #define PN_TYPE_CODEBLK 21009 typedef struct parserNode { int type; int listLen; char *matchString; // ITEMs only char *outString; // " int acLevel; // " char *varName; int outStackPos; struct parserNode *firstChild; struct parserNode *nextSibling; } parserNode; #define PARSER_TYPE_OPTIONS 8 typedef struct parserAtom { int stackOutPos; int linePos; // Position of this atom in the string copy of the line, used for error reporting char options[PARSER_TYPE_OPTIONS]; // characters, e.g. 'd' if %d is an allowed kind of value for this variable pplExpr *expr; pplObj *literal; struct parserAtom *next; } parserAtom; typedef struct parserLine { char *linetxt; int srcLineN; long srcId; char *srcFname; int stackLen, stackOffset; int containsMacros, refCount; parserAtom *firstAtom, *lastAtom; struct parserLine *next, *prev; } parserLine; typedef struct parserStatus { char prompt[64]; parserLine **rootpl; parserLine *pl [MAX_RECURSION_DEPTH]; parserNode *stk[MAX_RECURSION_DEPTH][16]; int oldStackOffset[MAX_RECURSION_DEPTH][16]; int blockDepth; int NinlineDatafiles[MAX_RECURSION_DEPTH]; int waitingForBrace, outputPos[MAX_RECURSION_DEPTH]; char expectingList[LSTR_LENGTH]; int eLPos, eLlinePos; } parserStatus; typedef struct parserOutput { int *stkCharPos; pplObj *stk; int stackLen; } parserOutput; #ifndef _PARSERINIT_C extern list *pplParserCmdList[]; #endif int ppl_parserInit (ppl_context *c); void ppl_parserAtomAdd (parserLine *in, int stackOutPos, int linePos, char *options, pplExpr *expr, pplObj *literal); void ppl_parserAtomFree (parserAtom **in); void ppl_parserLineFree (parserLine *in); void ppl_parserStatInit (parserStatus **in, parserLine **pl); void ppl_parserStatReInit(parserStatus *in); void ppl_parserStatAdd (parserStatus *in, int level, parserLine *pl); void ppl_parserStatFree (parserStatus **in); void ppl_parserLineInit (parserLine **in, int srcLineN, long srcId, char *srcFname, char *line); int ppl_parserCompile (ppl_context *c, parserStatus *s, int srcLineN, long srcId, char *srcFname, char *line, int expandMacros, int blockDepth); void ppl_parserLinePrint (ppl_context *c, parserLine *in); void ppl_parserExecute (ppl_context *c, parserLine *in, char *dirName, int interactive, int iterDepth); void ppl_parserShell (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #ifdef HAVE_READLINE void ppl_parseAutocompleteSetContext(ppl_context *c); char **ppl_rl_completion (const char *text, int start, int end); #endif #endif pyxplot-0.9.2/src/parser/parserInit.c0000664000175000017500000003510212026340554016174 0ustar dcf21dcf21// parserInit.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: parserInit.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PARSERINIT_C 1 #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" list *pplParserCmdList[27]; static void ppl_parserStartNode(pplerr_context *c, parserNode **stk, int *i, int type) { parserNode *newNode = (parserNode *)malloc(sizeof(parserNode)); if (newNode==NULL) { ppl_fatal(c,__FILE__,__LINE__,"Out of memory."); exit(1); } newNode->type = type; newNode->listLen = -1; newNode->acLevel = -1; newNode->outStackPos = -1; newNode->matchString = NULL; newNode->outString = NULL; newNode->varName = NULL; newNode->firstChild = newNode->nextSibling = NULL; if ((*i)>0) // If this new node is not the root context, check whether we need to insert an implicit sequence between *list* *seq* STUFF stuff stuff *endseq* *endlist* { parserNode **target = NULL; if ( (stk[(*i)-1]->type != PN_TYPE_SEQ) && (type != PN_TYPE_SEQ) ) ppl_parserStartNode(c, stk, i, PN_TYPE_SEQ); target = &(stk[(*i)-1]->firstChild); // Pointer to where first child of parent is linked while (*target != NULL) target = &((*target)->nextSibling); // If not first child of parent, traverse linked list to end *target = newNode; // Add new node into hierarchy, either as first child of parent, or into linked list of siblings } stk[(*i)++] = newNode; // Add new node structure to context stack return; } static void ppl_parserRollBack(pplerr_context *c, parserNode **stk, int *i, int type, const char *cmdText, int *NcharsTaken) { int j=1; // Count characters taken; start at 1 for closing bracket int varNameStart=-1, varNameEnd=-1; while (((*i)>0) && (stk[(*i)-1]->type == PN_TYPE_SEQ)) (*i)--; // Automatically close SEQs; they don't have closing grammar if ((*i)<=0) { sprintf(c->tempErrStr, "Incorrect nesting of types in command specification -- attempt to close an unopened bracket."); ppl_fatal(c,__FILE__,__LINE__, NULL); } else if (stk[(*i)-1]->type != type) { sprintf(c->tempErrStr, "Incorrect nesting of types in command specification -- expected %d, but got %d.", type, stk[(*i)-1]->type); ppl_fatal(c,__FILE__,__LINE__, NULL); } if (cmdText[j]=='@') { int k,l; if (type!=PN_TYPE_REP) { sprintf(c->tempErrStr, "Unexpected storage information after non [ ] data structure."); ppl_fatal(c,__FILE__,__LINE__, NULL); } j++; if (cmdText[j]=='0') { type=PN_TYPE_REP2; stk[(*i)-1]->type=type; j++; } // If storage variable name begins '0', zero repeats are allowed; a REP2 item, not a REP item if ((cmdText[j]>' ')&&(cmdText[j]!='@')) { varNameStart = j; while ((cmdText[j]>' ')&&(cmdText[j]!='@')) j++; // FFW over variable name varNameEnd = j; } if (cmdText[j++]!='@') { sprintf(c->tempErrStr, "Syntax error: expecting @ after ]@varname..."); ppl_fatal(c,__FILE__,__LINE__, NULL); } while ((cmdText[j]>' ')&&(cmdText[j]!='@')) j++; if (cmdText[j++]!='@') { sprintf(c->tempErrStr, "Syntax error: expecting @ after ]@varname@value..."); ppl_fatal(c,__FILE__,__LINE__, NULL); } while ((cmdText[j]>' ')&&(cmdText[j]!='@')) j++; if (cmdText[j++]!='@') { sprintf(c->tempErrStr, "Syntax error: expecting @ after ]@varname@value@ACL..."); ppl_fatal(c,__FILE__,__LINE__, NULL); } k=(int)ppl_getFloat(cmdText+j,NULL); while ((cmdText[j]>' ')&&(cmdText[j]!='@')) j++; stk[(*i)-1]->outStackPos = k; if (cmdText[j++]!='@') { sprintf(c->tempErrStr, "Syntax error: expecting @ after ]@varname@value@ACL@stackpos..."); ppl_fatal(c,__FILE__,__LINE__, NULL); } l=(int)ppl_getFloat(cmdText+j,NULL); while ((cmdText[j]>' ')&&(cmdText[j]!='@')) j++; stk[(*i)-1]->listLen = l; while ((cmdText[j]!='\0') && (cmdText[j]!='\n') && (cmdText[j]<' ')) j++; // FFW over trailing whitespace if (varNameStart > -1) { stk[(*i)-1]->varName = (char *)malloc((varNameEnd-varNameStart+1)*sizeof(char)); if (stk[(*i)-1]->varName == NULL) { ppl_fatal(c,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } strncpy( stk[(*i)-1]->varName , cmdText+varNameStart , varNameEnd-varNameStart ); stk[(*i)-1]->varName[varNameEnd - varNameStart] = '\0'; } } (*i)--; // Close structure of type "type" and roll back stack. *NcharsTaken = j; return; } int ppl_parserInit(ppl_context *c) { pplerr_context *e = &c->errcontext; int i; int inPos=0; for (i=0; i<27; i++) { pplParserCmdList[i] = ppl_listInit(1); if (pplParserCmdList[i]==NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory."); exit(1); } } // Loop over instructions in command list while (1) { int stackPos=0, cmdLetter, rootStackLen, nc=0; parserNode *defnStack[16]; while ((ppl_cmdList[inPos] != '\0') && (ppl_cmdList[inPos] <= ' ')) inPos++; // Ignore whitespace rootStackLen = (int)ppl_getFloat(ppl_cmdList+inPos, &nc); // Each line of command list begins with the length of the root stack namespace inPos+=nc; while ((ppl_cmdList[inPos] != '\0') && (ppl_cmdList[inPos] <= ' ')) inPos++; // Ignore whitespace if (ppl_cmdList[inPos] == '\0') break; // End of cmdList -- all instructions have now been read if ((ppl_cmdList[inPos]>='@')&&(ppl_cmdList[inPos+1]>='a')&&(ppl_cmdList[inPos+1]<='z')) cmdLetter = (int)(ppl_cmdList[inPos+1]-'a'); else cmdLetter = 26; // Begins with punctuation ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_SEQ); defnStack[0]->listLen = rootStackLen; // Loop over words in instruction definition while (1) { while ((ppl_cmdList[inPos] != '\0') && (ppl_cmdList[inPos] != '\n') && (ppl_cmdList[inPos] <= ' ')) inPos++; // Ignore whitespace if ((ppl_cmdList[inPos] == '\0') || (ppl_cmdList[inPos] == '\n')) break; // Newline means end of instruction // Punctuation which descends into a new hierarchical data structure if (ppl_cmdList[inPos] == '{') // {} grammar indicates an optional series of items, which go into a new structure. { ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_OPT); inPos++; } else if (ppl_cmdList[inPos] == '[') // [] grammar indicates a series of items which repeat 0 or more times. These go into a new structure. { ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_REP); inPos++; } else if (ppl_cmdList[inPos] == '(') // () grammar indicates items which can appear in any order, but each one not more than once. New structure. { ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_PER); inPos++; } else if (ppl_cmdList[inPos] == '<') // <> grammar indicates a list of items of which only one should be matched. New structure. { ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_ORA); inPos++; } // Punctuation which preceeds a new item in a sequence else if (ppl_cmdList[inPos] == '~') // ~ is used inside () to separate items { while ((stackPos>=0) && (defnStack[stackPos-1]->type == PN_TYPE_SEQ)) stackPos--; // Automatically close SEQs; they don't have closing grammar if ((stackPos<0) || (defnStack[stackPos-1]->type != PN_TYPE_PER)) { sprintf(e->tempErrStr, "Tilda should be used only in permutation structures (char pos %d).",inPos); ppl_fatal(e,__FILE__,__LINE__, NULL); } inPos++; } else if (ppl_cmdList[inPos] == '|') // | is used inside <> for either/or items { while ((stackPos>=0) && (defnStack[stackPos-1]->type == PN_TYPE_SEQ)) stackPos--; // Automatically close SEQs; they don't have closing grammar if ((stackPos<0) || (defnStack[stackPos-1]->type != PN_TYPE_ORA)) { sprintf(e->tempErrStr, "Pipe alternatives should only be used inside ORA structures (char pos %d).",inPos); ppl_fatal(e,__FILE__,__LINE__, NULL); } inPos++; } // Punctuation which closes a hierarchical data structure else if (ppl_cmdList[inPos] == '>') // Match closing brackets for the above types { int j=0; ppl_parserRollBack(e, defnStack, &stackPos, PN_TYPE_ORA, ppl_cmdList+inPos, &j) ; inPos+=j; } else if (ppl_cmdList[inPos] == ')') { int j=0; ppl_parserRollBack(e, defnStack, &stackPos, PN_TYPE_PER, ppl_cmdList+inPos, &j) ; inPos+=j; } else if (ppl_cmdList[inPos] == ']') { int j=0; ppl_parserRollBack(e, defnStack, &stackPos, PN_TYPE_REP, ppl_cmdList+inPos, &j) ; inPos+=j; } else if (ppl_cmdList[inPos] == '}') { int j=0; ppl_parserRollBack(e, defnStack, &stackPos, PN_TYPE_OPT, ppl_cmdList+inPos, &j) ; inPos+=j; } // Non-punctuation items which match strings and expressions else if (ppl_cmdList[inPos] == '@') { int strStart, k, l, m; parserNode *newNode, **target; inPos++; if (defnStack[stackPos-1]->type != PN_TYPE_SEQ) ppl_parserStartNode(e, defnStack, &stackPos, PN_TYPE_SEQ); // Match words have to go in sequences, not, e.g. "ora" structures if ((newNode = (parserNode *)malloc(sizeof(parserNode)))==NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } newNode->type = PN_TYPE_ITEM; newNode->firstChild = newNode->nextSibling = NULL; strStart = inPos; while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; // FFW over match string newNode->matchString = (char *)malloc((inPos-strStart+1)*sizeof(char)); if (newNode->matchString == NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } strncpy( newNode->matchString , ppl_cmdList+strStart , inPos-strStart ); newNode->matchString[inPos - strStart] = '\0'; if (strcmp(newNode->matchString, "DATABLOCK")==0) newNode->type = PN_TYPE_DATABLK; if (strcmp(newNode->matchString, "CODEBLOCK")==0) newNode->type = PN_TYPE_CODEBLK; if (ppl_cmdList[inPos++]!='@') { sprintf(e->tempErrStr, "Syntax error: expecting @ after @matchstr..."); ppl_fatal(e,__FILE__,__LINE__, NULL); } strStart = inPos; while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; // FFW over variable name newNode->varName = (char *)malloc((inPos-strStart+1)*sizeof(char)); if (newNode->varName == NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } strncpy( newNode->varName , ppl_cmdList+strStart , inPos-strStart ); newNode->varName[inPos - strStart] = '\0'; if (ppl_cmdList[inPos++]!='@') { sprintf(e->tempErrStr, "Syntax error: expecting @ after @matchstr@varname..."); ppl_fatal(e,__FILE__,__LINE__, NULL); } strStart = inPos; while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; // FFW over output string literal if (strStart==inPos) { newNode->outString = newNode->matchString; // No outString is specified, assume it is the same as matchString } else { newNode->outString = (char *)malloc((inPos-strStart+1)*sizeof(char)); if (newNode->outString == NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } strncpy( newNode->outString , ppl_cmdList+strStart , inPos-strStart ); newNode->outString[inPos - strStart] = '\0'; } if (ppl_cmdList[inPos++]!='@') { sprintf(e->tempErrStr, "Syntax error: expecting @ after @matchstr@varname@str..."); ppl_fatal(e,__FILE__,__LINE__, NULL); } k=(int)ppl_getFloat(ppl_cmdList+inPos,NULL); while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; newNode->acLevel = k; if (ppl_cmdList[inPos++]!='@') { sprintf(e->tempErrStr, "Syntax error: expecting @ after ]@varname@value@ACL..."); ppl_fatal(e,__FILE__,__LINE__, NULL); } l=(int)ppl_getFloat(ppl_cmdList+inPos,NULL); while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; newNode->outStackPos = l; if (ppl_cmdList[inPos++]!='@') { sprintf(e->tempErrStr, "Syntax error: expecting @ after ]@varname@value@ACL@stackpos..."); ppl_fatal(e,__FILE__,__LINE__, NULL); } m=(int)ppl_getFloat(ppl_cmdList+inPos,NULL); while ((ppl_cmdList[inPos]>' ')&&(ppl_cmdList[inPos]!='@')) inPos++; newNode->listLen = m; while ((ppl_cmdList[inPos]!='\0') && (ppl_cmdList[inPos]!='\n') && (ppl_cmdList[inPos]<' ')) inPos++; // FFW over trailing whitespace target = &(defnStack[stackPos-1]->firstChild); // Pointer to where first child of parent is linked while (*target != NULL) target = &((*target)->nextSibling); // If not first child of parent, traverse linked list to end *target = newNode; // Add new node into hierarchy, either as first child of parent, or into linked list of siblings } else if (ppl_cmdList[inPos]=='=') { parserNode *newNode, **target; if ((newNode = (parserNode *)calloc(1,sizeof(parserNode)))==NULL) { ppl_fatal(e,__FILE__,__LINE__,"Out of memory whilst setting up Pyxplot's command line parser."); exit(1); } newNode->type = PN_TYPE_CONFIRM; target = &(defnStack[stackPos-1]->firstChild); // Pointer to where first child of parent is linked while (*target != NULL) target = &((*target)->nextSibling); // If not first child of parent, traverse linked list to end *target = newNode; // Add new node into hierarchy, either as first child of parent, or into linked list of siblings inPos++; } else { sprintf(e->tempErrStr, "Syntax error: unexpected character '%c'", ppl_cmdList[inPos]); ppl_fatal(e,__FILE__,__LINE__, NULL); } } ppl_listAppend(pplParserCmdList[cmdLetter], defnStack[0]); } return 0; } pyxplot-0.9.2/src/parser/parserShell.c0000664000175000017500000003114512026340554016343 0ustar dcf21dcf21// parserShell.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: parserShell.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PARSERSHELL_C 1 #include #include #include #include #include "commands/core.h" #include "commands/eqnsolve.h" #include "commands/fft.h" #include "commands/fit.h" #include "commands/flowctrl.h" #include "commands/funcset.h" #include "commands/help.h" #include "commands/histogram.h" #include "commands/interpolate.h" #include "commands/set.h" #include "commands/show.h" #include "commands/tabulate.h" #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "epsMaker/canvasDraw.h" #include "settings/arrows_fns.h" #include "settings/axes_fns.h" #include "settings/labels_fns.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjPrint.h" #include "canvasItems.h" #include "children.h" #include "pplConstants.h" #define TBADD(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(c->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL,0); return; } \ } void ppl_parserShell(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { int contextNew; pplObj *stk = in->stk; char *d = (char *)stk[PARSE_arc_directive].auxil; // If directive is an expression, evaluate it and print result, unless it's an assignment if (stk[PARSE_arc_directive].objType == PPLOBJ_EXP) { int lastOpAssign=0; const int stkLevelOld = c->stackPtr; pplExpr *expr = (pplExpr *)stk[PARSE_arc_directive].auxil; pplObj *val = ppl_expEval(c, expr, &lastOpAssign, 1, iterDepth+1); if (c->errStat.status) return; // On error, stop if (!lastOpAssign) { pplObjPrint(c,val,NULL,c->errcontext.tempErrStr,LSTR_LENGTH,0,0); ppl_report(&c->errcontext, NULL); } // set ans { pplObj *optr, dummyTemp; int am, rc; ppl_contextGetVarPointer(c, "ans", &optr, &dummyTemp); dummyTemp.amMalloced=0; ppl_garbageObject(&dummyTemp); am = optr->amMalloced; rc = optr->refCount; optr->amMalloced = 0; ppl_garbageObject(optr); pplObjCpy(optr,val,0,0,1); optr->amMalloced = am; optr->refCount = rc; optr->self_lval = NULL; optr->self_this = NULL; } // Clean up stack while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } // If directive is not a string, something has gone wrong if (stk[PARSE_arc_directive].objType != PPLOBJ_STR) { ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, "directive type not a string"); return; } // Descend into a new memory context contextNew = ppl_memAlloc_DescendIntoNewContext(); // Directive is a string if (strcmp(d, "var_set")==0) ppl_directive_varset(c,pl,in,interactive,iterDepth); else if (strcmp(d, "func_set")==0) ppl_directive_funcset(c,pl,in,interactive); else if (strcmp(d, "akima")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_AKIMA); else if ((strcmp(d, "arrow")==0)||(strcmp(d,"line")==0)) ppl_directive_arrow(c,pl,in,interactive,iterDepth); else if (strcmp(d, "assert")==0) ppl_directive_assert(c,pl,in); else if (strcmp(d, "box")==0) ppl_directive_box(c,pl,in,interactive,iterDepth); else if (strcmp(d, "break")==0) ppl_directive_break(c,pl,in,interactive,iterDepth); else if (strcmp(d, "call")==0) { } // Work already done in evaluating the called object! else if (strcmp(d, "cd")==0) ppl_directive_cd(c,pl,in); else if ((strcmp(d, "circle")==0)||(strcmp(d, "arc")==0)) ppl_directive_circle(c,pl,in,interactive,iterDepth); else if (strcmp(d, "clear")==0) { ppl_directive_clear(c,pl,in,interactive); pplcsp_sendCommand(c,"A\n"); } else if (strcmp(d, "continue")==0) ppl_directive_continue(c,pl,in,interactive,iterDepth); else if (strcmp(d, "delete")==0) ppl_directive_delete(c,pl,in,interactive,iterDepth); else if (strcmp(d, "do")==0) ppl_directive_do(c,pl,in,interactive,iterDepth); else if (strcmp(d, "ellipse")==0) ppl_directive_ellipse(c,pl,in,interactive,iterDepth); else if (strcmp(d, "eps")==0) ppl_directive_eps(c,pl,in,interactive,iterDepth); else if (strcmp(d, "exec")==0) ppl_directive_exec(c,pl,in,interactive,iterDepth); else if ( (strcmp(d, "fft")==0) || (strcmp(d, "ifft")==0) ) ppl_directive_fft(c,pl,in,interactive,iterDepth); else if (strcmp(d, "fit")==0) ppl_directive_fit(c,pl,in,interactive,iterDepth); else if (strcmp(d, "for")==0) ppl_directive_for(c,pl,in,interactive,iterDepth); else if (strcmp(d, "foreach")==0) ppl_directive_foreach(c,pl,in,interactive,iterDepth); else if (strcmp(d, "foreachdatum")==0) ppl_directive_fordata(c,pl,in,interactive,iterDepth); else if (strcmp(d, "global")==0) ppl_directive_global(c,pl,in,interactive,iterDepth); else if (strcmp(d, "help")==0) ppl_directive_help(c,pl,in,interactive); else if (strcmp(d, "histogram")==0) ppl_directive_histogram(c,pl,in,interactive,iterDepth); else if (strcmp(d, "history")==0) ppl_directive_history(c,pl,in); else if (strcmp(d, "if")==0) ppl_directive_if(c,pl,in,interactive,iterDepth); else if (strcmp(d, "image")==0) ppl_directive_image(c,pl,in,interactive,iterDepth); else if (strcmp(d, "interpolate2d")==0) { int type = INTERP_2D; char *tempstr = (char *)stk[PARSE_interpolate2d_bmp].auxil; if (stk[PARSE_interpolate2d_bmp].objType==PPLOBJ_STR) switch (tempstr[4]) { case 'r': type = INTERP_BMPR; break; case 'g': type = INTERP_BMPG; break; case 'b': type = INTERP_BMPB; break; } ppl_directive_interpolate(c,pl,in,interactive,iterDepth,type); } else if (strcmp(d, "linear")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_LINEAR); else if (strcmp(d, "list")==0) ppl_directive_list(c,pl,in,interactive); else if (strcmp(d, "load")==0) ppl_directive_load(c,pl,in,interactive,iterDepth); else if (strcmp(d, "local")==0) ppl_directive_local(c,pl,in,interactive,iterDepth); else if (strcmp(d, "loglinear")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_LOGLIN); else if (strcmp(d, "maximise")==0) ppl_directive_maximise(c,pl,in,interactive,iterDepth); else if (strcmp(d, "minimise")==0) ppl_directive_minimise(c,pl,in,interactive,iterDepth); else if (strcmp(d, "move")==0) ppl_directive_move(c,pl,in,interactive,iterDepth); else if (strcmp(d, "piechart")==0) ppl_directive_piechart(c,pl,in,interactive,iterDepth); else if (strcmp(d, "pling")==0) { int status = system((char *)stk[PARSE_pling_cmd].auxil); if (WIFEXITED(status)) { int ec = WEXITSTATUS(status); if (ec) { if (DEBUG) ppl_log(&c->errcontext, "Pling command received non-zero return value."); } if (ec) { sprintf(c->errcontext.tempErrStr, "Shell returned exit code %d.", ec); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); } } else if (WIFSIGNALED(status)) { sprintf(c->errcontext.tempErrStr, "Shell terminated by signal %d.", WTERMSIG(status)); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); } else { sprintf(c->errcontext.tempErrStr, "Shell terminated because fail happened."); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); } } else if (strcmp(d, "plot")==0) ppl_directive_plot(c,pl,in,interactive,iterDepth,0); else if (strcmp(d, "point")==0) ppl_directive_point(c,pl,in,interactive,iterDepth); else if (strcmp(d, "polygon")==0) ppl_directive_polygon(c,pl,in,interactive,iterDepth); else if (strcmp(d, "polynomial")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_POLYN); else if (strcmp(d, "print")==0) ppl_directive_print(c,pl,in); else if (strcmp(d, "pwd")==0) ppl_report(&c->errcontext, c->errcontext.session_default.cwd); else if (strcmp(d, "quit")==0) c->shellExiting = 1; else if (strcmp(d, "refresh")==0) { if (c->set->term_current.display == SW_ONOFF_ON) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); } } else if (strcmp(d, "replot")==0) ppl_directive_plot(c,pl,in,interactive,iterDepth,1); else if (strcmp(d, "reset")==0) { int i; c->set->term_current = c->set->term_default; c->set->graph_current = c->set->graph_default; for (i=0; iset->palette_current [i] = c->set->palette_default [i]; c->set->paletteS_current[i] = c->set->paletteS_default[i]; c->set->palette1_current[i] = c->set->palette1_default[i]; c->set->palette2_current[i] = c->set->palette2_default[i]; c->set->palette3_current[i] = c->set->palette3_default[i]; c->set->palette4_current[i] = c->set->palette4_default[i]; } for (i=0; iset->XAxes[i]) ); pplaxis_copy(c, &(c->set->XAxes[i]), &(c->set->XAxesDefault[i])); pplaxis_destroy(c, &(c->set->YAxes[i]) ); pplaxis_copy(c, &(c->set->YAxes[i]), &(c->set->YAxesDefault[i])); pplaxis_destroy(c, &(c->set->ZAxes[i]) ); pplaxis_copy(c, &(c->set->ZAxes[i]), &(c->set->ZAxesDefault[i])); } for (i=0; iset->plot_styles[i])); ppl_withWordsCpy(c, &(c->set->plot_styles[i]) , &(c->set->plot_styles_default[i])); } pplarrow_list_destroy(c, &c->set->pplarrow_list); pplarrow_list_copy (c, &c->set->pplarrow_list, &c->set->pplarrow_list_default); ppllabel_list_destroy(c, &c->set->ppllabel_list); ppllabel_list_copy (c, &c->set->ppllabel_list, &c->set->ppllabel_list_default); ppl_directive_clear(c, NULL, NULL, 0); pplcsp_sendCommand(c,"A\n"); } else if (strcmp(d, "return")==0) ppl_directive_return(c,pl,in,interactive,iterDepth); else if (strcmp(d, "save")==0) ppl_directive_save(c,pl,in); else if (strcmp(d, "show")==0) ppl_directive_show(c,pl,in,interactive); else if (strcmp(d, "solve")==0) ppl_directive_solve(c,pl,in,interactive,iterDepth); else if (strcmp(d, "spline")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_SPLINE); else if (strcmp(d, "stepwise")==0) ppl_directive_interpolate(c,pl,in,interactive,iterDepth,INTERP_STEPWISE); else if (strcmp(d, "set")==0) ppl_directive_set(c,pl,in,interactive); else if (strcmp(d, "set_error")==0) ppl_directive_seterror(c,pl,in,interactive); else if (strcmp(d, "subroutine")==0) ppl_directive_subrt(c,pl,in,interactive,iterDepth); else if (strcmp(d, "swap")==0) ppl_directive_swap(c,pl,in,interactive,iterDepth); else if (strcmp(d, "tabulate")==0) ppl_directive_tabulate(c,pl,in,interactive,iterDepth); else if (strcmp(d, "text")==0) ppl_directive_text(c,pl,in,interactive,iterDepth); else if (strcmp(d, "undelete")==0) ppl_directive_undelete(c,pl,in,interactive,iterDepth); else if (strcmp(d, "unset")==0) ppl_directive_set(c,pl,in,interactive); else if (strcmp(d, "unset_error")==0) ppl_directive_unseterror(c,pl,in,interactive); else if (strcmp(d, "while")==0) ppl_directive_while(c,pl,in,interactive,iterDepth); else if (strcmp(d, "with")==0) ppl_directive_with(c,pl,in,interactive,iterDepth); else { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Unimplemented command: %s", d); TBADD(ERR_INTERNAL,0); } // Ascend out of memory context ppl_memAlloc_AscendOutOfContext(contextNew); return; } pyxplot-0.9.2/src/parser/parserExecute.c0000664000175000017500000003204612026340554016677 0ustar dcf21dcf21// parserExecute.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: parserExecute.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PARSEREXECUTE_C 1 #include #include #include #include #include #include "coreUtils/errorReport.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjPrint.h" #include "pplConstants.h" #define TBADD(et,pos) ppl_tbAdd(c,in->srcLineN,in->srcId,in->srcFname,0,et,pos,in->linetxt,NULL) void ppl_parserLinePrint(ppl_context *c, parserLine *in) { char *t = c->errcontext.tempErrStr; parserAtom *a = in->firstAtom; sprintf(t,"Parser line -- stack length %d\nOriginal line was: %s",in->stackLen,in->linetxt); ppl_report(&c->errcontext, NULL); if (in->containsMacros) ppl_report(&c->errcontext, "Contains macros."); for (a = in->firstAtom; a!=NULL; a=a->next) { if (a->literal!=NULL) { int i=0; sprintf(t+i,"Set %4d to literal of type %2d -- ",a->stackOutPos,a->literal->objType); i=strlen(t+i); pplObjPrint(c,a->literal,NULL,t+i,LSTR_LENGTH-i,0,0); i+=strlen(t+i); sprintf(t+i,"."); } else { int i=0; sprintf(t+i,"Set %4d to expression -- %s.",a->stackOutPos,a->expr->ascii); } ppl_report(&c->errcontext, NULL); } ppl_report(&c->errcontext, "---------------"); return; } void ppl_parserOutFree(parserOutput *in) { int i; if (in==NULL) return; for (i=0; istackLen; i++) ppl_garbageObject(&in->stk[i]); free(in->stk); free(in->stkCharPos); free(in); return; } #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(c->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL,0); return; } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } void ppl_parserExecute(ppl_context *c, parserLine *in, char *dirName, int interactive, int iterDepth) { int i; const int stkLevelOld = c->stackPtr; parserOutput *out = NULL; pplObj *stk = NULL; char *eB = c->errStat.errBuff; int *stkCharPos = NULL; // Check that recursion depth has not been exceeded if (iterDepth > MAX_RECURSION_DEPTH) { strcpy(eB,"Maximum recursion depth exceeded."); TBADD(ERR_OVERFLOW,0); return; } // If at bottom iteration depth, clean up stack now if there is any left-over junk if (iterDepth==0) while (c->stackPtr>0) { STACK_POP; } while ((in!=NULL)&&(!c->errStat.status)&&(!c->shellExiting)&&(!c->shellBroken)&&(!c->shellContinued)&&(!c->shellReturned)) { parserAtom *item = in->firstAtom; //ppl_parserLinePrint(c,in); // If line contains macros, need to recompile it now if (in->containsMacros) { int stat=0; parserStatus *ps = NULL; parserLine *pl = NULL; ppl_parserStatInit(&ps,&pl); if (ps==NULL) { strcpy(eB,"Out of memory."); TBADD(ERR_MEMORY,0); return; } stat = ppl_parserCompile(c, ps, in->srcLineN, in->srcId, in->srcFname, in->linetxt, 1, iterDepth+1); if (stat || c->errStat.status) break; ppl_parserExecute(c, ps->pl[iterDepth+1], dirName, interactive, iterDepth+1); ppl_parserLineFree(ps->pl[iterDepth+1]); ppl_parserStatFree(&ps); in = in->next; continue; } // Initialise output stack out = (parserOutput *)malloc(sizeof(parserOutput)); if (out==NULL) { strcpy(eB,"Out of memory."); TBADD(ERR_MEMORY,0); return; } stk = (pplObj *)malloc(in->stackLen*sizeof(pplObj)); if (stk==NULL) { free(out); strcpy(eB,"Out of memory."); TBADD(ERR_MEMORY,0); return; } for (i=0; istackLen; i++) { stk[i].refCount=1; pplObjZom(&stk[i],0); } stkCharPos = (int *)malloc(in->stackLen*sizeof(int)); if (stkCharPos==NULL) { free(out); free(stk); strcpy(eB,"Out of memory."); TBADD(ERR_MEMORY,0); return; } for (i=0; istackLen; i++) { stkCharPos[i]=-1; } out->stk = stk; out->stkCharPos = stkCharPos; out->stackLen = in->stackLen; // Loop over atoms while (item != NULL) { if (item->literal!=NULL) { // Atom is a literal: simply copy it pplObjCpy(&stk[item->stackOutPos],item->literal,0,0,1); } else { // Atom is an expression: evaluate it const int stkLevelOld = c->stackPtr; int lastOpAssign=0, passed=0, j=0, k=0, p=0; pplObj *val = ppl_expEval(c, item->expr, &lastOpAssign, 1, iterDepth+1); if (c->errStat.status) { if (item->options[1]=='E') // If expression has produced an error, and its second option is type E, store it for per-point evaluation { ppl_tbClear(c); pplObjExpression(&stk[item->stackOutPos],0,(void *)item->expr); item->expr->refCount++; goto gotTypeCexpression; } else { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,item->linePos); break; // On error, stop } } // Check type of pplObj produced by expression, and complain if the wrong type strcpy(eB+k,"Expression evaluates to the wrong type: needed"); k+=strlen(eB+k); for (j=0; ((joptions[j]!='\0')&&(!passed)); j++) { ppl_context *context = c; // Needed for CAST_TO_BOOL if (j!=0) { strcpy(eB+k,", or"); k+=strlen(eB+k); } switch(item->options[j]) { case 'a': strcpy(eB+k," an axis number"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; if (val->flagComplex) break; if (!val->dimensionless) break; if ( (val->real <= 0) || (val->real >= MAX_AXES) ) break; val->exponent[0] = (double)(item->options[++j]-'0'); passed=1; break; case 'A': strcpy(eB+k," an angle"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; if (val->flagComplex) break; if (val->dimensionless) { val->real *= M_PI/180; passed=1; break; } for (p=0; pexponent[p] != (p==UNIT_ANGLE)) { p=-1; break; } passed=(p>0); break; case 'b': CAST_TO_BOOL(val); passed=1; break; case 'c': strcpy(eB+k," a color"); k+=strlen(eB+k); if ( (val->objType!=PPLOBJ_COL) && ((val->objType!=PPLOBJ_NUM)||(!val->dimensionless)||(val->flagComplex)||(val->realreal>INT_MAX)) ) break; passed=1; break; case 'd': strcpy(eB+k," an integer"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; if (val->flagComplex) break; if (!val->dimensionless) break; if ( (val->real < INT_MIN) || (val->real > INT_MAX) ) break; passed=1; break; case 'D': strcpy(eB+k," a length"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; if (val->flagComplex) break; if (val->dimensionless) { val->real *= 0.01; passed=1; break; } for (p=0; pexponent[p] != (p==UNIT_LENGTH)) { p=-1; break; } passed=(p>0); break; case 'E': case 'F': passed=0; break; case 'f': strcpy(eB+k," a number"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; if (val->flagComplex) break; if (!val->dimensionless) break; passed=1; break; case 'o': passed=1; break; case 'p': case 'P': strcpy(eB+k," a position vector"); k+=strlen(eB+k); if (val->objType == PPLOBJ_VEC) { double m=1,x=0,y=0,z=0; gsl_vector *v=((pplVector *)val->auxil)->v; int l=v->size, rc; if ( (l<2) || (l>((item->options[j]=='P')?3:2)) ) break; // wrong size if (val->dimensionless) m=0.01; else { for (p=0; pexponent[p] != (p==UNIT_LENGTH)) { p=-1; break; } if (p<0) break; // vector has wrong units } if (l>0) x = gsl_vector_get(v,0) * m; if (l>1) y = gsl_vector_get(v,1) * m; if (l>2) z = gsl_vector_get(v,2) * m; rc = val->refCount; ppl_garbageObject(val); val->refCount = rc; pplObjNum(val ,0,x,0); pplObjNum(&stk[item->stackOutPos+1],0,y,0); if (item->options[j]=='P') pplObjNum(&stk[item->stackOutPos+2],0,z,0); passed=1; } else if (val->objType == PPLOBJ_LIST) { double x[3]={0,0,0}; list *li=(list *)val->auxil; int l=li->length, i, rc; if ( (l<2) || (l>((item->options[j]=='P')?3:2)) ) break; // wrong size for (i=0; iobjType != PPLOBJ_NUM) break; if (xo->flagComplex) break; if (xo->dimensionless) m=0.01; else { for (p=0; pexponent[p] != UNIT_LENGTH) { p=-1; break; } if (p<0) break; // vector has wrong units } x[i] = xo->real * m; } rc = val->refCount; ppl_garbageObject(val); val->refCount = rc; pplObjNum(val ,0,x[0],0); pplObjNum(&stk[item->stackOutPos+1],0,x[1],0); if (item->options[j]=='P') pplObjNum(&stk[item->stackOutPos+2],0,x[2],0); passed=1; } break; // fail case 'q': strcpy(eB+k," a string"); k+=strlen(eB+k); if (val->objType != PPLOBJ_STR) break; passed=1; break; case 'u': strcpy(eB+k," a physical quantity"); k+=strlen(eB+k); if (val->objType != PPLOBJ_NUM) break; passed=1; break; default: ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Illegal option encountered."); } } // If expression has produced a value of the wrong type, throw an error if (!passed) { strcpy(eB+k,"."); TBADD(ERR_TYPE, item->linePos); break; } // Copy value produced by atom pplObjCpy(&stk[item->stackOutPos], val, 0, 0, 1); STACK_CLEAN; } gotTypeCexpression: stkCharPos[item->stackOutPos] = item->linePos; item = item->next; } // If no error, pass command to shell if (!c->errStat.status) { char *cmd = (char *)stk[PARSE_arc_directive].auxil; if ((dirName != NULL) && (strcmp(dirName, cmd)!=0) && ((strcmp(dirName,"set")!=0)||(strcmp(cmd,"set_error")!=0))) { sprintf(eB,"Command of type '%s' is not allowed in this section of a configuration file.", cmd); TBADD(ERR_SYNTAX,0); } else if ((dirName != NULL) && (stk[PARSE_arc_editno].objType==PPLOBJ_NUM)) { sprintf(eB,"Settings may not be edited for canvas items within a configuration file."); TBADD(ERR_SYNTAX,0); } else { ppl_parserShell(c, in, out, interactive, iterDepth); } } // Free output stack STACK_CLEAN; ppl_parserOutFree(out); in = in->next; } return; } pyxplot-0.9.2/src/parser/parserCompile.c0000664000175000017500000015473612026340554016700 0ustar dcf21dcf21// parserCompile.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: parserCompile.c 1285 2012-08-10 01:07:03Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PARSERCOMPILE_C 1 #include #include #include #include #include #include #ifdef HAVE_READLINE #include #endif #include "coreUtils/errorReport.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "settings/epsColors.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #define PARSE_TBADD(X,Y,Z) \ { \ ppl_tbAdd(c,srcLineN,srcId,srcFname,1,X,Y,Z,""); \ if ( (c->errStat.errPosExpr==-1) && (c->errStat.oldErrPosExpr == c->algebraErrPos) && (c->algebraErrPos >= 0) && (c->algebraErrPos>=(Y)) ) \ { \ c->errStat.errPosExpr = c->algebraErrPos; \ c->errStat.sourceIdExpr = srcId; \ } \ } static char *strDup(const char *in, int N) { char *out = (char *)malloc(N+1); if (out==NULL) return NULL; strncpy(out, in, N+1); out[N]='\0'; return out; } void ppl_parserAtomAdd(parserLine *in, int stackOutPos, int linePos, char *options, pplExpr *expr, pplObj *literal) { parserAtom *output = (parserAtom *)malloc(sizeof(parserAtom)); if (output==NULL) return; output->stackOutPos = stackOutPos; output->linePos = linePos; output->expr = expr; output->next = NULL; strncpy(output->options, options, 8); output->options[7]='\0'; if (literal == NULL) output->literal = NULL; else { output->literal = (pplObj *)malloc(sizeof(pplObj)); if (output->literal==NULL) { free(output); return; } memcpy(output->literal, literal, sizeof(pplObj)); output->literal->refCount = 1; output->literal->amMalloced = 1; } if (in->lastAtom==NULL) { in->firstAtom = output; } else { in->lastAtom->next = output; } in->lastAtom = output; } static int parse_descend(ppl_context *c, parserStatus *s, int writeOut, int srcLineN, long srcId, char *srcFname, char *line, int *linepos, parserNode *node, int *tabCompNo, int tabCompStart, char *tabCompTxt, int level, int blockDepth, int *match) { int status=0; // 0=fail; 1=pass; 2=tab completion returned; 3=want another line. // If node is NULL, this means we're putting back together a hierarchy of SEQs that we earlier descended out of to look for more input statements if (node==NULL) { parserNode *nodeNext = s->stk[blockDepth][level+1]; node = s->stk[blockDepth][level]; if (nodeNext != NULL) // We need to descend still further... { parserNode *nodeIter = node->firstChild; status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,NULL,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status!=1) goto cleanup; // We came out of child node with a success return code. This means we carry on chomping along the SEQ // If we've come out of an OPT, treat it as a SEQ now... if ((node->type==PN_TYPE_SEQ)||(node->type==PN_TYPE_OPT)) { while ((nodeIter!=nodeNext) && (nodeIter!=NULL)) nodeIter = nodeIter->nextSibling; // Work out where we were... if (nodeIter==nodeNext) nodeIter = nodeIter->nextSibling; while (nodeIter != NULL) { status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status!=1) goto cleanup; nodeIter = nodeIter->nextSibling; } } else if ((node->type==PN_TYPE_REP)||(node->type==PN_TYPE_REP2)) { int separator=1; char sepStr[4]; parserNode sepNode; int oldStackOffset = s->oldStackOffset[blockDepth][level]; sepStr[0] = node->varName[strlen(node->varName)-1]; sepStr[1] = '\0'; if (isalnum(sepStr[0])) separator=0; sepNode.type = PN_TYPE_ITEM; sepNode.listLen = 0; sepNode.acLevel = -1; sepNode.matchString = sepStr; sepNode.outString = sepStr; sepNode.varName = "X"; sepNode.outStackPos = PARSE_arc_X; sepNode.firstChild = NULL; sepNode.nextSibling = NULL; // Treat the run through the REP that we're in the middle of as a SEQ while ((nodeIter!=nodeNext) && (nodeIter!=NULL)) nodeIter = nodeIter->nextSibling; // Work out where we were... if (nodeIter==nodeNext) nodeIter = nodeIter->nextSibling; while (nodeIter != NULL) { status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status!=1) goto cleanup; nodeIter = nodeIter->nextSibling; } // See whether REP repeats again while (1) { int lineposOld = *linepos; int matchOld = *match; int lineposOld2; parserNode *nodeIter = node->firstChild; if (separator) { status = parse_descend(c,s,0,srcLineN,srcId,srcFname,line,linepos,&sepNode,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) { status=0; } // Separator shouldn't ask for more lines! if (status==0) { *linepos=lineposOld; *match=matchOld; status=1; goto repLoopCleanup; } if (status==2) goto repLoopCleanup; } lineposOld2 = *linepos; while (nodeIter != NULL) { status = parse_descend(c,s,0,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) { status=0; goto repLoopCleanup; } // Trial run with writeOut=0 shouldn't ask for more lines! if (status==0) { if (!separator) { status=1; *linepos=lineposOld; *match=matchOld; } goto repLoopCleanup; } if (status==2) goto repLoopCleanup; nodeIter = nodeIter->nextSibling; } if ((s!=NULL) && writeOut) { int oldStackLen = s->pl[blockDepth]->stackLen; pplObj val; val.refCount=1; pplObjNum(&val,1,oldStackLen,0); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + ((s->pl[blockDepth]->stackOffset == oldStackOffset) ? node->outStackPos : 0), *linepos, "", NULL, &val); s->pl[blockDepth]->stackLen += node->listLen; s->pl[blockDepth]->stackOffset = oldStackLen; nodeIter=node->firstChild; *linepos=lineposOld2; *match=matchOld; while (nodeIter != NULL) { // Add an atom to the parserLine to point to the beginning of structure // This is written to either stack location (offset + stackPos) if first iteration, or (offset + 0) subsequently // In any repeating structure, first stack position is pointer to next item status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) goto cleanup; if (status!=1) goto repLoopCleanup; nodeIter = nodeIter->nextSibling; } } } repLoopCleanup: s->pl[blockDepth]->stackOffset = oldStackOffset; goto cleanup; } else { status=0; sprintf(c->errStat.errBuff,"Bad node type coming out of code block."); PARSE_TBADD(ERR_INTERNAL,0,line); } goto cleanup; } // We don't need to descend any further... we let ourselves loose on the code below! } // If this is a top-level attempt to parse a statement, make a new parserLine structure to hold the output of our attempt if ((s!=NULL) && writeOut && (level==0)) { parserLine *output=NULL; ppl_parserLineInit(&output,srcLineN,srcId,srcFname,line); output->stackLen = node->listLen; if (output==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); PARSE_TBADD(ERR_MEMORY,0,line); return 0; } ppl_parserStatAdd(s, blockDepth, output); } // FFW over spaces while ((line[*linepos]!='\0') && (line[*linepos]<=' ')) (*linepos)++; // Deal with the node we've been given switch (node->type) { case PN_TYPE_CONFIRM: { *match=1; status=1; goto cleanup; } case PN_TYPE_DATABLK: { if ((s==NULL)||(!writeOut)) { status=1; } else { int first = (s->blockDepth != blockDepth+1); // first line -- must be at end of command line which includes '--' if (first) { if (line[*linepos]!='\0') { status=0; goto cleanup; } } // Make parserLine structure to hold this line of text parserLine *output=NULL; ppl_parserLineInit(&output, srcLineN, srcId, srcFname, line); if (output==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); ppl_tbAdd(c,srcLineN,srcId,srcFname,0,ERR_MEMORY,0,line,"inline data"); status=0; goto cleanup; } output->stackLen = 0; output->containsMacros = 1; // If s->blockDepth is not already set, this is the first line of data if (first) { pplObj val; val.refCount=1; pplObjBytecode(&val,0,(void *)output); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); s->blockDepth = blockDepth+1; s->pl[s->blockDepth] = output; } else // Add this line of data to linked list of parserLines. { ppl_parserStatAdd(s, s->blockDepth, output); } // See whether this line is the end of a datablock if (strncmp(line+*linepos,"END",3)==0) { int i, endBlock=1; for (i=3; line[*linepos+i]!='\0'; i++) if (line[*linepos+i]>' ') { endBlock=0; break; } if (endBlock) { s->NinlineDatafiles[blockDepth]--; first=1; } } // Return status 1 or 3 depending whether we're still looking for more data if (s->NinlineDatafiles[blockDepth]<1) { status=1; strcpy(s->prompt, "pyxplot"); } else if (first) { status=3; strcpy(s->prompt, "data>>>"); } else { status=3; strcpy(s->prompt, "data..."); } *linepos += strlen(line+*linepos); } goto cleanup; } case PN_TYPE_CODEBLK: { if ((s==NULL)||(!writeOut)) { if (line[*linepos]=='{') { status=(s!=NULL); (*linepos)++; } // Return fail when tab-completing, even if we've actually correctly matched a {; it won't make any useful suggestions hereafter else if ((s!=NULL)&&(s->eLlinePos <= *linepos)) // Not tab completing, and we haven't matched a {: suggest { as an 'expecting' hint { int j,k,l; if (s->eLlinePos < *linepos) { s->eLlinePos = *linepos; s->eLPos = 0; s->expectingList[0]='\0'; } if (s->eLPos != 0) { strcpy(s->expectingList+s->eLPos, ", or "); s->eLPos+=strlen(s->expectingList+s->eLPos); } sprintf(s->expectingList+s->eLPos, "\"{\""); l = strlen(s->expectingList+s->eLPos); for (j=k=0; ((jeLPos)&&!k); j++) k = (strncmp(s->expectingList+j,s->expectingList+s->eLPos,l)==0); // Don't repeat ourselves if (!k) { s->eLPos+=l; } else { if (s->eLPos!=0) { s->eLPos-=5; } s->expectingList[s->eLPos]='\0'; } status=0; } else // We failed to match a { { status=0; } } else { char *cmd = (char *)s->pl[blockDepth]->firstAtom->literal->auxil; // THIS ASSUMES DIRECTIVE IS FIRST ATOM int first = (s->blockDepthwaitingForBrace = 1; s->outputPos[blockDepth] = s->pl[blockDepth]->stackOffset + node->outStackPos; s->blockDepth = blockDepth+1; s->pl[s->blockDepth] = NULL; } if ((s->waitingForBrace)&&(s->blockDepth==blockDepth+1)) { if (line[*linepos]=='{') { s->waitingForBrace = 0; (*linepos)++; while ((line[*linepos]!='\0') && (line[*linepos]<=' ')) (*linepos)++; // FFW over spaces if (line[*linepos]=='\0') goto codeblock_write_prompt; } else if (line[*linepos]=='\0') { goto codeblock_write_prompt; } else { status=0; if ((s!=NULL)&&(s->eLlinePos <= *linepos)) { int j,k,l; if (s->eLlinePos < *linepos) { s->eLlinePos = *linepos; s->eLPos = 0; s->expectingList[0]='\0'; } if (s->eLPos != 0) { strcpy(s->expectingList+s->eLPos, ", or "); s->eLPos+=strlen(s->expectingList+s->eLPos); } sprintf(s->expectingList+s->eLPos, "\"{\""); l = strlen(s->expectingList+s->eLPos); for (j=k=0; ((jeLPos)&&!k); j++) k = (strncmp(s->expectingList+j,s->expectingList+s->eLPos,l)==0); // Don't repeat ourselves if (!k) { s->eLPos+=l; } else { if (s->eLPos!=0) { s->eLPos-=5; } s->expectingList[s->eLPos]='\0'; } } goto cleanup; } } // Test for closing brace if ((line[*linepos]=='}')&&(s->blockDepth==blockDepth+1)) { status=1; (*linepos)++; if (s->outputPos[blockDepth]>=0) // check we've had at least one command { pplObj val; val.refCount=1; pplObjBytecode(&val,0,NULL); ppl_parserAtomAdd(s->pl[blockDepth], s->outputPos[blockDepth], *linepos, "", NULL, &val); s->outputPos[blockDepth]=-1; } strcpy(s->prompt, "pyxplot"); break; } // Compile line of text to bytecode ppl_parserCompile(c, s, srcLineN, srcId, srcFname, line+*linepos, 0, blockDepth+1); if (c->errStat.status) { status=0; goto cleanup; } // On error, stop if (s->blockDepthblockDepth=blockDepth+1; // If s->outputPos is set, this is the first line of data if (s->outputPos[blockDepth]>=0) { pplObj val; val.refCount=1; pplObjBytecode(&val,0,(void *)s->pl[blockDepth+1]); ppl_parserAtomAdd(s->pl[blockDepth], s->outputPos[blockDepth], *linepos, "", NULL, &val); s->outputPos[blockDepth]=-1; } // Write prompt codeblock_write_prompt: if (s->stk[blockDepth+1][0]!=NULL) { status=3; goto cleanup; } if (strcmp(cmd,"do" )==0) strcpy(s->prompt, "do"); else if (strcmp(cmd,"for" )==0) strcpy(s->prompt, "for"); else if (strcmp(cmd,"foreach" )==0) strcpy(s->prompt, "foreac"); else if (strcmp(cmd,"foreachdatum")==0) strcpy(s->prompt, "foreac"); else if (strcmp(cmd,"if" )==0) strcpy(s->prompt, "if"); else if (strcmp(cmd,"subroutine" )==0) strcpy(s->prompt, "subrou"); else if (strcmp(cmd,"while" )==0) strcpy(s->prompt, "while"); else strcpy(s->prompt, "unknow"); i = strlen(s->prompt); for ( ; i<7; i++) s->prompt[i]=first?'>':'.'; s->prompt[i]='\0'; status=3; } goto cleanup; } case PN_TYPE_ITEM: { int i; static int atNLastPos=-1; // Position of the last @n item matched if (*lineposmatchString[0]=='%') { if ((node->varName != NULL) && ((strcmp(node->varName,"filename")==0)||(strcmp(node->varName,"directory")==0))) { // Expecting a filename if ((*tabCompNo)!=0) { status=0; (*tabCompNo)--; goto item_cleanup; } status=2; strcpy(tabCompTxt, "\n"); (*tabCompNo)--; goto item_cleanup; } goto finished_looking_for_tabcomp; // Expecting a float or string, which we don't tab complete... move along and look for something else } if ((*linepos>0) && (isalnum(line[(*linepos)-1])) && (atNLastPos!=*linepos)) goto finished_looking_for_tabcomp; // 'plot a' cannot tab complete 'using' without space for (i=0; ((line[*linepos+i]>' ') && (node->matchString[i]>' ')); i++) if (toupper(line[*linepos+i])!=toupper(node->matchString[i])) { status=0; goto item_cleanup; // We don't match the beginning of this string } if ((node->acLevel == -1) && (node->matchString[i]<=' ')) goto finished_looking_for_tabcomp; // We've matched an @n string right to the end... move on if ((*tabCompNo)!=0) { status=0; (*tabCompNo)--; goto item_cleanup; } status=2; for (i=0; i<((*linepos)-tabCompStart); i++) tabCompTxt[i] = line[tabCompStart+i]; strcpy(tabCompTxt+i, node->matchString); // Matchstring should match itself (*tabCompNo)--; goto item_cleanup; } finished_looking_for_tabcomp: // Treat items which are @n if (node->acLevel == -1) { int i; status=1; for (i=0; (node->matchString[i]>' '); i++) if (toupper(line[*linepos+i])!=toupper(node->matchString[i])) { status=0; break; // We don't match this string } if (status==1) { *linepos += i; // We do match this string: advance by i spaces atNLastPos = *linepos; if ((s!=NULL) && writeOut && (strcmp(node->varName,"X")!=0)) { pplObj val; val.refCount=1; pplObjStr(&val,0,0,node->outString); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); } } } // Treat items which are not @n else if (node->matchString[0]!='%') // Items which do not begin % match themselves { int i = ppl_strAutocomplete(line+*linepos , node->matchString , node->acLevel); if (i<0) { status=0; } else { status=1; *linepos += i; // We match this string: advance by i spaces atNLastPos = *linepos; if ((s!=NULL) && writeOut && (strcmp(node->varName,"X")!=0)) { pplObj val; val.refCount=1; pplObjStr(&val,0,0,node->outString); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); } } } else // Item begins with a %, so substitute a value for this variable { pplExpr *expr; int explen=0, errPos=-1, errType; int dollarAllowed = ((node->matchString[1]=='E') || (node->matchString[2]=='E') || (node->matchString[1]=='F')); int equalsAllowed = (node->matchString[1]!='g'); int commaAllowed = (node->matchString[1]=='F'); int vectorAllowed = (node->matchString[1]=='P')||(node->matchString[1]=='p'); int vectorLength = (node->matchString[1]=='P')?3:2; int vectorCount = 0; int gotComma = 0; do { gotComma=0; switch (node->matchString[1]) { case 's': case 'S': case 'r': case 'v': { if (node->matchString[1]=='r') explen = strlen(line+*linepos); else if (node->matchString[1]=='s') { for (explen=0; ((isalpha(line[*linepos+explen]))||(line[*linepos+explen]=='_')); explen++); if (explen==0) { status=0; goto item_cleanup; } } else if (node->matchString[1]=='S') { for (explen=0; ((line[*linepos+explen]>' ')&&(line[*linepos+explen]!='\'')&&(line[*linepos+explen]!='\"')); explen++); if (explen==0) { status=0; goto item_cleanup; } } else if (node->matchString[1]=='v') { if (!isalpha(line[*linepos])) { status=0; goto item_cleanup; } // variable name must start with a letter for (explen=1; ((isalnum(line[*linepos+explen]))||(line[*linepos+explen]=='_')); explen++); // afterwards, numbers and _ allowed } if ((s!=NULL) && writeOut) { char *str = strDup(line+*linepos,explen); pplObj val; if (str==NULL) { status=0; goto item_cleanup; } val.refCount=1; pplObjStr(&val,0,1,str); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); } break; } case 'a': { int xyz , anum=1; if ((line[*linepos]=='x')||(line[*linepos]=='X')) xyz=0; else if ((line[*linepos]=='y')||(line[*linepos]=='Y')) xyz=1; else if ((line[*linepos]=='z')||(line[*linepos]=='Z')) xyz=2; else { status=0; goto item_cleanup; } if (ppl_validFloat(line+*linepos+1,NULL)) { double ad = ppl_getFloat(line+*linepos+1,&explen); if ((ad<=0)||(ad>=INT_MAX)) { status=0; goto item_cleanup; } anum = (int)floor(ad); explen++; } else { explen=1; } if ((s!=NULL)&&(writeOut)) { char opt[8]; pplObj val; val.refCount=1; pplObjNum(&val,1,anum,0); val.exponent[0] = xyz; sprintf(opt,"a%d",xyz); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos+1, opt, NULL, &val); } break; } case 'c': { char nambuff[64]; int id, i; for (i=0; ((i<63)&&((isalnum(line[*linepos+i]))||(line[*linepos+i]=='('))); i++) nambuff[i] = line[*linepos+i]; nambuff[i] = '\0'; id = ppl_fetchSettingByName(&c->errcontext, nambuff, SW_COLOR_INT, SW_COLOR_STR); if (id > 0) { pplObj val; val.refCount=1; explen=i; if ((s==NULL)||(!writeOut)) break; pplObjColor(&val,0,SW_COLSPACE_CMYK,*(double *)ppl_fetchSettingName(&c->errcontext, id, SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)), *(double *)ppl_fetchSettingName(&c->errcontext, id, SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)), *(double *)ppl_fetchSettingName(&c->errcontext, id, SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)), *(double *)ppl_fetchSettingName(&c->errcontext, id, SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)) ); val.exponent[2]=id; ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); break; } // If supplied string did not match a named color, treat it as an expression } default: { ppl_expCompile(c,srcLineN,srcId,srcFname,line+*linepos,&explen,dollarAllowed,equalsAllowed,commaAllowed,&expr,&errPos,&errType,c->errStat.errBuff); if (errPos>=0) { pplExpr_free(expr); ppl_tbAdd(c,srcLineN,srcId,srcFname,0,errType,errPos+*linepos,line,""); c->algebraErrPos = errPos+*linepos; status=0; goto item_cleanup; } if (vectorAllowed && (vectorCount+1 < vectorLength)) { while ((line[*linepos+explen]>'\0')&&(line[*linepos+explen]<=' ')) explen++; // ffw over whitespace if (line[*linepos+explen]==',') { explen++; gotComma=1; } // vector with another comma-separated component } if ((s==NULL)||(!writeOut)) pplExpr_free(expr); else if ((node->matchString[1]!='e') && (node->matchString[1]!='E') && (node->matchString[1]!='F') && (node->matchString[1]!='g')) { char *t = node->matchString+1; if (gotComma || (vectorCount>0)) t="D"; // not a vector, rather comma separated distances ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos + vectorCount, *linepos, t, expr, NULL); } else { int j, isInline=1; pplObj val; val.refCount=1; if (!(strcmp(node->varName,"expression")==0)) isInline=0; if (isInline && (strncmp(line+*linepos,"\"--\"",4)!=0) && (strncmp(line+*linepos,"'--'",4)!=0) ) isInline=0; for (j=4; j' ') isInline=0; if (isInline) s->NinlineDatafiles[blockDepth]++; pplObjExpression(&val,0,(void *)expr); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + node->outStackPos, *linepos, "", NULL, &val); } } // default } // switch *linepos += explen; if (gotComma) vectorCount++; } while (gotComma); status=1; } // item beginning with % // If we're not running in tab-completion mode and have failed, return an "expecting" hint item_cleanup: if ((s!=NULL) && (status!=1) && (s->eLlinePos <= *linepos)) { int i,j,k,l; char varname[FNAME_LENGTH]; if (s->eLlinePos < *linepos) { s->eLlinePos = *linepos; s->eLPos = 0; s->expectingList[0]='\0'; } if ((node->varName != NULL) && (node->varName[0] != '\0')) sprintf(varname, " (%s)", node->varName); else varname[0]='\0'; for (i=1; 1; i++) { if (s->eLPos != 0) { strcpy(s->expectingList+s->eLPos, ", or "); s->eLPos+=strlen(s->expectingList+s->eLPos); } if (node->matchString[0]!='%') { sprintf(s->expectingList+s->eLPos, "\"%s\"", node->matchString); } else { if (node->matchString[i]=='\0') { if (s->eLPos!=0) { s->eLPos-=5; s->expectingList[s->eLPos]='\0'; } break; } switch(node->matchString[i]) { case 'a': sprintf(s->expectingList+s->eLPos, "an axis name%s", varname); break; case 'A': sprintf(s->expectingList+s->eLPos, "an angle%s", varname); break; case 'b': sprintf(s->expectingList+s->eLPos, "a boolean%s", varname); break; case 'c': sprintf(s->expectingList+s->eLPos, "a color%s", varname); break; case 'd': sprintf(s->expectingList+s->eLPos, "an integer%s", varname); break; case 'D': sprintf(s->expectingList+s->eLPos, "a distance%s", varname); break; case 'e': sprintf(s->expectingList+s->eLPos, "an algebraic expression%s", varname); break; case 'E': sprintf(s->expectingList+s->eLPos, "an algebraic expression%s", varname); break; case 'F': sprintf(s->expectingList+s->eLPos, "an algebraic expression%s", varname); break; case 'g': sprintf(s->expectingList+s->eLPos, "an algebraic expression%s", varname); break; case 'f': sprintf(s->expectingList+s->eLPos, "a real, dimensionless number%s", varname); break; case 'o': sprintf(s->expectingList+s->eLPos, "an expression%s", varname); break; case 'p': sprintf(s->expectingList+s->eLPos, "a position vector%s", varname); break; case 'P': sprintf(s->expectingList+s->eLPos, "a position vector%s", varname); break; case 'q': sprintf(s->expectingList+s->eLPos, "a string%s", varname); break; case 'r': sprintf(s->expectingList+s->eLPos, "a string of text%s", varname); break; case 's': sprintf(s->expectingList+s->eLPos, "an alphabetical word%s", varname); break; case 'S': sprintf(s->expectingList+s->eLPos, "a word%s", varname); break; case 'u': sprintf(s->expectingList+s->eLPos, "a physical quantity%s", varname); break; case 'v': sprintf(s->expectingList+s->eLPos, "a variable name%s", varname); break; } } l = strlen(s->expectingList+s->eLPos); for (j=k=0; ((jeLPos)&&!k); j++) k = (strncmp(s->expectingList+j,s->expectingList+s->eLPos,l)==0); // Don't repeat ourselves if (!k) { s->eLPos+=l; } else { if (s->eLPos!=0) { s->eLPos-=5; } s->expectingList[s->eLPos]='\0'; } if (node->matchString[0]!='%') break; } } goto cleanup; } case PN_TYPE_SEQ: { parserNode *nodeIter = node->firstChild; while (nodeIter != NULL) { status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status!=1) goto cleanup; nodeIter = nodeIter->nextSibling; } goto cleanup; } case PN_TYPE_REP: case PN_TYPE_REP2: { int first=1, separator=1; char sepStr[4]; parserNode sepNode; int oldStackOffset = (s==NULL) ? 0 : s->pl[blockDepth]->stackOffset; if (s!=NULL) s->oldStackOffset[blockDepth][level] = oldStackOffset; sepStr[0] = node->varName[strlen(node->varName)-1]; sepStr[1] = '\0'; if (isalnum(sepStr[0])) separator=0; sepNode.type = PN_TYPE_ITEM; sepNode.listLen = 0; sepNode.acLevel = -1; sepNode.matchString = sepStr; sepNode.outString = sepStr; sepNode.varName = "X"; sepNode.outStackPos = PARSE_arc_X; sepNode.firstChild = NULL; sepNode.nextSibling = NULL; while (1) { int lineposOld = *linepos; int matchOld = *match; int lineposOld2; parserNode *nodeIter = node->firstChild; if (separator && !first) { status = parse_descend(c,s,0,srcLineN,srcId,srcFname,line,linepos,&sepNode,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) { status=0; } // Separator shouldn't ask for more lines! if (status==0) { *linepos=lineposOld; *match=matchOld; status=1; goto repCleanup; } if (status==2) goto repCleanup; } lineposOld2 = *linepos; while (nodeIter != NULL) { status = parse_descend(c,s,0,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) { status=0; goto repCleanup; } // Trial run with writeOut=0 shouldn't ask for more lines! if (status==0) { if (first ? (node->type==PN_TYPE_REP2) : !separator) { status=1; *linepos=lineposOld; *match=matchOld; } goto repCleanup; } if (status==2) goto repCleanup; nodeIter = nodeIter->nextSibling; } if ((s!=NULL) && writeOut) { int oldStackLen = s->pl[blockDepth]->stackLen; pplObj val; val.refCount=1; pplObjNum(&val,1,oldStackLen,0); ppl_parserAtomAdd(s->pl[blockDepth], s->pl[blockDepth]->stackOffset + ((s->pl[blockDepth]->stackOffset == oldStackOffset) ? node->outStackPos : 0), *linepos, "", NULL, &val); s->pl[blockDepth]->stackLen += node->listLen; s->pl[blockDepth]->stackOffset = oldStackLen; nodeIter=node->firstChild; *linepos=lineposOld2; *match=matchOld; while (nodeIter != NULL) { // Add an atom to the parserLine to point to the beginning of structure // This is written to either stack location (offset + stackPos) if first iteration, or (offset + 0) subsequently // In any repeating structure, first stack position is pointer to next item status = parse_descend(c,s,writeOut,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==3) goto cleanup; if (status!=1) goto repCleanup; nodeIter = nodeIter->nextSibling; } } first=0; } repCleanup: if (s!=NULL) s->pl[blockDepth]->stackOffset = oldStackOffset; goto cleanup; } case PN_TYPE_OPT: { int lineposOld = *linepos; int matchOld = *match; parserNode *nodeIter = node->firstChild; int wo = 0; while (1) { while (nodeIter != NULL) { status = parse_descend(c,s,wo,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (status==0) { *linepos=lineposOld; *match=matchOld; status=1; goto cleanup; } if (status>=2) goto cleanup; nodeIter = nodeIter->nextSibling; } // The dry run succeeded, so do it again, for real if (wo==writeOut) goto cleanup; *linepos=lineposOld; *match=matchOld; nodeIter=node->firstChild; wo=writeOut; } } case PN_TYPE_PER: { #define PER_MAXSIZE 64 int repeating=1; unsigned char excluded[PER_MAXSIZE]; memset((void *)excluded,0,PER_MAXSIZE); while (repeating) { int count = 0; int lineposOld = *linepos; int matchOld = *match; parserNode *nodeIter = node->firstChild; int wo = 0, secondPass=0; repeating=0; while (nodeIter != NULL) { if (excluded[count]) { nodeIter=nodeIter->nextSibling; count++; continue; } status = parse_descend(c,s,wo,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (secondPass) { excluded[count]=1; repeating=1; break; } if (status==3) { status=0; } if (status==0) { *linepos=lineposOld; *match=matchOld; nodeIter=nodeIter->nextSibling; count++; continue; } if (status==2) goto cleanup; *linepos=lineposOld; *match=matchOld; wo=writeOut; secondPass=1; } } status=1; goto cleanup; } case PN_TYPE_ORA: { int lineposOld = *linepos; int matchOld = *match; parserNode *nodeIter = node->firstChild; int wo = 0, secondPass=0; while (nodeIter != NULL) { status = parse_descend(c,s,wo,srcLineN,srcId,srcFname,line,linepos,nodeIter,tabCompNo,tabCompStart,tabCompTxt,level+1,blockDepth,match); if (secondPass) goto cleanup; if (status==3) { status=0; goto cleanup; } if (status==0) { *linepos=lineposOld; *match=matchOld; nodeIter=nodeIter->nextSibling; continue; } if (status==2) goto cleanup; *linepos=lineposOld; *match=matchOld; wo=writeOut; secondPass=1; } goto cleanup; } default: { sprintf(c->errcontext.tempErrStr, "Hit an unexpected node type %d.", node->type); ppl_fatal(&c->errcontext,__FILE__,__LINE__,NULL); } } cleanup: // If we are not going back for another line in a CODEBLOCK, clear the parserNode stack if (s!=NULL) { if (status!=3) s->stk[blockDepth][level] = NULL; else s->stk[blockDepth][level] = node; } // If we are at the top level of the hierarchy and we have failed to parse, throw a traceback now. // If we have succeeded in parsing, we should by now have consumed a whole line; if there is trailig text, that's an error if ((level==0) && (status<2) && (s!=NULL)) { if (status==1) { while ((line[*linepos]>'\0') && (line[*linepos]<=' ')) (*linepos)++; if (line[*linepos]!='\0') { if (s->eLlinePos <= *linepos) { if (s->eLlinePos < *linepos) { s->eLlinePos = *linepos; s->eLPos = 0; s->expectingList[0]='\0'; } if (s->eLPos>0) { snprintf(s->expectingList+s->eLPos,LSTR_LENGTH-s->eLPos,", or "); s->eLPos+=strlen(s->expectingList+s->eLPos); } snprintf(s->expectingList+s->eLPos,LSTR_LENGTH-s->eLPos,"the end of the command"); s->eLPos+=strlen(s->expectingList+s->eLPos); } status=0; } } if (status==0) { snprintf(c->errStat.errBuff,LSTR_LENGTH,"At this point, was expecting %s.",s->expectingList); c->errStat.errBuff[LSTR_LENGTH-1] = '\0'; PARSE_TBADD(ERR_SYNTAX,s->eLlinePos,line); } } if (status==1) ppl_tbClear(c); if ((s!=NULL)&&(status!=3)) s->blockDepth=0; if ((s!=NULL)&&(status!=3)&&(level==0)) s->NinlineDatafiles[blockDepth]=0; //printf("%d %d %d %d\n",blockDepth,level,status,s->blockDepth); return status; } void ppl_parserAtomFree(parserAtom **in) { parserAtom *i; if (in==NULL) return; i = *in; while (i!=NULL) { parserAtom *next = i->next; if (i->literal!=NULL) ppl_garbageObject(i->literal); if (i->expr !=NULL) pplExpr_free(i->expr); free(i); i = next; } *in=NULL; return; } void ppl_parserStatInit(parserStatus **in, parserLine **pl) { *in = (parserStatus *)malloc(sizeof(parserStatus)); if (*in==NULL) return; *pl = NULL; (*in)->rootpl = pl; ppl_parserStatReInit(*in); return; } void ppl_parserStatReInit(parserStatus *in) { int i,j; parserLine **pl = in->rootpl; if (*pl != NULL) ppl_parserLineFree(*pl); *pl = NULL; for (i=0; ipl[i]=NULL; for (i=0; istk[i][j]=NULL; for (i=0; ioutputPos[i] = -1; strcpy(in->prompt, "pyxplot"); in->blockDepth = 0; for (i=0; iNinlineDatafiles[i] = 0; in->waitingForBrace = 0; in->eLPos = 0; in->eLlinePos = 0; in->expectingList[0] = '\0'; return; } void ppl_parserStatAdd(parserStatus *in, int bd, parserLine *pl) { if (in->pl[bd] != NULL) { pl->prev = in->pl[bd]; in->pl[bd]->next = pl; in->pl[bd] = pl; } else { if (bd==0) *(in->rootpl) = pl; pl->prev = NULL; in->pl[bd] = pl; } return; } void ppl_parserStatFree(parserStatus **in) { parserLine **pl = (*in)->rootpl; if (*pl != NULL) ppl_parserLineFree(*pl); *pl = NULL; free(*in); *in = NULL; } void ppl_parserLineInit(parserLine **in, int srcLineN, long srcId, char *srcFname, char *line) { parserLine *output=NULL; *in = NULL; // Initialise output structure output = (parserLine *)malloc(sizeof(parserLine)); if (output==NULL) return; output->linetxt = (char *)malloc(strlen(line)+1); if (output->linetxt==NULL) { free(output); return; } strcpy(output->linetxt, line); output->srcFname = (char *)malloc(strlen(srcFname)+1); if (output->srcFname==NULL) { free(output->linetxt); free(output); return; } strcpy(output->srcFname, srcFname); output->firstAtom = NULL; output->lastAtom = NULL; output->next = NULL; output->prev = NULL; output->containsMacros = 0; output->refCount = 1; output->srcLineN = srcLineN; output->srcId = srcId; output->stackLen = 16; output->stackOffset = 0; *in = output; return; } void ppl_parserLineFree(parserLine *in) { parserLine *item = in; if (in==NULL) return; if ( __sync_sub_and_fetch(&in->refCount,1) > 0) return; while (item != NULL) { parserLine *next = item->next; ppl_parserAtomFree(&item->firstAtom); if (item->linetxt !=NULL) free(item->linetxt); if (item->srcFname!=NULL) free(item->srcFname); free(item); item = next; } return; } #define LOOP_OVER_LINE \ { \ int i; char quoteChar; \ for (i=0 , quoteChar='\0'; line[i]!='\0'; i++) \ { \ if ((quoteChar=='\0') && (line[i]=='\'') ) quoteChar = '\''; \ else if ((quoteChar=='\0') && (line[i]=='\"') ) quoteChar = '\"'; \ else if ((quoteChar=='\'') && (line[i]=='\'') && (line[i-1]!='\\')) quoteChar = '\0'; \ else if ((quoteChar=='\"') && (line[i]=='\"') && (line[i-1]!='\\')) quoteChar = '\0'; \ #define LOOP_END(X) \ else if (X) \ { \ if (obPos > obLen-16) { obLen += LSTR_LENGTH; outbuff = (char *)realloc(outbuff, obLen); if (outbuff==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); fail=1; break; } } \ outbuff[obPos++] = line[i]; \ } \ } \ } #define TEST_FOR_MACROS \ containsMacros=0; \ LOOP_OVER_LINE \ else if ((quoteChar=='\0') && (line[i]=='`')) { containsMacros=1; break; } \ else if ((quoteChar=='\0') && (line[i]=='@')) { containsMacros=1; break; } \ LOOP_END(0) int ppl_parserCompile(ppl_context *c, parserStatus *s, int srcLineN, long srcId, char *srcFname, char *line, int expandMacros, int blockDepth) { listIterator *cmdIter=NULL; int i, cln, containsMacros=0; int obLen = LSTR_LENGTH, obPos; char *outbuff = NULL; c->algebraErrPos = c->errStat.oldErrPosExpr = c->errStat.oldErrPosCmd = -1; if (blockDepth > MAX_RECURSION_DEPTH) { strcpy(c->errStat.errBuff,"Maximum recursion depth exceeded."); PARSE_TBADD(ERR_OVERFLOW,0,line); ppl_parserStatReInit(s); return 1; } // Deal with macros and ` ` substitutions if (!expandMacros) { int fail=0; TEST_FOR_MACROS; if (containsMacros && (s!=NULL) && !fail) // If we're not expanding macros at this stage, flag this parserLine as containing macros, and exit { const int bd = ppl_max(blockDepth,s->blockDepth); if (s->waitingForBrace) { sprintf(c->errStat.errBuff,"Cannot process a macro on the same line as the opening brace of a loop."); PARSE_TBADD(ERR_SYNTAX,0,line); ppl_parserStatReInit(s); return 1; } parserLine *output=NULL; if ((s->stk[blockDepth][0]==NULL)&&(blockDepth==0)) ppl_parserStatReInit(s); ppl_parserLineInit(&output, srcLineN, srcId, srcFname, line); if (output==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); PARSE_TBADD(ERR_MEMORY,0,line); ppl_parserStatReInit(s); return 1; } output->stackLen = 0; output->containsMacros = 1; ppl_parserStatAdd(s, bd, output); if ((bd>0)&&(s->outputPos[bd-1]>=0)) { pplObj val; val.refCount=1; pplObjBytecode(&val,0,(void *)s->pl[bd]); ppl_parserAtomAdd(s->pl[bd-1], s->outputPos[bd-1], 0, "", NULL, &val); s->outputPos[bd-1]=-1; } return 0; } } else { char *lineOriginal = line; int l=0, fail=0;; for (l=0; (l<16)&&!fail; l++) // Repeatedly test for and substitute macros; nested macros are allowed { TEST_FOR_MACROS; if (fail || !containsMacros) break; { outbuff = (char *)malloc(obLen); obPos = 0; if (outbuff!=NULL) LOOP_OVER_LINE // First, substitute for ` ` expressions else if ((quoteChar=='\0') && (line[i]=='`')) { int is=++i, status; char *key=NULL; FILE *substPipe; for ( ; ((line[i]!='\0')&&(line[i]!='`')) ; i++); // Find end of ` ` expression if (line[i]!='`') { sprintf(c->errStat.errBuff, "Mismatched `"); fail=1; break; } key = (char *)malloc(i-is+1); // Put macro name into a string if (key==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); fail=1; break; } strncpy(key, line+is, i-is); key[i-is]='\0'; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Shell substitution with command '%s'.", key); ppl_log(&c->errcontext,NULL); } if ((substPipe = popen(key,"r"))==NULL) { sprintf(c->errStat.errBuff, "Could not spawl shell substitution command '%s'.", key); fail=1; goto shellSubstErr; } while ((!feof(substPipe)) && (!ferror(substPipe))) { if (fscanf(substPipe,"%c",outbuff+obPos) == EOF) break; if (outbuff[obPos]=='\n') outbuff[obPos] = ' '; if (outbuff[obPos]!='\0') obPos++; if (obPos > obLen-16) { obLen += LSTR_LENGTH; outbuff = (char *)realloc(outbuff, obLen); if (outbuff==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); fail=1; break; } } \ } status = pclose(substPipe); if (fail) goto shellSubstErr; if (WIFEXITED(status)) { int ec = WEXITSTATUS(status); if (ec) { sprintf(c->errStat.errBuff, "Command failure during ` ` substitution (exit code %d).", ec); fail=1; goto shellSubstErr; } } else if (WIFSIGNALED(status)) { sprintf(c->errStat.errBuff, "Command failure during ` ` substitution (terminated by signal %d).", WTERMSIG(status)); fail=1; goto shellSubstErr; } else { sprintf(c->errStat.errBuff, "Command failure during ` ` substitution (fail happened)."); fail=1; goto shellSubstErr; } shellSubstErr: if (key!=NULL) free(key); if (fail) break; } // Second, substitute for macros else if ((quoteChar=='\0') && (line[i]=='@')) { int is=++i, j, got=0; char *key=NULL; for ( ; (isalnum(line[i])||(line[i]=='_')) ; i++); // Find end of macro name key = (char *)malloc(i-is+1); // Put macro name into a string if (key==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); fail=1; break; } strncpy(key, line+is, i-is); key[i-is]='\0'; for (j=1; j>=0 ; j--) { pplObj *obj = (pplObj *)ppl_dictLookup(c->namespaces[j] , key); if (obj==NULL) continue; if ((obj->objType==PPLOBJ_GLOB)||(obj->objType==PPLOBJ_ZOM)) continue; if (obj->objType!=PPLOBJ_STR) { sprintf(c->errStat.errBuff,"Attempt to expand a macro, \"%s\", which is not a string variable.", key); got=-1; break; } if (obPos+strlen((char *)obj->auxil) > obLen-16) { obLen+=strlen((char *)obj->auxil) + LSTR_LENGTH; outbuff = (char *)realloc(outbuff, obLen); if (outbuff==NULL) { got=-2; break; } } strcpy(outbuff+obPos,(char *)obj->auxil); obPos += strlen(outbuff+obPos); got=1; break; } if (got==0) { sprintf(c->errStat.errBuff,"Undefined macro, \"%s\".",key); } free(key); if (got<=0) { fail=1; break; } i--; } LOOP_END(1); outbuff[obPos++]='\0'; // Clean up after macro substitution if ((!fail)&&(outbuff!=NULL)) { if (line!=lineOriginal) free(line); line = outbuff; } else if (outbuff!=NULL) { free(outbuff); outbuff=NULL; } } } if (fail) { PARSE_TBADD(ERR_SYNTAX,0,line); ppl_parserStatReInit(s); return 1; } } // If we are returning to add more code into a codeblock, do that now if (s->stk[blockDepth][0] != NULL) { int match=0, linepos=0; s->eLPos = s->eLlinePos = 0; s->expectingList[0] = '\0'; parse_descend(c, s, 1, srcLineN, srcId, srcFname, line, &linepos, NULL, NULL, -1, NULL, 0, blockDepth, &match); if (c->errStat.status) { if (outbuff!=NULL) free(outbuff); ppl_parserStatReInit(s); return 1; } return 0; } // If we're not adding more code to a codeBlock, and this is a top-level call, clean the stack if (blockDepth==0) ppl_parserStatReInit(s); // Fetch first non-whitespace character of command string for (i=0; ((line[i]>='\0')&&(line[i]<=' ')); i++); if ((line[i]>='a')&&(line[i]<='z')) cln=(int)(line[i]-'a'); else if ((line[i]>='A')&&(line[i]<='Z')) cln=(int)(line[i]-'A'); else cln=26; // Cycle through possible command matches cmdIter = ppl_listIterateInit(pplParserCmdList[cln]); while (1) { int match=0, linepos=0; parserNode *item; if (cmdIter == NULL) // Once we've finished cycling through commands that start with punctuation, cycle through ones that start with first letter { if (cln==26) break; cmdIter = ppl_listIterateInit(pplParserCmdList[cln=26]); if (cmdIter==NULL) break; } // Fetch next item from list of possible commands and try to parse it item = (parserNode *)ppl_listIterate(&cmdIter); match = linepos = 0; parse_descend(c, s, 1, srcLineN, srcId, srcFname, line, &linepos, item, NULL, -1, NULL, 0, blockDepth, &match); // If this command did not match as far as the '=' token, clear stack and traceback if (match==0) { parserLine *new = s->pl[blockDepth]; parserLine *old = new->prev; ppl_tbClear(c); c->errStat.oldErrPosExpr = c->errStat.oldErrPosCmd = c->algebraErrPos = -1; ppl_parserLineFree(new); s->pl[blockDepth]=old; if (old!=NULL) old->next=NULL; if ((blockDepth==0)&&(old==NULL)) *(s->rootpl)=NULL; s->eLPos = s->eLlinePos = 0; s->expectingList[0] = '\0'; continue; } // If we did match as far as '=', but got an error traceback, free the stack and return to the user if (c->errStat.status) { if (outbuff!=NULL) free(outbuff); ppl_parserStatReInit(s); return 1; } // Success! if (outbuff!=NULL) free(outbuff); return 0; } // We have not found a match to this command sprintf(c->errStat.errBuff, "Unrecognised command."); PARSE_TBADD(ERR_SYNTAX,0,line); if (outbuff!=NULL) free(outbuff); ppl_parserStatReInit(s); return 1; } #ifdef HAVE_READLINE static ppl_context *rootContext = NULL; void ppl_parseAutocompleteSetContext(ppl_context *c) { rootContext = c; return; } char *ppl_parseAutocomplete(const char *dummy, int status) { static int matchNum=0, start=0; static char *linebuff = NULL, *line = NULL; char *output = NULL; // We are called once with negative status to set up static varaibles, before readline calls us with status>=0 if (status<0) { start = -status-1; matchNum = -1; if (line != NULL) { free(linebuff); linebuff=NULL; } if (rootContext->inputLineAddBuffer == NULL) // If we're on the second line of a continued line, add InputLineAddBuffer to beginning of line { line = rl_line_buffer; } else { int i = strlen(rl_line_buffer) + strlen(rootContext->inputLineAddBuffer); if ((linebuff = (char *)malloc(i+1))==NULL) return NULL; strcpy(linebuff, rootContext->inputLineAddBuffer); strcpy(linebuff+strlen(linebuff) , rl_line_buffer); linebuff[i] = '\0'; line = linebuff; start += strlen(rootContext->inputLineAddBuffer); } } // Look for possible tab completions. Do this in a while loop, since if we get a %s filename completion, we search again while (1) { int cln=0; listIterator *cmdIter=NULL; int number = matchNum++; char tabCompTxt[FNAME_LENGTH] = "\0"; if (number<0) number=0; // Return first item twice // Loop over all of the possible commands that could be intended while (1) { int match=0, linepos=0; parserNode *item; if (cmdIter == NULL) // Once we've finished cycling through each list, move onto the next one { if (cln==27) break; cmdIter = ppl_listIterateInit(pplParserCmdList[cln++]); if (cmdIter==NULL) continue; } // Fetch next item from list of possible commands and try to parse it item = (parserNode *)ppl_listIterate(&cmdIter); match = linepos = 0; parse_descend(rootContext, NULL, 0, -1, -1, "", line, &linepos, item, &number, start, tabCompTxt, 0, 0, &match); if (tabCompTxt[0] == '\n') // Special case: use Readline's filename tab completion { if (status < 0) // On initial pass through, it's not too late to tell wrapper to use readline's own completer { if ((output = (char *)malloc(strlen(tabCompTxt)+1))==NULL) return NULL; strcpy(output, tabCompTxt); return output; } else { // On subsequent pass-throughs, it's too late... break; } } if (tabCompTxt[0] != '\0') // We have a new completion option; do not iterate through more commands { if ((output = (char *)malloc(strlen(tabCompTxt)+1))==NULL) return NULL; strcpy(output, tabCompTxt); return output; } } if (tabCompTxt[0] == '\n') continue; // We've been asked to match filenames, but have already made other Pyxplot syntax suggestions... skip on and return next match else break; } return NULL; // Tell readline we have no more matches to offer } char **ppl_rl_completion(const char *text, int start, int end) { char **matches; char *firstItem; if ((start>0)&&((rl_line_buffer[start-1]=='\"')||(rl_line_buffer[start-1]=='\''))) return NULL; // Do filename completion firstItem = ppl_parseAutocomplete(text, -1-start); // Setup parse_autocomplete to know what string it's working on if (firstItem!=NULL) { if (firstItem[0]=='\n') // We are trying to match a %s:filename field, so turn on filename completion { free(firstItem); rl_attempted_completion_over = 1; // NULL means that readline's default filename completer is activated return NULL; } else { free(firstItem); } } matches = rl_completion_matches(text, ppl_parseAutocomplete); rl_attempted_completion_over = 1; // Make sure that filenames are not completion options return matches; } #endif pyxplot-0.9.2/src/canvasItems.c0000664000175000017500000030615312026340554015044 0ustar dcf21dcf21// canvasItems.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: canvasItems.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CANVASITEMS_C 1 #include #include #include #include #include #include #include "canvasItems.h" #include "datafile.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "epsMaker/canvasDraw.h" #include "epsMaker/eps_plot.h" #include "epsMaker/eps_plot_styles.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "settings/arrows_fns.h" #include "settings/axes_fns.h" #include "settings/labels_fns.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #define TBADD(et,msg,pos) { strcpy(c->errStat.errBuff, msg); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,""); } #define TBADD2(et,pos) { ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,""); } // Free a node in the multiplot canvas item list static void canvas_item_delete(ppl_context *c, canvas_item *ptr) { int i; canvas_itemlist *canvas_items = c->canvas_items; canvas_plotrange *pr, *pr2; canvas_plotdesc *pd, *pd2; if (ptr->polygonPoints != NULL) free(ptr->polygonPoints); if (ptr->text != NULL) free(ptr->text); ppl_withWordsDestroy(c, &(ptr->settings.dataStyle)); ppl_withWordsDestroy(c, &(ptr->settings.funcStyle)); pplExpr_free(ptr->settings.ColMapExpr); pplExpr_free(ptr->settings.MaskExpr); pplExpr_free(ptr->settings.c1format); if (ptr->XAxes != NULL) { for (i=0; iXAxes[i]) ); free(ptr->XAxes); } if (ptr->YAxes != NULL) { for (i=0; iYAxes[i]) ); free(ptr->YAxes); } if (ptr->ZAxes != NULL) { for (i=0; iZAxes[i]) ); free(ptr->ZAxes); } pplarrow_list_destroy(c, &(ptr->arrow_list)); ppllabel_list_destroy(c, &(ptr->label_list)); ppl_withWordsDestroy(c, &(ptr->with_data)); // Delete range structures pr = ptr->plotranges; while (pr != NULL) { pr2 = pr->next; free(pr); pr = pr2; } // Delete plot item descriptors pd = ptr->plotitems; while (pd != NULL) { pd2 = pd->next; if (pd->functions != NULL) for (i=0; iNFunctions; i++) pplExpr_free ( pd->functions[i]); if (pd->UsingList != NULL) for (i=0; iNUsing ; i++) pplExpr_free ( pd->UsingList[i]); if (pd->vectors != NULL) for (i=0; iNFunctions; i++) ppl_garbageObject(&pd->vectors [i]); if (pd->filename != NULL) free(pd->filename); if (pd->functions != NULL) free(pd->functions); if (pd->vectors != NULL) free(pd->vectors); if (pd->label != NULL) pplExpr_free(pd->label); if (pd->SelectCriterion != NULL) pplExpr_free(pd->SelectCriterion); if (pd->title != NULL) free(pd->title); if (pd->UsingList != NULL) free(pd->UsingList); ppl_withWordsDestroy(c, &pd->ww); ppl_withWordsDestroy(c, &pd->ww_final); free(pd); pd = pd2; } // Reseal doubly-linked list if (ptr->prev != NULL) ptr->prev->next = ptr->next; else canvas_items->first = ptr->next; if (ptr->next != NULL) ptr->next->prev = ptr->prev; else canvas_items->last = ptr->prev; free(ptr); return; } // Add a new multiplot canvas item to the list above static int canvas_itemlist_add(ppl_context *c, pplObj *command, int type, canvas_item **output, int *id, unsigned char includeAxes) { canvas_itemlist *canvas_items; canvas_item *ptr, *next, *prev, **insertpointA, **insertpointB; int i, editNo, gotEditNo; // If we're not in multiplot mode, clear the canvas now if (c->set->term_current.multiplot == SW_ONOFF_OFF) ppl_directive_clear(c, NULL, NULL, 0); canvas_items = c->canvas_items; // Ensure that multiplot canvas list is initialised before trying to use it if (canvas_items == NULL) { canvas_items = (canvas_itemlist *)malloc(sizeof(canvas_itemlist)); if (canvas_items == NULL) return 1; c->canvas_items = (void *)canvas_items; canvas_items->first = NULL; canvas_items->last = NULL; } gotEditNo = (command[PARSE_arc_editno].objType == PPLOBJ_NUM); if (!gotEditNo) { int prevId; insertpointA = &(canvas_items->last); next = NULL; prev = (*insertpointA==NULL) ? NULL : canvas_items->last; insertpointB = (*insertpointA==NULL) ? &(canvas_items->first) : &(canvas_items->last->next); prevId = (*insertpointA==NULL) ? 0 : canvas_items->last->id; editNo = prevId+1; } else { editNo = (int)round(command[PARSE_arc_editno].real); insertpointB = &(canvas_items->first); prev = NULL; while ((*insertpointB != NULL) && ((*insertpointB)->id < editNo)) { prev = *insertpointB; insertpointB = &((*insertpointB)->next); } next = *insertpointB; if (next==NULL) { insertpointA = &(canvas_items->last); } else if (next->id == editNo) { next = next->next; if (next==NULL) insertpointA = &(canvas_items->last); else insertpointA = &(next->prev); canvas_item_delete(c, *insertpointB); } else { insertpointA = &(next->prev); } } ptr = (canvas_item *)malloc(sizeof(canvas_item)); if (ptr==NULL) return 1; *insertpointA = *insertpointB = ptr; ptr->next = next; // Link doubly-linked list ptr->prev = prev; ptr->polygonPoints = NULL; ptr->text = NULL; ptr->plotitems = NULL; ptr->plotranges = NULL; ptr->id = editNo; ptr->type = type; ptr->deleted = 0; ppl_withWordsZero(c, &ptr->with_data); // Copy the user's current settings ptr->settings = c->set->graph_current; ptr->settings.ColMapExpr = pplExpr_cpy(c->set->graph_current.ColMapExpr); ptr->settings.MaskExpr = pplExpr_cpy(c->set->graph_current.MaskExpr); ptr->settings.c1format = pplExpr_cpy(c->set->graph_current.c1format); ppl_withWordsCpy(c, &ptr->settings.dataStyle , &c->set->graph_current.dataStyle); ppl_withWordsCpy(c, &ptr->settings.funcStyle , &c->set->graph_current.funcStyle); if (includeAxes) { ptr->XAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); ptr->YAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); ptr->ZAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); if ((ptr->XAxes==NULL)||(ptr->YAxes==NULL)||(ptr->ZAxes==NULL)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (A)."); if (ptr->XAxes!=NULL) { free(ptr->XAxes); ptr->XAxes = NULL; } if (ptr->YAxes!=NULL) { free(ptr->YAxes); ptr->YAxes = NULL; } if (ptr->ZAxes!=NULL) { free(ptr->ZAxes); ptr->ZAxes = NULL; } free(ptr); return 1; } else { for (i=0; iXAxes[i]), &(c->set->XAxes[i])); for (i=0; iYAxes[i]), &(c->set->YAxes[i])); for (i=0; iZAxes[i]), &(c->set->ZAxes[i])); } pplarrow_list_copy(c, &ptr->arrow_list , &c->set->pplarrow_list); ppllabel_list_copy(c, &ptr->label_list , &c->set->ppllabel_list); } else { ptr->XAxes = ptr->YAxes = ptr->ZAxes = NULL; ptr->arrow_list = NULL; ptr->label_list = NULL; } *output = ptr; // Return pointer to the newly-created canvas item *id = ptr->id; return 0; } // Implementation of the clear command. Also called whenever the canvas is to be cleared. int ppl_directive_clear(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { canvas_itemlist *canvas_items = c->canvas_items; canvas_item *ptr, *next; if (canvas_items == NULL) return 0; ptr = canvas_items->first; while (ptr != NULL) { next = ptr->next; ptr->prev = NULL; canvas_item_delete(c, ptr); ptr = next; } free(canvas_items); c->canvas_items = NULL; c->replotFocus = -1; return 0; } // Produce a textual representation of the command which would need to be typed to produce any given canvas item char *ppl_canvas_item_textify(ppl_context *c, canvas_item *ptr, char *output) { int i,j; if (ptr->type == CANVAS_ARROW) // Produce textual representations of arrow commands { sprintf(output, "%s item %d from %s,%s to %s,%s with %s", (ptr->ArrowType==SW_ARROWTYPE_NOHEAD) ? "line" : "arrow", ptr->id, ppl_numericDisplay( ptr->xpos *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->ypos *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay((ptr->xpos+ptr->xpos2)*100, c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay((ptr->ypos+ptr->ypos2)*100, c->numdispBuff[3], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), *(char **)ppl_fetchSettingName(&c->errcontext, ptr->ArrowType, SW_ARROWTYPE_INT, (void *)SW_ARROWTYPE_STR, sizeof(char *)) ); i = strlen(output); ppl_withWordsPrint(c, &ptr->with_data, output+i+1); if (strlen(output+i+1)>0) { output[i]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_BOX ) // Produce textual representations of box commands { sprintf(output, "box item %d ", ptr->id); i = strlen(output); sprintf(output+i, ptr->xpos2set ? "at %s,%s width %s height %s" : "from %s,%s to %s,%s", ppl_numericDisplay( ptr->xpos *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->ypos *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay((ptr->xpos*(!ptr->xpos2set)+ptr->xpos2)*100, c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay((ptr->ypos*(!ptr->xpos2set)+ptr->ypos2)*100, c->numdispBuff[3], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); sprintf(output+i, " rotate %s", ppl_numericDisplay(ptr->rotation * 180/M_PI , c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_CIRC ) // Produce textual representations of circle commands { sprintf(output, "%s item %d at %s,%s radius %s", ptr->xfset ? "arc" : "circle", ptr->id, ppl_numericDisplay( ptr->xpos *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->ypos *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->xpos2 *100, c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i = strlen(output); if (ptr->xfset) { sprintf(output+i," from %s to %s", ppl_numericDisplay( ptr->xf *180/M_PI, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->yf *180/M_PI, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); } ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_ELLPS) // Produce textual representations of ellipse commands { sprintf(output, "ellipse item %d", ptr->id); i = strlen(output); if (ptr->x1set ) sprintf(output+i, " from %s,%s to %s,%s", ppl_numericDisplay( ptr->x1 *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->y1 *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->x2 *100, c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->y2 *100, c->numdispBuff[3], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->xcset ) sprintf(output+i, " centre %s,%s", ppl_numericDisplay( ptr->xc *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->yc *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->xfset ) sprintf(output+i, " focus %s,%s", ppl_numericDisplay( ptr->xf *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->yf *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->aset ) sprintf(output+i, " SemiMajorAxis %s", ppl_numericDisplay( ptr->a *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->bset ) sprintf(output+i, " SemiMinorAxis %s", ppl_numericDisplay( ptr->b *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->eccset) sprintf(output+i, " eccentricity %s", ppl_numericDisplay( ptr->ecc , c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->slrset) sprintf(output+i, " SemiLatusRectum %s", ppl_numericDisplay( ptr->slr *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->arcset) sprintf(output+i, " arc from %s to %s", ppl_numericDisplay( ptr->arcfrom*180/M_PI, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->arcto *180/M_PI, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); sprintf(output+i, " rotate %s", ppl_numericDisplay( ptr->rotation *180/M_PI , c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_EPS ) // Produce textual representations of eps commands { sprintf(output, "eps item %d ", ptr->id); i = strlen(output); ppl_strEscapify(ptr->text, output+i); i += strlen(output+i); sprintf(output+i, " at %s,%s", ppl_numericDisplay(ptr->xpos*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay(ptr->ypos*100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->xpos2set) sprintf(output+i, " width %s" , ppl_numericDisplay(ptr->xpos2*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L))); i += strlen(output+i); if (ptr->ypos2set) sprintf(output+i, " height %s", ppl_numericDisplay(ptr->ypos2*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L))); i += strlen(output+i); sprintf(output+i, " rotate %s", ppl_numericDisplay(ptr->rotation * 180/M_PI , c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->clip ) { sprintf(output+i, " clip" ); i += strlen(output+i); } if (ptr->calcbbox) { sprintf(output+i, " calcbbox"); i += strlen(output+i); } } else if (ptr->type == CANVAS_IMAGE) // Produce textual representations of image commands { sprintf(output, "image item %d ", ptr->id); i = strlen(output); ppl_strEscapify(ptr->text, output+i); i += strlen(output+i); sprintf(output+i, " at %s,%s", ppl_numericDisplay(ptr->xpos*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay(ptr->ypos*100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); if (ptr->smooth ) { sprintf(output+i, " smooth"); i += strlen(output+i); } if (ptr->NoTransparency ) { sprintf(output+i, " NoTransparency"); i += strlen(output+i); } if (ptr->CustomTransparency) { sprintf(output+i, " transparent rgb%d:%d:%d", ptr->TransColR, ptr->TransColG, ptr->TransColB); i += strlen(output+i); } if (ptr->xpos2set) sprintf(output+i, " width %s" , ppl_numericDisplay(ptr->xpos2*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L))); i += strlen(output+i); if (ptr->ypos2set) sprintf(output+i, " height %s", ppl_numericDisplay(ptr->ypos2*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L))); i += strlen(output+i); sprintf(output+i, " rotate %s", ppl_numericDisplay(ptr->rotation * 180/M_PI , c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); } else if (ptr->type == CANVAS_PIE) // Produce textual representations of piechart commands { canvas_plotdesc *pd; sprintf(output, "piechart item %d", ptr->id); i = strlen(output); pd = ptr->plotitems; if (pd!=NULL) { if (!pd->function) { if ( (pd->filename != NULL) || (pd->vectors != NULL) ) { output[i++]=' '; ppl_strEscapify(pd->filename, output+i); i+=strlen(output+i); // Filename of datafile we are plotting } } else for (j=0; jNFunctions; j++) // Print out the list of functions which we are plotting { output[i++]=(j!=0)?':':' '; ppl_strStrip(pd->functions[j]->ascii , output+i); i+=strlen(output+i); } if (pd->EverySet>0) { sprintf(output+i, " every %ld", pd->EveryList[0]); i+=strlen(output+i); } // Print out 'every' clause of plot command if (pd->EverySet>1) { sprintf(output+i, ":%ld", pd->EveryList[1]); i+=strlen(output+i); } if (pd->EverySet>2) { sprintf(output+i, ":%ld", pd->EveryList[2]); i+=strlen(output+i); } if (pd->EverySet>3) { sprintf(output+i, ":%ld", pd->EveryList[3]); i+=strlen(output+i); } if (pd->EverySet>4) { sprintf(output+i, ":%ld", pd->EveryList[4]); i+=strlen(output+i); } if (pd->EverySet>5) { sprintf(output+i, ":%ld", pd->EveryList[5]); i+=strlen(output+i); } if (ptr->text==NULL) { sprintf(output+i, " format auto"); i+=strlen(output+i); } else { sprintf(output+i, " format %s", ptr->text); i+=strlen(output+i); } if (pd->IndexSet) { sprintf(output+i, " index %d", pd->index); i+=strlen(output+i); } // Print index to use if ((pd->label!=NULL) || (ptr->ArrowType!=SW_PIEKEYPOS_AUTO)) { sprintf(output+i, " label %s", *(char **)ppl_fetchSettingName(&c->errcontext, ptr->ArrowType, SW_PIEKEYPOS_INT, (void *)SW_PIEKEYPOS_STR, sizeof(char *))); i+=strlen(output+i); if (pd->label!=NULL) sprintf(output+i, " %s", pd->label->ascii); // Print label string i+=strlen(output+i); } if (pd->SelectCriterion!=NULL) { sprintf(output+i, " select %s", pd->SelectCriterion->ascii); i+=strlen(output+i); } // Print select criterion ppl_withWordsPrint(c, &pd->ww, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } i+=strlen(output+i); sprintf(output+i, " using %s", (pd->UsingRowCols==DATAFILE_COL)?"columns":"rows"); i+=strlen(output+i); // Print using list for (j=0; jNUsing; j++) { output[i++]=(j!=0)?':':' '; strcpy(output+i, pd->UsingList[j]->ascii); i+=strlen(output+i); } } } else if (ptr->type == CANVAS_PLOT) // Produce textual representations of plot commands { canvas_plotrange *pr; canvas_plotdesc *pd; pplObj v; unsigned char pr_first=1, pd_first=1; sprintf(output, "plot item %d", ptr->id); i = strlen(output); if (ptr->ThreeDim) strcpy(output+i, " 3d"); i += strlen(output+i); pr = ptr->plotranges; // Print out plot ranges while (pr != NULL) { if (pr_first) { output[i++]=' '; pr_first=0; } output[i++]='['; if (pr->AutoMinSet) output[i++]='*'; if (pr->MinSet) { v=pr->unit; v.real=pr->min; sprintf(output+i, "%s", ppl_unitsNumericDisplay(c,&v,0,0,0)); i+=strlen(output+i); } if (pr->MinSet || pr->MaxSet || pr->AutoMinSet || pr->AutoMaxSet) { strcpy(output+i,":"); i+=strlen(output+i); } if (pr->AutoMaxSet) output[i++]='*'; if (pr->MaxSet) { v=pr->unit; v.real=pr->max; sprintf(output+i, "%s", ppl_unitsNumericDisplay(c,&v,0,0,0)); i+=strlen(output+i); } strcpy(output+i,"]"); i+=strlen(output+i); pr = pr->next; } pd = ptr->plotitems; // Print out plotted items one by one while (pd != NULL) { if (pd_first) { pd_first=0; } else { output[i++]=','; } if (pd->parametric) { sprintf(output+i, " parametric"); i+=strlen(output+i); } if (pd->TRangeSet) { sprintf(output+i, " [%s:%s]", ppl_unitsNumericDisplay(c,&pd->Tmin,0,0,0), ppl_unitsNumericDisplay(c,&pd->Tmax,1,0,0)); i+=strlen(output+i); } if (pd->VRangeSet) { sprintf(output+i, " [%s:%s]", ppl_unitsNumericDisplay(c,&pd->Vmin,0,0,0), ppl_unitsNumericDisplay(c,&pd->Vmax,1,0,0)); i+=strlen(output+i); } if ( (!pd->function) || (pd->vectors != NULL) ) { if (pd->filename != NULL) { output[i++]=' '; ppl_strEscapify(pd->filename, output+i); i+=strlen(output+i); // Filename of datafile we are plotting } } else for (j=0; jNFunctions; j++) // Print out the list of functions which we are plotting { output[i++]=(j!=0)?':':' '; ppl_strStrip(pd->functions[j]->ascii , output+i); i+=strlen(output+i); } if (pd->axis1set || pd->axis2set || pd->axis3set) // Print axes to use { strcpy(output+i, " axes "); i+=strlen(output+i); if (pd->axis1set) { sprintf(output+i, "%c%d", "xyzc"[pd->axis1xyz], pd->axis1); i+=strlen(output+i); } if (pd->axis2set) { sprintf(output+i, "%c%d", "xyzc"[pd->axis2xyz], pd->axis2); i+=strlen(output+i); } if (pd->axis3set) { sprintf(output+i, "%c%d", "xyzc"[pd->axis3xyz], pd->axis3); i+=strlen(output+i); } } if (pd->EverySet>0) { sprintf(output+i, " every %ld", pd->EveryList[0]); i+=strlen(output+i); } // Print out 'every' clause of plot command if (pd->EverySet>1) { sprintf(output+i, ":%ld", pd->EveryList[1]); i+=strlen(output+i); } if (pd->EverySet>2) { sprintf(output+i, ":%ld", pd->EveryList[2]); i+=strlen(output+i); } if (pd->EverySet>3) { sprintf(output+i, ":%ld", pd->EveryList[3]); i+=strlen(output+i); } if (pd->EverySet>4) { sprintf(output+i, ":%ld", pd->EveryList[4]); i+=strlen(output+i); } if (pd->EverySet>5) { sprintf(output+i, ":%ld", pd->EveryList[5]); i+=strlen(output+i); } if (pd->IndexSet) { sprintf(output+i, " index %d", pd->index); i+=strlen(output+i); } // Print index to use if (pd->label!=NULL) { sprintf(output+i, " label %s", pd->label->ascii); i+=strlen(output+i); } // Print label string if (pd->SelectCriterion!=NULL) { sprintf(output+i, " select %s", pd->SelectCriterion->ascii); i+=strlen(output+i); } // Print select criterion if (pd->ContinuitySet) // Print continuous / discontinuous flag { if (pd->continuity == DATAFILE_DISCONTINUOUS) { sprintf(output+i, " discontinuous"); i+=strlen(output+i); } else { sprintf(output+i, " continuous"); i+=strlen(output+i); } } if (pd->NoTitleSet) { strcpy(output+i, " notitle"); i+=strlen(output+i); } // notitle is set else if (pd->TitleSet ) { strcpy(output+i, " title "); i+=strlen(output+i); ppl_strEscapify(pd->title, output+i); i+=strlen(output+i); } ppl_withWordsPrint(c, &pd->ww, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; i+=strlen(output+i); } else { output[i]='\0'; } sprintf(output+i, " using %s", (pd->UsingRowCols==DATAFILE_COL)?"columns":"rows"); i+=strlen(output+i); // Print using list for (j=0; jNUsing; j++) { output[i++]=(j!=0)?':':' '; strcpy(output+i, pd->UsingList[j]->ascii); i+=strlen(output+i); } pd = pd->next; } } else if (ptr->type == CANVAS_POINT ) // Produce textual representations of point commands { sprintf(output, "point item %d at %s,%s", ptr->id, ppl_numericDisplay( ptr->xpos *100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->ypos *100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i = strlen(output); if (ptr->text != NULL) { sprintf(output+i, " label "); i+=strlen(output+i); ppl_strEscapify(ptr->text, output+i); i+=strlen(output+i); } ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_POLYGON) // Produce textual representations of polygon commands { int p; sprintf(output, "polygon item %d [", ptr->id); i = strlen(output); for (p=0; pNpolygonPoints; p++) { if (p>0) output[i++]=','; sprintf(output+i, "[%s,%s]", ppl_numericDisplay( ptr->polygonPoints[2*p ]*100, c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->polygonPoints[2*p+1]*100, c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); } sprintf(output+i, "]"); i += strlen(output+i); ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else if (ptr->type == CANVAS_TEXT ) // Produce textual representations of text commands { sprintf(output, "text item %d ", ptr->id); i = strlen(output); ppl_strEscapify(ptr->text, output+i); i += strlen(output+i); sprintf(output+i, " at %s,%s rotate %s gap %s", ppl_numericDisplay( ptr->xpos * 100 , c->numdispBuff[0], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->ypos * 100 , c->numdispBuff[1], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->rotation * 180/M_PI, c->numdispBuff[2], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)), ppl_numericDisplay( ptr->xpos2 * 100 , c->numdispBuff[3], c->set->term_current.SignificantFigures, (c->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i += strlen(output+i); ppl_withWordsPrint(c, &ptr->with_data, output+i+6); if (strlen(output+i+6)>0) { sprintf(output+i, " with"); output[i+5]=' '; } else { output[i]='\0'; } } else { sprintf(output, "[unknown object]"); } // Ooops. return output; } // Implementation of the list command int ppl_directive_list(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { canvas_itemlist *canvas_items = c->canvas_items; int i; canvas_item *ptr; ppl_report(&c->errcontext, "# ID Command"); if (canvas_items == NULL) return 0; ptr = canvas_items->first; while (ptr != NULL) { sprintf(c->errcontext.tempErrStr, "%5d %s", ptr->id, (ptr->deleted) ? "[deleted] " : ""); i = strlen(c->errcontext.tempErrStr); ppl_canvas_item_textify(c, ptr, c->errcontext.tempErrStr+i); ppl_report(&c->errcontext, NULL); ptr = ptr->next; } return 0; } // Implementation of the delete command static int canvas_delete(ppl_context *c, const int id) { canvas_itemlist *canvas_items = c->canvas_items; canvas_item *ptr = canvas_items->first; while ((ptr!=NULL)&&(ptr->id!=id)) ptr=ptr->next; if (ptr==NULL) { sprintf(c->errcontext.tempErrStr, "There is no multiplot item with ID %d.", id); ppl_warning(&c->errcontext, ERR_GENERIC, 0); return 1; } else { ptr->deleted = 1; } return 0; } int ppl_directive_delete(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_itemlist *canvas_items = c->canvas_items; int pos; if (canvas_items==NULL) { TBADD(ERR_GENERIC, "There are currently no items on the multiplot canvas.", 0); return 1; } pos = PARSE_delete_deleteno; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { int id; pos = (int)round(stk[pos].real); id = (int)round(stk[pos+PARSE_delete_number_deleteno].real); canvas_delete(c, id); } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); } return 0; } // Implementation of the undelete command int ppl_directive_undelete(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_itemlist *canvas_items = c->canvas_items; int pos; if (canvas_items==NULL) { TBADD(ERR_GENERIC, "There are currently no items on the multiplot canvas.", 0); return 1; } pos = PARSE_undelete_undeleteno; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { canvas_item *ptr; int id; pos = (int)round(stk[pos].real); id = (int)round(stk[pos+PARSE_undelete_number_undeleteno].real); ptr = canvas_items->first; while ((ptr!=NULL)&&(ptr->id!=id)) ptr=ptr->next; if (ptr==NULL) { sprintf(c->errcontext.tempErrStr, "There is no multiplot item with ID %d.", id); ppl_warning(&c->errcontext, ERR_GENERIC, 0); return 1; } else { ptr->deleted = 0; } } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); } return 0; } // Implementation of the move command int ppl_directive_move(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_itemlist *canvas_items = c->canvas_items; int moveno, gotRotation; double x, y, rotation; unsigned char rotatable; canvas_item *ptr; if (canvas_items==NULL) { TBADD(ERR_GENERIC, "There are currently no items on the multiplot canvas.", 0); return 1; } moveno = (int)round(stk[PARSE_move_moveno ].real); x = stk[PARSE_move_p ].real ; y = stk[PARSE_move_p+1 ].real ; rotation = stk[PARSE_move_rotation].real ; gotRotation = (stk[PARSE_move_rotation].objType == PPLOBJ_NUM); ptr = canvas_items->first; while ((ptr!=NULL)&&(ptr->id!=moveno)) ptr=ptr->next; if (ptr==NULL) { sprintf(c->errStat.errBuff, "There is no multiplot item with ID %d.", moveno); TBADD2(ERR_GENERIC, 0); return 1; } rotatable = ((ptr->type!=CANVAS_ARROW)&&(ptr->type!=CANVAS_CIRC)&&(ptr->type!=CANVAS_PIE)&&(ptr->type!=CANVAS_PLOT)&&(ptr->type!=CANVAS_POINT)); if (gotRotation && !rotatable) { sprintf(c->errcontext.tempErrStr, "It is not possible to rotate multiplot item %d.", moveno); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); } if (ptr->type==CANVAS_POLYGON) { int c; if (!gotRotation) { double ox = x - ptr->polygonPoints[0]; double oy = y - ptr->polygonPoints[1]; for (c=0; cNpolygonPoints; c++) { ptr->polygonPoints[2*c ] += ox; ptr->polygonPoints[2*c+1] += oy; } } else { for (c=0; cNpolygonPoints; c++) { double ox = ptr->polygonPoints[2*c ] - ptr->polygonPoints[0]; double oy = ptr->polygonPoints[2*c+1] - ptr->polygonPoints[1]; ox = ox* cos(rotation) + oy*-sin(rotation); oy = ox* sin(rotation) + oy* cos(rotation); ptr->polygonPoints[2*c ] = ox + x; ptr->polygonPoints[2*c+1] = oy + y; } } } else if ((ptr->type!=CANVAS_PLOT)&&(ptr->type!=CANVAS_PIE)) // Most canvas items are moved using the xpos and ypos fields { ptr->xpos = x; ptr->ypos = y; if (gotRotation && rotatable) ptr->rotation = rotation; } else // Plots are moved using the origin fields in settings_graph { ptr->settings.OriginX.real = x; ptr->settings.OriginY.real = y; } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); } return 0; } // Implementation of the swap command int ppl_directive_swap(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_itemlist *canvas_items = c->canvas_items; int item1, item2; canvas_item **ptr1, **ptr2, *temp; if (canvas_items==NULL) { TBADD(ERR_GENERIC, "There are currently no items on the multiplot canvas.", 0); return 1; } // Read the ID numbers of the items to be swapped item1 = (int)round(stk[PARSE_swap_item1].real); item2 = (int)round(stk[PARSE_swap_item2].real); // Seek the first item to be swapped ptr1 = &canvas_items->first; while ((*ptr1!=NULL)&&((*ptr1)->id!=item1)) ptr1=&((*ptr1)->next); if (*ptr1==NULL) { sprintf(c->errStat.errBuff, "There is no multiplot item with ID %d.", item1); TBADD2(ERR_GENERIC, 0); return 1; } // Seek the second item to be swapped ptr2 = &canvas_items->first; while ((*ptr2!=NULL)&&((*ptr2)->id!=item2)) ptr2=&((*ptr2)->next); if (*ptr2==NULL) { sprintf(c->errStat.errBuff, "There is no multiplot item with ID %d.", item2); TBADD2(ERR_GENERIC, 0); return 1; } // Do swap (*ptr1)->id = item2; (*ptr2)->id = item1; temp = *ptr1; *ptr1 = *ptr2; *ptr2 = temp; temp = (*ptr1)->next; (*ptr1)->next = (*ptr2)->next; (*ptr2)->next = temp; // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); } return 0; } // Implementation of the arrow command int ppl_directive_arrow(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, gotTempstr; double x1, x2, y1, y2; char *tempstr, *tempstr2; // Look up the start and end point of the arrow, and ensure that they are either dimensionless or in units of length x1 = stk[PARSE_arrow_p1 ].real; y1 = stk[PARSE_arrow_p1+1].real; x2 = stk[PARSE_arrow_p2 ].real; y2 = stk[PARSE_arrow_p2+1].real; // Add this arrow to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_ARROW,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (B)."); return 1; } ptr->xpos = x1; ptr->ypos = y1; ptr->xpos2 = x2 - x1; ptr->ypos2 = y2 - y1; // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_arrow_, 0, &ptr->with_data); // Work out whether this arrow is in the 'head', 'nohead' or 'twoway' style tempstr = (char *)stk[PARSE_arrow_arrow_style].auxil; gotTempstr = (stk[PARSE_arrow_arrow_style].objType == PPLOBJ_STR); tempstr2 = (char *)stk[PARSE_arrow_directive ].auxil; if (gotTempstr) ptr->ArrowType = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ARROWTYPE_INT, SW_ARROWTYPE_STR); else ptr->ArrowType = (strcmp(tempstr2,"arrow")==0) ? SW_ARROWTYPE_HEAD : SW_ARROWTYPE_NOHEAD; // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Arrow has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the box command int ppl_directive_box(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, gotx2, gotWidth, gotHeight, gotAng; double x1, x2, x3, y1, y2, y3, ang, width, height; // Look up the positions of the two corners of the box x1 = stk[PARSE_box_p1 ].real; y1 = stk[PARSE_box_p1 +1].real; x2 = stk[PARSE_box_p2 ].real; gotx2 = (stk[PARSE_box_p2 ].objType==PPLOBJ_NUM); y2 = stk[PARSE_box_p2 +1].real; x3 = stk[PARSE_box_p3 ].real; y3 = stk[PARSE_box_p3 +1].real; ang = stk[PARSE_box_rotation ].real; gotAng = (stk[PARSE_box_rotation ].objType==PPLOBJ_NUM); width = stk[PARSE_box_width ].real; gotWidth = (stk[PARSE_box_width ].objType==PPLOBJ_NUM); height= stk[PARSE_box_height ].real; gotHeight = (stk[PARSE_box_height ].objType==PPLOBJ_NUM); if ((!gotx2) && ((!gotWidth)||(!gotHeight))) // If box is specified in width/height format, both must be specified { sprintf(c->errStat.errBuff, "When a box is specified with given width and height, both width and height must be specified."); TBADD2(ERR_SYNTAX, 0); return 1; } // Add this box to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_BOX,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (C)."); return 1; } ptr->xpos = gotx2 ? x1 : x3; ptr->ypos = gotx2 ? y1 : y3; if (gotx2) // Box is specified by two corners { ptr->xpos2 = x2 - ptr->xpos; ptr->ypos2 = y2 - ptr->ypos; ptr->xpos2set = 0; // Rotation should be about CENTRE of box } else // Box is specified with width and height { ptr->xpos2 = width; ptr->ypos2 = height; ptr->xpos2set = 1; // Rotation should be about fixed corner of box } if (gotAng) { ptr->rotation = ang; } // Rotation angle is zero if not specified else { ptr->rotation = 0.0; } // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_box_, 0, &ptr->with_data); // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Box has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the circle command int ppl_directive_circle(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, gota1, amArc; double x, y, r, a1, a2; char *tempstr; // Look up the position of the centre of the circle and its radius tempstr = (char *)stk[PARSE_circle_directive ].auxil; amArc = (strcmp(tempstr,"arc")==0); x = stk[PARSE_circle_p ].real; y = stk[PARSE_circle_p+1].real; r = stk[PARSE_circle_r ].real; a1 = stk[PARSE_arc_angle1].real; gota1 = amArc && (stk[PARSE_arc_angle1].objType==PPLOBJ_NUM); a2 = stk[PARSE_arc_angle2].real; // Add this circle to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_CIRC,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (D)."); return 1; } ptr->xpos = x; ptr->ypos = y; ptr->xpos2 = r; if (gota1) { ptr->xfset = 1; ptr->xf = a1; ptr->yf = a2; } // arc command else { ptr->xfset = 0; } // circle command // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, amArc?PARSE_TABLE_arc_:PARSE_TABLE_circle_, 0, &ptr->with_data); // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Circle has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the ellipse command int ppl_directive_ellipse(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int e=0, r=0, p=0, id; int gotAng, gotX1, gotXc, gotXf, gotA2, gotB2, gotA, gotB, gotSlr, gotLr, gotEcc, gotarc; double ang, x1, x2, y1, y2, xc, yc, xf, yf, a2, b2, a, b, slr, lr, ecc, arcfrom, arcto; double ratio; // Look up the input parameters which define the ellipse ang = stk[PARSE_ellipse_rotation ].real; gotAng = (stk[PARSE_ellipse_rotation ].objType==PPLOBJ_NUM); x1 = stk[PARSE_ellipse_p1 ].real; gotX1 = (stk[PARSE_ellipse_p1 ].objType==PPLOBJ_NUM); y1 = stk[PARSE_ellipse_p1+1 ].real; x2 = stk[PARSE_ellipse_p2 ].real; y2 = stk[PARSE_ellipse_p2+1 ].real; xc = stk[PARSE_ellipse_center ].real; gotXc = (stk[PARSE_ellipse_center ].objType==PPLOBJ_NUM); yc = stk[PARSE_ellipse_center+1 ].real; xf = stk[PARSE_ellipse_focus ].real; gotXf = (stk[PARSE_ellipse_focus ].objType==PPLOBJ_NUM); yf = stk[PARSE_ellipse_focus+1 ].real; a2 = stk[PARSE_ellipse_majoraxis ].real; gotA2 = (stk[PARSE_ellipse_majoraxis ].objType==PPLOBJ_NUM); b2 = stk[PARSE_ellipse_minoraxis ].real; gotB2 = (stk[PARSE_ellipse_minoraxis ].objType==PPLOBJ_NUM); a = stk[PARSE_ellipse_semimajoraxis].real; gotA = (stk[PARSE_ellipse_semimajoraxis].objType==PPLOBJ_NUM); b = stk[PARSE_ellipse_semiminoraxis].real; gotB = (stk[PARSE_ellipse_semiminoraxis].objType==PPLOBJ_NUM); slr = stk[PARSE_ellipse_slr ].real; gotSlr = (stk[PARSE_ellipse_slr ].objType==PPLOBJ_NUM); lr = stk[PARSE_ellipse_lr ].real; gotLr = (stk[PARSE_ellipse_lr ].objType==PPLOBJ_NUM); ecc = stk[PARSE_ellipse_eccentricity ].real; gotEcc = (stk[PARSE_ellipse_eccentricity ].objType==PPLOBJ_NUM); arcfrom = stk[PARSE_ellipse_arcfrom ].real; gotarc = (stk[PARSE_ellipse_arcfrom ].objType==PPLOBJ_NUM); arcto = stk[PARSE_ellipse_arcto ].real; // Count number of input parameters that have been supplied, to make sure we have a suitable set if (gotAng) { r++; } else { ang=0.0; } if (gotXc ) { p++; } if (gotXf ) { p++; } if (gotA2 ) { e++; } if (gotB2 ) { e++; } if (gotA ) { e++; } if (gotB ) { e++; } if (gotEcc) { e++; if ((ecc<0.0) || (ecc>=1.0)) { strcpy(c->errStat.errBuff, "Supplied eccentricity is not in the range 0 <= e < 1."); TBADD2(ERR_NUMERICAL,0); return 1; } } if (gotSlr) { e++; } if (gotLr ) { e++; } // Major axis length is a drop-in replacement for the semi-major axis length if (gotA2) { a = a2/2; gotA =1; } if (gotB2) { b = b2/2; gotB =1; } if (gotLr) { slr = lr/2; gotSlr=1; } // Check that we have been supplied an appropriate set of inputs if ( (!gotX1) && (((p==2)&&((e!=1)||(r!=0))) || ((p<2)&&(e!=2))) ) { strcpy(c->errStat.errBuff, "Ellipse command has received an inappropriate set of inputs. Must specify either the position of both the centre and focus of the ellipse, and one further piece of information out of the major axis length, the minor axis length, the eccentricity or the semi-latus rectum, or the position of one of these two points, the rotation angle of the major axis of the ellipse, and two further pieces of information."); TBADD2(ERR_GENERIC,0); return 1; } // Convert inputs such that we have the position of the centre of the ellipse and major/minor axes if (gotX1) // User has specified two corners of the ellipse { xc = (x2 + x1) / 2.0; yc = (y2 + y1) / 2.0; a = fabs(x2 - x1) / 2.0; b = fabs(y2 - y1) / 2.0; } else if (p==2) // User has specified both centre and focus of the ellipse, and one further piece of information { if (ppl_dblEqual(xc, xf) && ppl_dblEqual(yc, yf)) { ang = 0.0; } else { ang = atan2(yc - yf , xc - xf); } xc = xc; yc = yc; if (gotA) // Additional piece of information was major axis... { a = fabs(a); ecc = hypot(xc - xf , yc - yf) / a; if ((ecc < 0.0) || (ecc >= 1.0)) { strcpy(c->errStat.errBuff, "Supplied semi-major axis length is shorter than the distance between the supplied focus and centre of the ellipse. No ellipse may have such parameters."); TBADD2(ERR_NUMERICAL,0); return 1; } if (ppl_dblEqual(ecc,0.0)) { b = a; } else { b = a * sqrt(1.0-pow(ecc,2)); } } else if (gotB) // minor axis... { b = fabs(b); a = hypot(hypot(xc - xf , yc - yf) , b); if (b > a) { strcpy(c->errStat.errBuff, "Supplied minor axis length is longer than the implied major axis length of the ellipse."); TBADD2(ERR_NUMERICAL,0); return 1; } ecc = sqrt(1.0 - pow(b/a , 2.0)); } else if (gotEcc) // eccentricity... { a = hypot(xc - xf , yc - yf) / ecc; if (ppl_dblEqual(ecc,0.0)) { b = a; } else { b = a * sqrt(1.0-pow(ecc,2)); } } else if (gotSlr) // or semi-latus rectum... { ratio = hypot(xc - xf , yc - yf) / slr; ecc = (sqrt(1+4*pow(ratio,2))-1.0) / (2*ratio); if ((ecc<0.0) || (ecc>=1.0)) { strcpy(c->errStat.errBuff, "Eccentricity implied for ellipse is not in the range 0 <= e < 1."); TBADD2(ERR_NUMERICAL,0); return 1; } a = hypot(xc - xf , yc - yf) / ecc; b = a * sqrt(1.0 - pow(ecc,2.0)); } else { strcpy(c->errStat.errBuff, "Flow control error in ellipse command."); TBADD2(ERR_INTERNAL,0); return 1; } } else // User has specified centre / focus of ellipse and two further pieces of information... { if (gotA && gotB) // major and minor axes... { a = fabs(a); b = fabs(b); if (b>a) { strcpy(c->errStat.errBuff, "Supplied minor axis length is longer than the supplied major axis length of the ellipse."); TBADD2(ERR_NUMERICAL,0); TBADD2(ERR_NUMERICAL,0); return 1; } ecc = sqrt(1.0 - pow(b/a , 2.0)); } else if (gotA && gotEcc) // major axis and eccentricity... { a = fabs(a); b = a * sqrt(1.0 - pow(ecc,2.0)); } else if (gotA && gotSlr) // major axis and SLR... { a = fabs(a); if (fabs(slr) > a) { strcpy(c->errStat.errBuff, "Supplied semi-latus rectum is longer than the supplied semi-major axis length of the ellipse. No ellipse may have such parameters."); TBADD2(ERR_NUMERICAL,0); return 1; } ecc = sqrt(1.0 - fabs(slr) / a); b = a * sqrt(1.0 - pow(ecc,2.0)); } else if (gotB && gotEcc) // minor axis and eccentricity... { b = fabs(b); a = b / sqrt(1.0 - pow(ecc,2.0)); } else if (gotB && gotSlr) // minor axis and SLR... { b = fabs(b); if (fabs(slr) > b) { strcpy(c->errStat.errBuff, "Supplied semi-latus rectum is longer than the supplied semi-minor axis length of the ellipse. No ellipse may have such parameters."); TBADD2(ERR_NUMERICAL,0); return 1; } ecc = sqrt(1.0 - pow(fabs(slr) / b,2.0)); a = b / sqrt(1.0 - pow(ecc,2.0)); } else if (gotEcc && gotSlr) // eccentricity and SLR... { a = fabs(slr) / (1.0 - pow(ecc,2.0)); b = a * sqrt(1.0 - pow(ecc,2.0)); } else { strcpy(c->errStat.errBuff, "Flow control error in ellipse command."); TBADD2(ERR_INTERNAL,0); return 1; } if (gotXc) // User has specified the centre of the ellipse { xc = xc; yc = yc; } else if (!gotXf) // User has specified neither the centre nor a focus of the ellipse; use origin as centre { xc = c->set->graph_current.OriginX.real; yc = c->set->graph_current.OriginY.real; } else // User has specified the focus of the ellipse... convert to the centre by translating distance a * eccentricity { xc = xf + a * ecc * cos( ang); yc = yf + a * ecc * sin( ang); } } // Add this ellipse to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_ELLPS,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (E)."); return 1; } ptr->xpos = xc; ptr->ypos = yc; ptr->xpos2 = a ; ptr->ypos2 = b; ptr->rotation = ang; // Add the exact parameterisation which we have been given to canvas item, so that "list" command prints it out in the form originally supplied ptr->x1set = ptr->xcset = ptr->xfset = ptr->aset = ptr->bset = ptr->eccset = ptr->slrset = 0; ptr->x1 = ptr->y1 = ptr->x2 = ptr->y2 = ptr->xc = ptr->yc = ptr->xf = ptr->yf = ptr->ecc = ptr->slr = 0.0; ptr->arcset = 0; if (gotX1 ) { ptr->x1set = 1; ptr->x1 = x1; ptr->y1 = y1; ptr->x2 = x2; ptr->y2 = y2; } else if (gotXc || !gotXf) { ptr->xcset = 1; ptr->xc = xc; ptr->yc = yc; } if (gotXf ) { ptr->xfset = 1; ptr->xf = xf; ptr->yf = yf; } if (gotA ) { ptr-> aset = 1; ptr->a = a ; } if (gotB ) { ptr-> bset = 1; ptr->b = b ; } if (gotEcc) { ptr->eccset= 1; ptr->ecc= ecc; } if (gotSlr) { ptr->slrset= 1; ptr->slr= slr; } if (gotarc) { ptr->arcset= 1; ptr->arcfrom=arcfrom; ptr->arcto=arcto; } // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_ellipse_, 0, &ptr->with_data); // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Ellipse has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the eps command int ppl_directive_eps(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id; double x, y, ang, width, height; int gotX, gotY, gotAng, gotWidth, gotHeight, clip, calcbbox; char *text, *fname; // Read in positional information for this eps image x = stk[PARSE_eps_p ].real; gotX = (stk[PARSE_eps_p ].objType==PPLOBJ_NUM); y = stk[PARSE_eps_p+1 ].real; gotY = (stk[PARSE_eps_p+1 ].objType==PPLOBJ_NUM); ang = stk[PARSE_eps_rotation].real; gotAng = (stk[PARSE_eps_rotation].objType==PPLOBJ_NUM); width = stk[PARSE_eps_width ].real; gotWidth = (stk[PARSE_eps_width ].objType==PPLOBJ_NUM); height = stk[PARSE_eps_height ].real; gotHeight = (stk[PARSE_eps_height ].objType==PPLOBJ_NUM); clip = (stk[PARSE_eps_clip ].objType!=PPLOBJ_ZOM); calcbbox= (stk[PARSE_eps_calcbbox].objType!=PPLOBJ_ZOM); fname = (char *)stk[PARSE_eps_filename].auxil; text = (char *)malloc(strlen(fname)+1); if (text == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (F)."); return 1; } strcpy(text, fname); // Add this eps image to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_EPS,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (G)."); free(text); return 1; } if (gotX ) { ptr->xpos = x ; } else { ptr->xpos = c->set->graph_current.OriginX.real; } if (gotY ) { ptr->ypos = y ; } else { ptr->ypos = c->set->graph_current.OriginY.real; } if (gotAng ) { ptr->rotation = ang ; } else { ptr->rotation = 0.0; } if (gotWidth ) { ptr->xpos2 = width ; ptr->xpos2set = 1; } else { ptr->xpos2 = 0.0; ptr->xpos2set = 0; } if (gotHeight) { ptr->ypos2 = height; ptr->ypos2set = 1; } else { ptr->ypos2 = 0.0; ptr->ypos2set = 0; } ptr->text = text; ptr->clip = clip; ptr->calcbbox = calcbbox; // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "EPS image has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the point command int ppl_directive_point(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id; double x, y; // Look up the position of the point, and ensure that it is either dimensionless or in units of length x = stk[PARSE_point_p ].real; y = stk[PARSE_point_p+1].real; // Add this point to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_POINT,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (H)."); return 1; } ptr->xpos = x; ptr->ypos = y; // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_point_, 0, &ptr->with_data); // See whether this point is labelled if (stk[PARSE_point_label].objType==PPLOBJ_STR) { char *tempstr = (char *)stk[PARSE_point_label].auxil; char *text = (char *)malloc(strlen(tempstr)+1); if (text == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (I)."); return 1; } strcpy(text, tempstr); ptr->text = text; } else { ptr->text = NULL; } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Point has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the polygon command int ppl_directive_polygon(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, Npts, i; double *ptList; list *ptListObj; // Count how many points have been supplied if (stk[PARSE_polygon_pointlist].objType != PPLOBJ_LIST) { sprintf(c->errcontext.tempErrStr, "List of points in polygon should have been a list; supplied object was of type <%s>.", pplObjTypeNames[stk[PARSE_polygon_pointlist].objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return 1; } ptListObj = (list *)stk[PARSE_polygon_pointlist].auxil; Npts = ppl_listLen(ptListObj); ptList = (double *)malloc(2*Npts*sizeof(double)); if (ptList==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (J)."); return 1; } if (Npts<2) { printf(c->errcontext.tempErrStr, "A minimum of two points are required to specify the outline of a polygon."); goto fail; } for (i=0; iobjType == PPLOBJ_VEC) { pplVector *v = (pplVector *)item->auxil; int l = v->v->size; double m=1; if (item->dimensionless) m=0.01; else { int p; for (p=0; pexponent[p] != (p==UNIT_LENGTH)) { p=-1; break; } if (p<0) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a position vector; supplied position had wrong units.", i+1); goto fail; } } if (l!=2) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a two-component position vector; supplied vector had %d components.", i+1, l); goto fail; } x = gsl_vector_get(v->v,0) * m; y = gsl_vector_get(v->v,1) * m; } else if (item->objType == PPLOBJ_LIST) { int j,p; double m=1; list *l = (list *)item->auxil; pplObj *xo[2]; if (ppl_listLen(l)!=2) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a two-component position vector; supplied vector had %d components.", i+1, ppl_listLen(l)); goto fail; } for (j=0; j<2; j++) { xo[j] = (pplObj *)ppl_listGetItem(l,j); if (xo[j]->objType != PPLOBJ_NUM) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a position vector; supplied object had type <%s>.", i+1, pplObjTypeNames[xo[j]->objType]); goto fail; } if (xo[j]->flagComplex) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a position vector; supplied object was complex.", i+1); goto fail; } if (xo[j]->dimensionless) m=0.01; else { for (p=0; pexponent[p] != UNIT_LENGTH) { p=-1; break; } if (p<0) { printf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a position vector; supplied position had wrong units.", i+1); goto fail; } } } x = xo[0]->real * m; y = xo[1]->real * m; } else { sprintf(c->errcontext.tempErrStr, "Point %d of polygon should have specified as a vector or a list; supplied object was of type <%s>.", i+1, pplObjTypeNames[item->objType]); fail: ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); free(ptList); return 1; } ptList[2*i ] = x; ptList[2*i+1] = y; } // Add this polygon to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_POLYGON,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (K)."); return 1; } ptr->NpolygonPoints = Npts; ptr->polygonPoints = ptList; // Read in color and linewidth information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_polygon_, 0, &ptr->with_data); // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Polygon has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the text command int ppl_directive_text(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, gotX, gotY, gotAng, gotGap, gotTempstr; double x, y, ang, gap; char *tempstr, *text; // Look up the position of the text item x = stk[PARSE_text_p ].real; gotX = (stk[PARSE_text_p ].objType==PPLOBJ_NUM); y = stk[PARSE_text_p+1 ].real; gotY = (stk[PARSE_text_p+1 ].objType==PPLOBJ_NUM); gap = stk[PARSE_text_gap ].real; gotGap = (stk[PARSE_text_gap ].objType==PPLOBJ_NUM); ang = stk[PARSE_text_rotation].real; gotAng = (stk[PARSE_text_rotation].objType==PPLOBJ_NUM); // Read the string which we are to render tempstr = (char *)stk[PARSE_text_string].auxil; text = (char *)malloc(strlen(tempstr)+1); if (text == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (L)."); return 1; } strcpy(text, tempstr); if (canvas_itemlist_add(c,stk,CANVAS_TEXT,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (M)."); free(text); return 1; } // Check for halign or valign modifiers tempstr = (char *)stk[PARSE_text_halign].auxil; gotTempstr = (stk[PARSE_text_halign].objType==PPLOBJ_STR); if (gotTempstr) ptr->settings.TextHAlign = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_HALIGN_INT, SW_HALIGN_STR); tempstr = (char *)stk[PARSE_text_valign].auxil; gotTempstr = (stk[PARSE_text_valign].objType==PPLOBJ_STR); if (gotTempstr) ptr->settings.TextVAlign = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_VALIGN_INT, SW_VALIGN_STR); if (gotX ) { ptr->xpos = x ; } else { ptr->xpos = c->set->graph_current.OriginX.real; } if (gotY ) { ptr->ypos = y ; } else { ptr->ypos = c->set->graph_current.OriginY.real; } if (gotGap) { ptr->xpos2 = gap; } else { ptr->xpos2 = 0.0; } if (gotAng) { ptr->rotation = ang; } else { ptr->rotation = 0.0; } ptr->text = text; // Read in color information, if available ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_text_, 0, &ptr->with_data); // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Text item has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the image command int ppl_directive_image(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; canvas_item *ptr; int id, transR=0, transG=0, transB=0, smooth, noTrans, cTrans; double x, y, ang, width, height; int gotX, gotY, gotAng, gotWidth, gotHeight; char *text, *fname; x = stk[PARSE_image_p ].real; gotX = (stk[PARSE_image_p ].objType==PPLOBJ_NUM); y = stk[PARSE_image_p+1 ].real; gotY = (stk[PARSE_image_p+1 ].objType==PPLOBJ_NUM); ang = stk[PARSE_image_rotation].real; gotAng = (stk[PARSE_image_rotation].objType==PPLOBJ_NUM); width = stk[PARSE_image_width ].real; gotWidth = (stk[PARSE_image_width ].objType==PPLOBJ_NUM); height = stk[PARSE_image_height ].real; gotHeight = (stk[PARSE_image_height ].objType==PPLOBJ_NUM); smooth = (stk[PARSE_image_smooth].objType==PPLOBJ_STR); noTrans = (stk[PARSE_image_notrans].objType==PPLOBJ_STR); cTrans = (stk[PARSE_image_colorR].objType==PPLOBJ_NUM); if (cTrans) { transR = (int)floor(stk[PARSE_image_colorR].real*255); transR = ppl_max(ppl_min(transR,255),0); transG = (int)floor(stk[PARSE_image_colorG].real*255); transG = ppl_max(ppl_min(transG,255),0); transB = (int)floor(stk[PARSE_image_colorB].real*255); transB = ppl_max(ppl_min(transB,255),0); } fname = (char *)stk[PARSE_eps_filename].auxil; text = (char *)malloc(strlen(fname)+1); if (text == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (N)."); return 1; } strcpy(text, fname); // Add this eps image to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_IMAGE,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (O)."); free(text); return 1; } if (gotX ) { ptr->xpos = x ; } else { ptr->xpos = c->set->graph_current.OriginX.real; } if (gotY ) { ptr->ypos = y ; } else { ptr->ypos = c->set->graph_current.OriginY.real; } if (gotAng ) { ptr->rotation = ang ; } else { ptr->rotation = 0.0; } if (gotWidth ) { ptr->xpos2 = width ; ptr->xpos2set = 1; } else { ptr->xpos2 = 0.0; ptr->xpos2set = 0; } if (gotHeight) { ptr->ypos2 = height; ptr->ypos2set = 1; } else { ptr->ypos2 = 0.0; ptr->ypos2set = 0; } ptr->text = text; if (smooth ) { ptr->smooth = 1; } else { ptr->smooth = 0; } if (noTrans ) { ptr->NoTransparency = 1; } else { ptr->NoTransparency = 0; } if (cTrans ) { ptr->CustomTransparency = 1; ptr->TransColR = transR; ptr->TransColG = transG; ptr->TransColB = transB; } else { ptr->CustomTransparency = 0; } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Bitmap image has been removed from multiplot, because it generated an error."); return 1; } } return 0; } #define TBADDP ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_NUMERICAL,0,pl->linetxt,"") #define STACK_POPP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(c->errcontext.tempErrStr,"Stack forward reference detected."); ppl_error(&c->errcontext,ERR_STACKED,-1,-1,NULL); free(new); return 1; } \ } #define STACK_CLEANP while (c->stackPtr>stkLevelOld) { STACK_POPP; } static int ppl_getPlotFname(ppl_context *c, char *in, int wildcardMatchNumber, canvas_plotdesc *out) { int i, C; char escaped[FNAME_LENGTH]; wordexp_t wordExp; glob_t globData; out->function=0; out->NFunctions=-1; out->functions=NULL; out->vectors=NULL; if (wildcardMatchNumber<0) wildcardMatchNumber=0; C = wildcardMatchNumber; if ((strcmp(in,"")==0)||(strcmp(in,"-")==0)||(strcmp(in,"--")==0)) // special filenames match once only { if (wildcardMatchNumber>0) return 1; out->filename = (char *)malloc(4); if (out->filename==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (P)."); return 1; } strcpy(out->filename, in); return 0; } { int j,k; for (j=k=0; ((in[j]!='\0')&&(kerrcontext.tempErrStr, "Could not open file '%s'.", escaped); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); return 1; } for (i=0; ierrcontext.tempErrStr, "Could not open file '%s'.", escaped); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); } return 1; } if (C>=globData.gl_pathc) { C-=globData.gl_pathc; globfree(&globData); continue; } out->filename = (char *)malloc(strlen(globData.gl_pathv[C])+1); if (out->filename==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (Q)."); return 1; } strcpy(out->filename, globData.gl_pathv[C]); globfree(&globData); wordfree(&wordExp); return 0; } wordfree(&wordExp); if (wildcardMatchNumber==0) { sprintf(c->errcontext.tempErrStr, "Could not open file '%s'.", escaped); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); } return 1; } static int ppl_getPlotData(ppl_context *c, parserLine *pl, parserOutput *in, canvas_item *ci, const int *ptab, int stkbase, int wildcardMatchNumber, int iterDepth, parserLine **dataSpool, int NExpectIn) { pplObj *stk = in->stk; canvas_plotdesc **plotItemPtr = &ci->plotitems; canvas_plotdesc *new = NULL; while (*plotItemPtr != NULL) plotItemPtr=&(*plotItemPtr)->next; // Find end of list of plot items // Malloc a structure to hold this plot item new=(canvas_plotdesc *)malloc(sizeof(canvas_plotdesc)); if (new == NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (R)."); return 1; } memset((void *)new, 0, sizeof(canvas_plotdesc)); new->filename=NULL; new->PersistentDataTable=NULL; ppl_withWordsZero(c, &new->ww); ppl_withWordsZero(c, &new->ww_final); // Test for expression list or filename { const int pos1 = ptab[PARSE_INDEX_expression_list] + stkbase; const int pos2 = ptab[PARSE_INDEX_filename] + stkbase; if ((pos1>0)&&(stk[pos1].objType==PPLOBJ_NUM)) // we have been passed a list of expressions { const int stkLevelOld = c->stackPtr; int pos = pos1; int Nexprs=0, i; pplExpr **exprList; pplObj *first; while (stk[pos].objType == PPLOBJ_NUM) // count number of expressions { pos = (int)round(stk[pos].real); if (pos<=0) break; Nexprs++; } if (Nexprs < 1) { ppl_error(&c->errcontext, ERR_SYNTAX, -1, -1, "Fewer than one expression was supplied to evaluate."); free(new); return 1; } exprList = (pplExpr **)ppl_memAlloc(Nexprs*sizeof(pplExpr *)); if (exprList==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (S)."); free(new); return 1; } for (i=0, pos=pos1; stk[pos].objType==PPLOBJ_NUM; i++) { pos = (int)round(stk[pos].real); if (pos<=0) break; exprList[i] = (pplExpr *)stk[pos+ptab[PARSE_INDEX_expression]].auxil; } first = ppl_expEval(c, exprList[0], &i, 0, iterDepth); if ((!c->errStat.status) && (first->objType==PPLOBJ_STR) && (Nexprs==1)) // If we have a single expression that evaluates to a string, it's a filename { char *datafile = (char *)first->auxil; int status = ppl_getPlotFname(c, datafile, wildcardMatchNumber, new); STACK_CLEANP; if (status) return 1; } else if ((!c->errStat.status) && (first->objType==PPLOBJ_VEC)) { const int stkLevelOld = c->stackPtr; pplObj *vecs; gsl_vector *v = ((pplVector *)first->auxil)->v; const int l = v->size; int j; vecs = (pplObj *)ppl_memAlloc(Nexprs*sizeof(pplObj)); if (vecs==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (T)."); free(new); return 1; } for (i=0; ierrStat.status) { sprintf(c->errStat.errBuff,"Could not evaluate vector expressions."); TBADDP; ppl_tbWrite(c); ppl_tbClear(c); for (j=0; jobjType!=PPLOBJ_VEC) { sprintf(c->errcontext.tempErrStr,"Vector data supplied to other columns, but columns %d evaluated to an object of type <%s>.", i+1, pplObjTypeNames[obj->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); for (j=0; jauxil)->v->size; if (l!=l2) { sprintf(c->errcontext.tempErrStr,"Data supplied as a list of vectors, but they have varying lengths, including %d (vector %d) and %d (vector %d).", l, 1, l2, i+1); ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, NULL); for (j=0; jfunction = 0; new->NFunctions = Nexprs; new->vectors = (pplObj *)malloc(Nexprs*sizeof(pplObj)); new->functions = (pplExpr **)malloc(Nexprs*sizeof(pplExpr *)); if ( (new->vectors==NULL) || (new->functions==NULL) ) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (U)."); for (i=0; ivectors, vecs, Nexprs*sizeof(pplObj)); for (i=0; ifunctions[i] = pplExpr_cpy(exprList[i]); } else { for (i=0; ifunction = 1; new->NFunctions = Nexprs; new->functions = (pplExpr **)malloc(Nexprs*sizeof(pplExpr *)); new->vectors = NULL; if (new->functions==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (V)."); free(new); return 1; } for (i=0; ifunctions[i] = pplExpr_cpy(exprList[i]); } else { free(new); return 1; } } } else if ((pos2>0)&&(stk[pos2].objType==PPLOBJ_STR)) // we have been passed a filename { char *filename = (char *)stk[pos2].auxil; int status = ppl_getPlotFname(c, filename, wildcardMatchNumber, new); if (status) return 1; } else { sprintf(c->errcontext.tempErrStr, "Could not find any expressions to evaluate."); ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, NULL); free(new); return 1; } } // Read parametric flag new->parametric = ( (ptab[PARSE_INDEX_parametric]>0) && (stk[stkbase+ptab[PARSE_INDEX_parametric]].objType==PPLOBJ_STR) ); // Read T and V ranges new->TRangeSet = ( (ptab[PARSE_INDEX_tmin]>0) && (stk[stkbase+ptab[PARSE_INDEX_tmin]].objType!=PPLOBJ_ZOM) ); new->VRangeSet = ( (ptab[PARSE_INDEX_vmin]>0) && (stk[stkbase+ptab[PARSE_INDEX_vmin]].objType!=PPLOBJ_ZOM) ); if (new->TRangeSet) { new->Tmin = stk[stkbase+ptab[PARSE_INDEX_tmin]]; new->Tmax = stk[stkbase+ptab[PARSE_INDEX_tmax]]; if (!gsl_finite(new->Tmin.real)) { sprintf(c->errcontext.tempErrStr, "Lower limit specified for parameter t is not finite."); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->TRangeSet=0; } else if (!gsl_finite(new->Tmax.real)) { sprintf(c->errcontext.tempErrStr, "Upper limit specified for parameter t is not finite."); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->TRangeSet=0; } else if (!ppl_unitsDimEqual(&new->Tmin, &new->Tmax)) { sprintf(c->errcontext.tempErrStr, "Upper and lower limits specified for parameter t have conflicting physical units of <%s> and <%s>.", ppl_printUnit(c,&new->Tmin,NULL,NULL,0,1,0), ppl_printUnit(c,&new->Tmax,NULL,NULL,1,1,0)); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->TRangeSet=0; } } if (new->VRangeSet) { new->Vmin = stk[stkbase+ptab[PARSE_INDEX_vmin]]; new->Vmax = stk[stkbase+ptab[PARSE_INDEX_vmax]]; if (!gsl_finite(new->Vmin.real)) { sprintf(c->errcontext.tempErrStr, "Lower limit specified for parameter v is not finite."); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->VRangeSet=0; } else if (!gsl_finite(new->Vmax.real)) { sprintf(c->errcontext.tempErrStr, "Upper limit specified for parameter v is not finite."); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->VRangeSet=0; } else if (!ppl_unitsDimEqual(&new->Vmin, &new->Vmax)) { sprintf(c->errcontext.tempErrStr, "Upper and lower limits specified for parameter v have conflicting physical units of <%s> and <%s>.", ppl_printUnit(c,&new->Vmin,NULL,NULL,0,1,0), ppl_printUnit(c,&new->Vmax,NULL,NULL,1,1,0)); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); new->VRangeSet=0; } } // Read axes new->axis1set = new->axis2set = new->axis3set = 0; new->axis1 = new->axis2 = new->axis3 = 1; new->axis1xyz = 0; new->axis2xyz = 1; new->axis3xyz = 2; if (ptab[PARSE_INDEX_axis_1]>0) { int got1 = (stk[stkbase+ptab[PARSE_INDEX_axis_1]].objType==PPLOBJ_NUM); int xyz1 = got1?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_1]].exponent[0])):-1; int n1 = got1?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_1]].real )):-1; int got2 = (stk[stkbase+ptab[PARSE_INDEX_axis_2]].objType==PPLOBJ_NUM); int xyz2 = got2?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_2]].exponent[0])):-1; int n2 = got2?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_2]].real )):-1; int got3 = (stk[stkbase+ptab[PARSE_INDEX_axis_3]].objType==PPLOBJ_NUM); int xyz3 = got3?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_3]].exponent[0])):-1; int n3 = got3?((int)round(stk[stkbase+ptab[PARSE_INDEX_axis_3]].real )):-1; if (got1) { new->axis1set = 1; new->axis1xyz = xyz1; new->axis1 = n1; } if (got2) { new->axis2set = 1; new->axis2xyz = xyz2; new->axis2 = n2; } if (got3) { new->axis3set = 1; new->axis3xyz = xyz3; new->axis3 = n3; } } // Read using fields { int Nusing=0, i=0; int hadNonNullUsingItem = 0; int pos = ptab[PARSE_INDEX_using_list] + stkbase; const int o = ptab[PARSE_INDEX_using_item]; if (o>0) { while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nusing>=USING_ITEMS_MAX) { sprintf(c->errcontext.tempErrStr, "Too many using items; maximum of %d are allowed.", USING_ITEMS_MAX); ppl_error(&c->errcontext,ERR_SYNTAX,-1,-1,NULL); free(new); return 1; } if (stk[pos+o].objType == PPLOBJ_EXP) hadNonNullUsingItem = 1; Nusing++; } if ((!hadNonNullUsingItem) && (Nusing==1)) Nusing=0; // If we've only had one using item, and it was blank, this is a parser abberation new->NUsing = Nusing; if (Nusing<1) { new->UsingList = NULL; } else { new->UsingList = (pplExpr **)malloc((Nusing+8) * sizeof(pplExpr *)); // we may add some more using items later; leave room for eight if (new->UsingList==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (W)."); free(new); return 1; } pos = ptab[PARSE_INDEX_using_list] + stkbase; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (stk[pos+o].objType == PPLOBJ_EXP) new->UsingList[i] = pplExpr_cpy((pplExpr *)stk[pos+o].auxil); else new->UsingList[i] = NULL; i++; } } } } // Read data label new->label = NULL; if (ptab[PARSE_INDEX_label]>0) { pplObj *o = &stk[stkbase+ptab[PARSE_INDEX_label]]; if (o->objType!=PPLOBJ_EXP) { new->label = NULL; } else { new->label = pplExpr_cpy((pplExpr *)o->auxil); } } // Read continuous flag new->ContinuitySet = 0; new->continuity = DATAFILE_CONTINUOUS; if (ptab[PARSE_INDEX_continuous]>0) { if (stk[stkbase+ptab[PARSE_INDEX_continuous ]].objType==PPLOBJ_STR) { new->ContinuitySet = 1; new->continuity = DATAFILE_CONTINUOUS; } if (stk[stkbase+ptab[PARSE_INDEX_discontinuous]].objType==PPLOBJ_STR) { new->ContinuitySet = 1; new->continuity = DATAFILE_DISCONTINUOUS; } } // Read title/notitle setting new->NoTitleSet = new->TitleSet = 0; new->title = NULL; if (ptab[PARSE_INDEX_title]>0) { pplObj *o1 = &stk[stkbase+ptab[PARSE_INDEX_notitle]]; pplObj *o2 = &stk[stkbase+ptab[PARSE_INDEX_title]]; if (o1->objType==PPLOBJ_STR) { new->NoTitleSet = 1; new->TitleSet = 0; new->title = NULL; } else if (o2->objType==PPLOBJ_STR) { new->NoTitleSet = 0; new->title = (char *)malloc(strlen((char *)o2->auxil)+1); new->TitleSet = (new->title!=NULL); if (new->TitleSet) strcpy(new->title, (char *)o2->auxil); } } // Read index field { const int p1 = ptab[PARSE_INDEX_index]; const int p2 = ptab[PARSE_INDEX_use_rows]; const int p3 = ptab[PARSE_INDEX_use_columns]; if ((p1>0)&&(stk[stkbase+p1].objType==PPLOBJ_NUM)) { new->IndexSet=1; new->index=(int)round(stk[stkbase+p1].real); } else { new->IndexSet=0; new->index=-1; } if ((p2>0)&&(stk[stkbase+p2].objType==PPLOBJ_STR)) { new->UsingRowCols = DATAFILE_ROW; } else if ((p3>0)&&(stk[stkbase+p3].objType==PPLOBJ_STR)) { new->UsingRowCols = DATAFILE_COL; } else { new->UsingRowCols = DATAFILE_COL; } } // Read every fields new->EverySet = 0; new->EveryList[0] = new->EveryList[1] = 1; new->EveryList[2] = new->EveryList[3] = new->EveryList[4] = new->EveryList[5] = -1; if (ptab[PARSE_INDEX_every_list]>0) { int Nevery = 0; int pos = ptab[PARSE_INDEX_every_list] + stkbase; const int o = ptab[PARSE_INDEX_every_item]; while (stk[pos].objType == PPLOBJ_NUM) { long x; pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nevery>=6) { ppl_warning(&c->errcontext, ERR_SYNTAX, "More than six numbers supplied to the every modifier -- trailing entries ignored."); break; } x = (long)round(stk[pos+o].real); if (x>new->EveryList[Nevery]) new->EveryList[Nevery]=x; new->EverySet = ++Nevery; } } // Read select criterion { const int p = ptab[PARSE_INDEX_select_criterion]; if ((p>0)&&(stk[stkbase+p].objType==PPLOBJ_EXP)) new->SelectCriterion = pplExpr_cpy((pplExpr *)stk[stkbase+p].auxil); else new->SelectCriterion = NULL; } // Read withWords ppl_withWordsFromDict(c, in, pl, ptab, stkbase, &new->ww); // If reading data from pipe, read and store it now if ((new->filename!=NULL) && ((strcmp(new->filename,"-")==0) || (strcmp(new->filename,"--")==0))) { int status=0, errCount=DATAFILE_NERRS, nObjs=0; pplExpr **UsingList; int NUsing = new->NUsing; unsigned char autoUsingList=0; const int linespoints = new->ww.USElinespoints ? new->ww.linespoints : (ci->settings.dataStyle.USElinespoints ? ci->settings.dataStyle.linespoints : SW_STYLE_POINTS); int NExpect = (NExpectIn>0) ? NExpectIn : eps_plot_styles_NDataColumns(&c->errcontext, linespoints, ci->ThreeDim); char *errbuff = (char *)malloc(LSTR_LENGTH); UsingList = (pplExpr **)malloc( (USING_ITEMS_MAX+8) * sizeof(pplExpr *) ); if ((errbuff==NULL) || (UsingList==NULL)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (X)."); free(new); return 1; } memcpy(UsingList, new->UsingList, NUsing*sizeof(pplExpr *)); new->ww.linespoints = linespoints; // Fix plot style, so that number of expected columns doesn't later change with DataStyle new->ww.USElinespoints = 1; // Color maps can take 3,4,5 or 6 columns of data if (linespoints==SW_STYLE_COLORMAP) { int listlen = NUsing; if ((listlen>=3)&&(listlen<=6)) NExpect=listlen; } if (eps_plot_AddUsingItemsForWithWords(c, &new->ww, &NExpect, &autoUsingList, &UsingList, &NUsing, &nObjs, errbuff)) { free(new); ppl_error(&c->errcontext,ERR_GENERIC, -1, -1, errbuff); free(errbuff); free(UsingList); return 1; } // Add extra using items for, e.g. "linewidth $3". if (NExpect != NUsing) { sprintf(c->errcontext.tempErrStr, "The supplied using ... clause contains the wrong number of items. We need %d columns of data, but %d have been supplied.", NExpect, NUsing); ppl_error(&c->errcontext,ERR_SYNTAX,-1,-1,NULL); free(errbuff); free(UsingList); return 1; } ppldata_fromFile(c, &new->PersistentDataTable, new->filename, 0, NULL, dataSpool, new->index, UsingList, autoUsingList, NExpect, nObjs, new->label, new->SelectCriterion, NULL, new->UsingRowCols, new->EveryList, new->continuity, 1, &status, errbuff, &errCount, iterDepth); free(errbuff); free(UsingList); } // Store plot item *plotItemPtr=new; return 0; } // Implementation of the piechart command int ppl_directive_piechart(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; parserLine *spool=NULL, **dataSpool = &spool; canvas_item *ptr; int id, status; // Add this piechart to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_PIE,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (Y)."); return 1; } // Look up format string if (stk[PARSE_piechart_format_string].objType==PPLOBJ_EXP) ptr->format = pplExpr_cpy((pplExpr *)stk[PARSE_piechart_format_string].auxil); else ptr->format = NULL; // Look up label position if (stk[PARSE_piechart_piekeypos].objType==PPLOBJ_STR) { char *i = (char *)stk[PARSE_piechart_piekeypos].auxil; ptr->ArrowType = ppl_fetchSettingByName(&c->errcontext, i, SW_PIEKEYPOS_INT, SW_PIEKEYPOS_STR); } else { ptr->ArrowType = SW_PIEKEYPOS_AUTO; } // Look up data spool if (stk[PARSE_piechart_data].objType==PPLOBJ_BYT) { spool = (parserLine *)stk[PARSE_piechart_data].auxil; if (spool!=NULL) spool = spool->next; // first line is command line } // Fetch options in common with the plot command status = ppl_getPlotData(c, pl, in, ptr, PARSE_TABLE_piechart_, 0, 0, iterDepth, dataSpool, 1); if (status) { canvas_delete(c, id); return 1; } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Piechart has been removed from multiplot, because it generated an error."); return 1; } } return 0; } // Implementation of the plot command int ppl_directive_plot(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth, int replot) { pplObj *stk = in->stk; canvas_item *ptr = NULL; parserLine *spool = NULL, **dataSpool = &spool; canvas_itemlist *canvas_items = c->canvas_items; int id; // If replotting, find a plot item to append plot items onto if (replot) { int gotEditNo = (stk[PARSE_replot_editno].objType == PPLOBJ_NUM); int editNo = gotEditNo ? ((int)round(stk[PARSE_replot_editno].real)) : c->replotFocus; if (canvas_items!=NULL) { ptr = canvas_items->first; while ((ptr!=NULL)&&(ptr->id!=editNo)) ptr=ptr->next; } if (ptr == NULL) { sprintf(c->errcontext.tempErrStr, "No plot found to replot."); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return 1; } id = editNo; } else { // Add this plot to the linked list which decribes the canvas if (canvas_itemlist_add(c,stk,CANVAS_PLOT,&ptr,&id,0)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (Z)."); return 1; } } c->replotFocus = id; // Copy graph settings and axes to this plot structure. Do this every time that the replot command is called ppl_withWordsDestroy(c,&ptr->settings.dataStyle); // First free the old set of settings which we'd stored ppl_withWordsDestroy(c,&ptr->settings.funcStyle); pplExpr_free(ptr->settings.ColMapExpr); pplExpr_free(ptr->settings.MaskExpr); pplExpr_free(ptr->settings.c1format); if (ptr->XAxes != NULL) { int i; for (i=0; iXAxes[i]) ); free(ptr->XAxes); } if (ptr->YAxes != NULL) { int i; for (i=0; iYAxes[i]) ); free(ptr->YAxes); } if (ptr->ZAxes != NULL) { int i; for (i=0; iZAxes[i]) ); free(ptr->ZAxes); } pplarrow_list_destroy(c, &ptr->arrow_list); ppllabel_list_destroy(c, &ptr->label_list); ptr->settings = c->set->graph_current; ptr->settings.ColMapExpr = pplExpr_cpy(c->set->graph_current.ColMapExpr); ptr->settings.MaskExpr = pplExpr_cpy(c->set->graph_current.MaskExpr); ptr->settings.c1format = pplExpr_cpy(c->set->graph_current.c1format); ppl_withWordsCpy(c, &ptr->settings.dataStyle , &c->set->graph_current.dataStyle); ppl_withWordsCpy(c, &ptr->settings.funcStyle , &c->set->graph_current.funcStyle); ptr->XAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); ptr->YAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); ptr->ZAxes = (pplset_axis *)malloc(MAX_AXES * sizeof(pplset_axis)); if ((ptr->XAxes==NULL)||(ptr->YAxes==NULL)||(ptr->ZAxes==NULL)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1,"Out of memory (0)."); if (ptr->XAxes!=NULL) { free(ptr->XAxes); ptr->XAxes = NULL; } if (ptr->YAxes!=NULL) { free(ptr->YAxes); ptr->YAxes = NULL; } if (ptr->ZAxes!=NULL) { free(ptr->ZAxes); ptr->ZAxes = NULL; } return 1; } else { int i; for (i=0; iXAxes[i]), &(c->set->XAxes[i])); for (i=0; iYAxes[i]), &(c->set->YAxes[i])); for (i=0; iZAxes[i]), &(c->set->ZAxes[i])); } pplarrow_list_copy(c, &ptr->arrow_list , &c->set->pplarrow_list); ppllabel_list_copy(c, &ptr->label_list , &c->set->ppllabel_list); // Check whether 3d or 2d plot if (!replot) { ptr->ThreeDim = (stk[PARSE_replot_threedim].objType==PPLOBJ_STR); // Set 3d flag } // Read data range { int nr = 0; int pos= PARSE_replot_0range_list; const int o1 = PARSE_replot_min_0range_list; const int o2 = PARSE_replot_max_0range_list; const int o3 = PARSE_replot_minauto_0range_list; const int o4 = PARSE_replot_maxauto_0range_list; canvas_plotrange **rangePtr = &ptr->plotranges; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (nr>=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff,"Too many ranges specified; a maximum of %d are allowed.", USING_ITEMS_MAX); TBADD2(ERR_SYNTAX,0); canvas_delete(c, id); return 1; } if (*rangePtr == NULL) { *rangePtr=(canvas_plotrange *)malloc(sizeof(canvas_plotrange)); if (*rangePtr == NULL) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory (1)."); canvas_delete(c, id); return 1; } pplObjNum(&(*rangePtr)->unit,0,0,0); (*rangePtr)->min=(*rangePtr)->max=0.0; (*rangePtr)->MinSet=(*rangePtr)->MaxSet=(*rangePtr)->AutoMinSet=(*rangePtr)->AutoMaxSet=0; (*rangePtr)->next=NULL; } { pplObj *min = &stk[pos+o1]; int gotMin = (min->objType==PPLOBJ_NUM)||(min->objType==PPLOBJ_DATE)||(min->objType==PPLOBJ_BOOL); pplObj *max = &stk[pos+o2]; int gotMax = (max->objType==PPLOBJ_NUM)||(max->objType==PPLOBJ_DATE)||(max->objType==PPLOBJ_BOOL); int minAuto = (stk[pos+o3].objType==PPLOBJ_STR); int maxAuto = (stk[pos+o4].objType==PPLOBJ_STR); if ( gotMin && gotMax && (min->objType != max->objType) ) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[min->objType], pplObjTypeNames[max->objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if ( gotMin && gotMax && !ppl_unitsDimEqual(min, max) ) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting units of <%s> and <%s>.", nr+1, ppl_printUnit(c,min,NULL,NULL,0,0,0), ppl_printUnit(c,max,NULL,NULL,0,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if ( gotMin && (!gotMax) && (!maxAuto) && ((*rangePtr)->MaxSet) && (min->objType != (*rangePtr)->unit.objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[min->objType], pplObjTypeNames[(*rangePtr)->unit.objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if ( gotMin && (!gotMax) && (!maxAuto) && ((*rangePtr)->MaxSet) && (!ppl_unitsDimEqual(min,&(*rangePtr)->unit))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting units of <%s> and <%s>.", nr+1, ppl_printUnit(c,min,NULL,NULL,0,0,0), ppl_printUnit(c,&(*rangePtr)->unit,NULL,NULL,0,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if ( gotMax && (!gotMin) && (!minAuto) && ((*rangePtr)->MinSet) && (max->objType != (*rangePtr)->unit.objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[(*rangePtr)->unit.objType], pplObjTypeNames[max->objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if ( gotMax && (!gotMin) && (!minAuto) && ((*rangePtr)->MinSet) && (!ppl_unitsDimEqual(max,&(*rangePtr)->unit))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified in range %d have conflicting units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&(*rangePtr)->unit,NULL,NULL,0,0,0), ppl_printUnit(c,max,NULL,NULL,0,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_replot_min_0range_list]); canvas_delete(c, id); return 1; } if (minAuto) { (*rangePtr)->AutoMinSet=1; (*rangePtr)->MinSet=0; (*rangePtr)->min=0.0; } if (maxAuto) { (*rangePtr)->AutoMaxSet=1; (*rangePtr)->MaxSet=0; (*rangePtr)->max=0.0; } if (gotMin ) { (*rangePtr)->AutoMinSet=0; (*rangePtr)->MinSet=1; (*rangePtr)->min=min->real; (*rangePtr)->unit=*min; (*rangePtr)->unit.real=1.0; } if (gotMax ) { (*rangePtr)->AutoMaxSet=0; (*rangePtr)->MaxSet=1; (*rangePtr)->max=max->real; (*rangePtr)->unit=*max; (*rangePtr)->unit.real=1.0; } } rangePtr = &(*rangePtr)->next; nr++; } } // Look up data spool if (stk[PARSE_replot_data].objType==PPLOBJ_BYT) { spool = (parserLine *)stk[PARSE_replot_data].auxil; if (spool!=NULL) spool=spool->next; // first line is command line } // Read list of plotted items { int pos = PARSE_replot_0plot_list; while (stk[pos].objType == PPLOBJ_NUM) { int w; pos = (int)round(stk[pos].real); if (pos<=0) break; // Check that axes are correctly specified { int got1 = (stk[pos+PARSE_replot_axis_1_0plot_list].objType==PPLOBJ_NUM); int xyz1 = got1?((int)round(stk[pos+PARSE_replot_axis_1_0plot_list].exponent[0])):-1; //int n1 = got1?((int)round(stk[pos+PARSE_replot_axis_1_0plot_list].real )):-1; int got2 = (stk[pos+PARSE_replot_axis_2_0plot_list].objType==PPLOBJ_NUM); int xyz2 = got2?((int)round(stk[pos+PARSE_replot_axis_2_0plot_list].exponent[0])):-1; //int n2 = got2?((int)round(stk[pos+PARSE_replot_axis_2_0plot_list].real )):-1; int got3 = (stk[pos+PARSE_replot_axis_3_0plot_list].objType==PPLOBJ_NUM); int xyz3 = got3?((int)round(stk[pos+PARSE_replot_axis_3_0plot_list].exponent[0])):-1; //int n3 = got3?((int)round(stk[pos+PARSE_replot_axis_3_0plot_list].real )):-1; if (got1 || got2 || got3) { c->errcontext.tempErrStr[0]='\0'; if ((!ptr->ThreeDim) && (!(got1 && got2 && !got3))) sprintf(c->errcontext.tempErrStr, "The axes clause in the plot command must contain two perpendicular axes to produce a two-dimensional plot."); else if (ptr->ThreeDim && (!(got1 && got2 && got3))) sprintf(c->errcontext.tempErrStr, "The axes clause in the plot command must contain three perpendicular axes to produce a three-dimensional plot."); else if ( ((!ptr->ThreeDim) && ( ((xyz1!=0)&&(xyz2!=0)) || ((xyz1!=1)&&(xyz2!=1)) )) || (( ptr->ThreeDim) && ( (xyz1==xyz2) || (xyz2==xyz3) )) ) sprintf(c->errcontext.tempErrStr, "The axes clause in the plot command may not list multiple parallel axes."); if (c->errcontext.tempErrStr[0]!='\0') { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, NULL); canvas_delete(c, id); return 1; } } } // Loop over wildcard matches for (w=0 ; ; w++) { int status = ppl_getPlotData(c, pl, in, ptr, PARSE_TABLE_replot_, pos, w, iterDepth, dataSpool, -1); if (status) { if (w==0) { canvas_delete(c, id); return 1; } else { break; } } } } } // Redisplay the canvas as required if ((c->set->term_current.display == SW_ONOFF_ON)&&(!cancellationFlag)) { unsigned char *unsuccessful_ops = (unsigned char *)ppl_memAlloc(MULTIPLOT_MAXINDEX); ppl_canvas_draw(c, unsuccessful_ops, iterDepth); if (unsuccessful_ops[id]) { canvas_delete(c, id); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Plot has been removed from multiplot, because it generated an error."); return 1; } } return 0; } pyxplot-0.9.2/src/datafile_rasters.h0000664000175000017500000000220112026340554016073 0ustar dcf21dcf21// datafile_rasters.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: datafile_rasters.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _DATAFILE_RASTERS_H #define _DATAFILE_RASTERS_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppldata_fromFuncs_checkSpecialRaster(ppl_context *C, pplExpr **fnlist, int fnlist_len, char *dummyVar, double *min, double *max, pplObj *unit, double **raster, int *rasterLen); #endif pyxplot-0.9.2/src/defaultObjs/0000775000175000017500000000000012026340554014655 5ustar dcf21dcf21pyxplot-0.9.2/src/defaultObjs/defaultUnits.h0000664000175000017500000000166312026340554017503 0ustar dcf21dcf21// defaultUnits.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultUnits.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _DEFAULTUNITS_H #define _DEFAULTUNITS_H 1 #include "userspace/context.h" void ppl_makeDefaultUnits(ppl_context *context); #endif pyxplot-0.9.2/src/defaultObjs/zetaRiemann.c0000664000175000017500000001341512026340554017302 0ustar dcf21dcf21// zetaRiemann.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Matthew Smith // // $Id: zetaRiemann.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains an implementation of the Riemann Zeta Function for // general complex inputs provided courtesy of Matthew Smith. #define DECIMAL_PLACES 18 #include #include #include #include #include #include #include #include #include #include "defaultObjs/zetaRiemann.h" void riemann_zeta_complex__(double x, double y, gsl_complex *output, int *status, char *errText) { gsl_complex a,am,b,c,d,e; double g,h; int j,n,m,sign; a = gsl_complex_rect(x,y); /* the argument to zeta */ b = gsl_complex_sub_real(a,1); g = gsl_complex_abs(b); if (g<0.01) { e = gsl_complex_inverse(b); /* build up the Laurent sum as we are near the pole */ e = gsl_complex_add_real(e,0.57721566490153286061); d = gsl_complex_mul_real(b,-0.07281584548367672486); e = gsl_complex_sub(e,d); c = gsl_complex_mul(b,b); d = gsl_complex_mul_real(c,-0.00484518159643615924); e = gsl_complex_add(e,d); c = gsl_complex_mul(c,b); d = gsl_complex_mul_real(c,0.00034230573671722431); e = gsl_complex_sub(e,d); c = gsl_complex_mul(c,b); d = gsl_complex_mul_real(c,0.00009689041939447083); e = gsl_complex_add(e,d); c = gsl_complex_mul(c,b); d = gsl_complex_mul_real(c,0.00000661103181084219); e = gsl_complex_sub(e,d); c = gsl_complex_mul(c,b); d = gsl_complex_mul_real(c,-0.00000033162409087528); e = gsl_complex_add(e,d); *output = e; return; } // Use Peter Borwein's method. // This is Algorithm 3 from his 2000 Canadian Math. Soc. Proc. paper. n = (int) (2.1+1.2*DECIMAL_PLACES+0.76*abs(y)+0.25*log(1+(y*y/(x*x)))); m = n; am = gsl_complex_negative(a); e = GSL_COMPLEX_ZERO; sign = 1; g = 1.0; h = 0.0; for (j=0;j<=(n-1);j++) { sign = -sign; d = gsl_complex_pow(gsl_complex_rect(((double) (2*n-j)),0.0),am); h += g; d = gsl_complex_mul_real(d,h); if (sign==1) e = gsl_complex_add(e,d); else e = gsl_complex_sub(e,d); g *= (double) (n-j); g /= (double) (j+1); while ((h>0.5) && (m>0)) { g /= 2.0; h /= 2.0; e = gsl_complex_div_real(e,2.0); m--; } } e = gsl_complex_add_real(e,1.0); sign = 1; for(j=1;j<=(n-1);j++) { sign = -sign; d = gsl_complex_pow(gsl_complex_rect(((double) (j+1)),0.0),am); if (sign==1) e = gsl_complex_add(e,d); else e = gsl_complex_sub(e,d); } d=gsl_complex_pow(gsl_complex_rect(2.0,0.0),gsl_complex_negative(b)); d=gsl_complex_add_real(gsl_complex_negative(d),1.0); e=gsl_complex_div(e,d); *output = e; return; } void riemann_zeta_complex(gsl_complex in, gsl_complex *output, int *status, char *errText) { double x,y; gsl_complex b,c; gsl_sf_result dr,dt; x = GSL_REAL(in); y = GSL_IMAG(in); if ((x==1.0) && (y==0.0)) { *status = 1; /* pole at z=1 */ strcpy(errText, "The Riemann zeta function has a pole at z=1 and cannot be evaluated here."); return; } else if ((x==0.0) && (y==0.0)) { *status = 0; *output = gsl_complex_rect(-0.5,0.0); return; } else if (abs(y)>1000000.0) { *status = 1; /* would take too long to evaluate */ strcpy(errText, "The Riemann zeta function takes a long time to evaluate for inputs with large complex components; operation cancelled."); return; } else if (x<-300.0) { *status = 1; /* risk of overflow */ strcpy(errText, "The Riemann zeta function cannot be evaluated for inputs with real parts below -300 due to numerical overflows."); return; } else if ((y==0.0) && ((x/2)==((double) ((int) (x/2))))) { *status = 0; *output = GSL_COMPLEX_ZERO; return; } else if (x>=0.5) { *status=0; riemann_zeta_complex__(x,y,output,status,errText); return; } else { b = gsl_complex_mul_real(in,M_LN2); c = gsl_complex_mul_real(gsl_complex_sub_real(in,1.0),log(M_PI)); b = gsl_complex_add(b,c); if (abs(y)<41) { c = gsl_complex_sin(gsl_complex_mul_real(in,M_PI_2)); if ((GSL_REAL(c)==0) && (GSL_IMAG(c)==0)) { *status = 0; *output = GSL_COMPLEX_ZERO; return; } c = gsl_complex_log(c); } else { if (y>0) c = gsl_complex_rect(y*M_PI_2-M_LN2,-x*M_PI_2-M_PI_2); else c = gsl_complex_rect(-y*M_PI_2-M_LN2,x*M_PI_2-M_PI_2); } b = gsl_complex_add(b,c); gsl_sf_lngamma_complex_e((1-x),(-y),&dr,&dt); c = gsl_complex_rect(dr.val,dt.val); b = gsl_complex_add(b,c); if(GSL_REAL(b)>660) { *status=1; /* risk of overflow */ sprintf(errText, "The Riemann zeta function could not be evaluated due to a numerical overflow."); return; } b = gsl_complex_exp(b); riemann_zeta_complex__(1.0-x,-y,&c,status,errText); b = gsl_complex_mul(b,c); *status = 0; *output = b; return; } } pyxplot-0.9.2/src/defaultObjs/moduleRandom.c0000664000175000017500000001005612026340554017451 0ustar dcf21dcf21// moduleRandom.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleRandom.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleRandom.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" static gsl_rng *rndgen = NULL; // Random number generator void pplfunc_setRandomSeed(long i) { if (rndgen==NULL) rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, i); return; } void pplfunc_frandom (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } OUTPUT.real = gsl_rng_uniform(rndgen); } void pplfunc_frandombin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "binomial(p,n)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } CHECK_NEEDINT(in[1], "n", "function's second argument must be an integer in the range"); OUTPUT.real = gsl_ran_binomial(rndgen, in[0].real, (unsigned int)in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_frandomcs (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "chisq(nu)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } OUTPUT.real = gsl_ran_chisq(rndgen, in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_frandomg (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gaussian(sigma)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } OUTPUT.real = gsl_ran_gaussian(rndgen, in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_frandomln (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lognormal(zeta,sigma)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } in++; CHECK_1INPUT_DIMLESS; // THIS IS CORRECT. Only check in[1] in--; OUTPUT.real = gsl_ran_lognormal(rndgen, in[0].real, in[1].real); CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, &in[0]); } void pplfunc_frandomp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "poisson(n)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } OUTPUT.real = gsl_ran_poisson(rndgen, in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_frandomt (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "tdist(nu)"; if (rndgen==NULL) { rndgen = gsl_rng_alloc(gsl_rng_default); gsl_rng_set(rndgen, 0); } OUTPUT.real = gsl_ran_tdist(rndgen, in[0].real); CHECK_OUTPUT_OKAY; } pyxplot-0.9.2/src/defaultObjs/moduleColor.c0000664000175000017500000003172012026340554017310 0ustar dcf21dcf21// moduleColor.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleColor.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Parts of this source file are modified from public domain code by John // Walker, including corrections by Andrew J. S. Hamilton. // See // Source code at // Referenced from // John Walker's homepage is at #include #include #include #include #include #include #include #include "expressions/expCompile.h" #include "expressions/expEval.h" #include "expressions/fnCall.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleColor.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" #define GAMMA_FUDGE 0.45 struct colorSystem { char *name; // Colour system name double xRed, yRed, // Red x, y xGreen, yGreen, // Green x, y xBlue, yBlue, // Blue x, y xWhite, yWhite, // White point x, y gamma; // Gamma correction for system }; // White point chromaticities #define IlluminantC 0.3101, 0.3162 // For NTSC television #define IlluminantD65 0.3127, 0.3291 // For EBU and SMPTE #define IlluminantE 0.33333333, 0.33333333 // CIE equal-energy illuminant #define GAMMA_REC709 0 // Rec. 709 static struct colorSystem // Name xRed yRed xGreen yGreen xBlue yBlue White point Gamma // NTSCsystem = { "NTSC", 0.67, 0.33, 0.21, 0.71, 0.14, 0.08, IlluminantC, GAMMA_REC709 }, // EBUsystem = { "EBU (PAL/SECAM)", 0.64, 0.33, 0.29, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }, SMPTEsystem = { "SMPTE", 0.630, 0.340, 0.310, 0.595, 0.155, 0.070, IlluminantD65, GAMMA_REC709 }; // HDTVsystem = { "HDTV", 0.670, 0.330, 0.210, 0.710, 0.150, 0.060, IlluminantD65, GAMMA_REC709 }, // CIEsystem = { "CIE", 0.7355, 0.2645, 0.2658, 0.7243, 0.1669, 0.0085, IlluminantE, GAMMA_REC709 }, // Rec709system = { "CIE REC 709", 0.64, 0.33, 0.30, 0.60, 0.15, 0.06, IlluminantD65, GAMMA_REC709 }; #define CIE_WLEN_MIN 380 #define CIE_WLEN_STEPSIZE 5 #define N_CIE_STEPS 81 static double cie_color_match[N_CIE_STEPS][3] = { {0.0014,0.0000,0.0065}, {0.0022,0.0001,0.0105}, {0.0042,0.0001,0.0201}, {0.0076,0.0002,0.0362}, {0.0143,0.0004,0.0679}, {0.0232,0.0006,0.1102}, {0.0435,0.0012,0.2074}, {0.0776,0.0022,0.3713}, {0.1344,0.0040,0.6456}, {0.2148,0.0073,1.0391}, {0.2839,0.0116,1.3856}, {0.3285,0.0168,1.6230}, {0.3483,0.0230,1.7471}, {0.3481,0.0298,1.7826}, {0.3362,0.0380,1.7721}, {0.3187,0.0480,1.7441}, {0.2908,0.0600,1.6692}, {0.2511,0.0739,1.5281}, {0.1954,0.0910,1.2876}, {0.1421,0.1126,1.0419}, {0.0956,0.1390,0.8130}, {0.0580,0.1693,0.6162}, {0.0320,0.2080,0.4652}, {0.0147,0.2586,0.3533}, {0.0049,0.3230,0.2720}, {0.0024,0.4073,0.2123}, {0.0093,0.5030,0.1582}, {0.0291,0.6082,0.1117}, {0.0633,0.7100,0.0782}, {0.1096,0.7932,0.0573}, {0.1655,0.8620,0.0422}, {0.2257,0.9149,0.0298}, {0.2904,0.9540,0.0203}, {0.3597,0.9803,0.0134}, {0.4334,0.9950,0.0087}, {0.5121,1.0000,0.0057}, {0.5945,0.9950,0.0039}, {0.6784,0.9786,0.0027}, {0.7621,0.9520,0.0021}, {0.8425,0.9154,0.0018}, {0.9163,0.8700,0.0017}, {0.9786,0.8163,0.0014}, {1.0263,0.7570,0.0011}, {1.0567,0.6949,0.0010}, {1.0622,0.6310,0.0008}, {1.0456,0.5668,0.0006}, {1.0026,0.5030,0.0003}, {0.9384,0.4412,0.0002}, {0.8544,0.3810,0.0002}, {0.7514,0.3210,0.0001}, {0.6424,0.2650,0.0000}, {0.5419,0.2170,0.0000}, {0.4479,0.1750,0.0000}, {0.3608,0.1382,0.0000}, {0.2835,0.1070,0.0000}, {0.2187,0.0816,0.0000}, {0.1649,0.0610,0.0000}, {0.1212,0.0446,0.0000}, {0.0874,0.0320,0.0000}, {0.0636,0.0232,0.0000}, {0.0468,0.0170,0.0000}, {0.0329,0.0119,0.0000}, {0.0227,0.0082,0.0000}, {0.0158,0.0057,0.0000}, {0.0114,0.0041,0.0000}, {0.0081,0.0029,0.0000}, {0.0058,0.0021,0.0000}, {0.0041,0.0015,0.0000}, {0.0029,0.0010,0.0000}, {0.0020,0.0007,0.0000}, {0.0014,0.0005,0.0000}, {0.0010,0.0004,0.0000}, {0.0007,0.0002,0.0000}, {0.0005,0.0002,0.0000}, {0.0003,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0002,0.0001,0.0000}, {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0001,0.0000,0.0000}, {0.0000,0.0000,0.0000} }; static void xyz_to_rgb(struct colorSystem *cs, double xc, double yc, double zc, double *r, double *g, double *b) { double xr, yr, zr, xg, yg, zg, xb, yb, zb; double xw, yw, zw; double rx, ry, rz, gx, gy, gz, bx, by, bz; double rw, gw, bw; xr = cs->xRed; yr = cs->yRed; zr = 1 - (xr + yr); xg = cs->xGreen; yg = cs->yGreen; zg = 1 - (xg + yg); xb = cs->xBlue; yb = cs->yBlue; zb = 1 - (xb + yb); xw = cs->xWhite; yw = cs->yWhite; zw = 1 - (xw + yw); // xyz -> rgb matrix, before scaling to white rx = (yg * zb) - (yb * zg); ry = (xb * zg) - (xg * zb); rz = (xg * yb) - (xb * yg); gx = (yb * zr) - (yr * zb); gy = (xr * zb) - (xb * zr); gz = (xb * yr) - (xr * yb); bx = (yr * zg) - (yg * zr); by = (xg * zr) - (xr * zg); bz = (xr * yg) - (xg * yr); // White scaling factors. Dividing by yw scales the white luminance to unity, as conventional. rw = ((rx * xw) + (ry * yw) + (rz * zw)) / yw; gw = ((gx * xw) + (gy * yw) + (gz * zw)) / yw; bw = ((bx * xw) + (by * yw) + (bz * zw)) / yw; // xyz -> rgb matrix, correctly scaled to white rx = rx / rw; ry = ry / rw; rz = rz / rw; gx = gx / gw; gy = gy / gw; gz = gz / gw; bx = bx / bw; by = by / bw; bz = bz / bw; // rgb of the desired point *r = (rx * xc) + (ry * yc) + (rz * zc); *g = (gx * xc) + (gy * yc) + (gz * zc); *b = (bx * xc) + (by * yc) + (bz * zc); return; } static int inside_gamut(double r, double g, double b) { return (r >= 0) && (g >= 0) && (b >= 0); } static int constrain_rgb(double *r, double *g, double *b) { double w; // Amount of white needed is w = - min(0, *r, *g, *b) w = (0 < *r) ? 0 : *r; w = (w < *g) ? w : *g; w = (w < *b) ? w : *b; w = -w; // Add just enough white to make r, g, b all positive if (w>0) { double n = (*r+*g+*b) / (*r+*g+*b+w); if (!gsl_finite(n)) n=1; *r=(*r+w)*n; *g=(*g+w)*n; *b=(*b+w)*n; return 1; // Colour modified to fit RGB gamut } return 0; // Colour within RGB gamut } void pplfunc_colWavelen (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "wavelength(lambda,norm)"; double p0,wi,wj,x,y,z,r,g,b,norm; int i,j; CHECK_DIMLESS_OR_HAS_UNIT(in[0], "first", "a wavelength", UNIT_LENGTH, 1); if (!in[1].dimensionless) { *status=1; *errType=ERR_UNIT; sprintf(errText, "The %s function requires a dimensionless renormalisation constant as its second argument. Supplied value has dimensions of <%s>.", FunctionDescription, ppl_printUnit(c, &in[1], NULL, NULL, 0, 1, 0)); return; } pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,0,0,0,0); norm = in[1].real; p0 = ((in[0].real * 1e9) - CIE_WLEN_MIN) / CIE_WLEN_STEPSIZE; if ((!gsl_finite(p0))||(p0<0)||(p0>=N_CIE_STEPS-1)) { pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,0,0,0,0); return; } // Black i = (int)floor(p0); if (i<0) i=0; if (i>N_CIE_STEPS-2) i=N_CIE_STEPS-2; j = i+1; wi = (j-p0); if (wi<0) wi=0; if (wi>1) wi=1; wj = 1-wi; x = cie_color_match[i][0]*wi + cie_color_match[j][0]*wj; y = cie_color_match[i][1]*wi + cie_color_match[j][1]*wj; z = cie_color_match[i][2]*wi + cie_color_match[j][2]*wj; // Fudge to brightness of spectrum { double xyz = gsl_hypot3(x,y,z); if (xyz>1) xyz=1; if (xyz<0) xyz=0; double XYZ = pow(xyz, GAMMA_FUDGE); double gamma = XYZ / xyz; x *= gamma; y *= gamma; z *= gamma; } xyz_to_rgb(&SMPTEsystem, x, y, z, &r, &g, &b); if (!inside_gamut(r,g,b)) constrain_rgb(&r,&g,&b); r*=fabs(norm); if (r<0) r=0; if (r>1) r=1; g*=fabs(norm); if (g<0) g=0; if (g>1) g=1; b*=fabs(norm); if (b<0) b=0; if (b>1) b=1; pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,r,g,b,0); return; } #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { *status=1; *errType=ERR_INTERNAL; strcpy(errText,"Stack forward reference detected."); return; } \ } void pplfunc_colSpectrum(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "spectrum(spec,norm)"; pplFunc *fi; const int stkLevelOld = c->stackPtr; double x=0,y=0,z=0,r,g,b,norm; int i; if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (!in[1].dimensionless) { *status=1; *errType=ERR_UNIT; sprintf(errText, "The %s function requires a dimensionless renormalisation constant as its second argument. Supplied value has dimensions of <%s>.", FunctionDescription, ppl_printUnit(c, &in[1], NULL, NULL, 0, 1, 0)); return; } pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,0,0,0,0); norm = in[1].real; // Check there's enough space on the stack STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_MEMORY; sprintf(errText, "stack overflow in the colors.spectrum function."); return; } for (i=0; istack[c->stackPtr], &in[0], 1, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push wavelength pplObjNum(&c->stack[c->stackPtr], 0 , wlen, 0); c->stack[c->stackPtr].dimensionless=0; c->stack[c->stackPtr].exponent[UNIT_LENGTH]=1; c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside spectrum function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } // Return error if function didn't return a number if (c->stack[c->stackPtr-1].objType!=PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a spectrum function that returns a number. Supplied function returned an object of type <%s>.", FunctionDescription, pplObjTypeNames[c->stack[c->stackPtr-1].objType]); return; } // Get number back and clean stack w = fabs(c->stack[c->stackPtr-1].real) / N_CIE_STEPS; if (!gsl_finite(w)) w=0; while (c->stackPtr>stkLevelOld) { STACK_POP; } // Add color to accumulators x += cie_color_match[i][0]*w; y += cie_color_match[i][1]*w; z += cie_color_match[i][2]*w; } // Fudge to brightness of spectrum { double xyz = gsl_hypot3(x,y,z); if (xyz>1) xyz=1; if (xyz<0) xyz=0; double XYZ = pow(xyz, GAMMA_FUDGE); double gamma = XYZ / xyz; x *= gamma; y *= gamma; z *= gamma; } xyz_to_rgb(&SMPTEsystem, x, y, z, &r, &g, &b); if (!inside_gamut(r,g,b)) constrain_rgb(&r,&g,&b); r*=fabs(norm); if (r<0) r=0; if (r>1) r=1; g*=fabs(norm); if (g<0) g=0; if (g>1) g=1; b*=fabs(norm); if (b<0) b=0; if (b>1) b=1; pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,r,g,b,0); return; } pyxplot-0.9.2/src/defaultObjs/moduleOs.c0000664000175000017500000003663512026340554016625 0ustar dcf21dcf21// moduleOs.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleOs.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/getPasswd.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "defaultObjs/moduleOs.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" #define COPYSTR(X,Y) \ { \ X = (char *)malloc(strlen(Y)+1); \ if (X==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } \ strcpy(X, Y); \ } void pplfunc_osChdir (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.chdir() function requires a single string argument."); return; } if (chdir((char*)in[0].auxil)!=0) { *status=1; *errType=ERR_FILE; sprintf(errText,"The os.chdir() encountered an error: %s",strerror(errno)); return; } strncpy(c->errcontext.session_default.cwd , (char*)in[0].auxil , FNAME_LENGTH); c->errcontext.session_default.cwd[FNAME_LENGTH-1]='\0'; } void pplfunc_osGetCwd (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *tmp; COPYSTR(tmp, c->errcontext.session_default.cwd); pplObjStr(&OUTPUT,0,1,tmp); } void pplfunc_osGetEgid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getegid(),0); } void pplfunc_osGetEuid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,geteuid(),0); } void pplfunc_osGetGid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getgid(),0); } void pplfunc_osGetPid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getpid(),0); } void pplfunc_osGetPgrp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getpgrp(),0); } void pplfunc_osGetPpid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getppid(),0); } void pplfunc_osGetUid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjNum(&OUTPUT,0,getuid(),0); } void pplfunc_osGetHome(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *out,*tmp; tmp = ppl_unixGetHomeDir(&c->errcontext); out = (char *)malloc(strlen(tmp)+1); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } strcpy(out, tmp); pplObjStr(&OUTPUT,0,1,out); return; } void pplfunc_osGetHost(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { const int outlen=FNAME_LENGTH; char *out; out = (char *)malloc(outlen); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } gethostname(out,outlen); out[outlen-1]='\0'; pplObjStr(&OUTPUT,0,1,out); return; } void pplfunc_osGetLogin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *out,*tmp; tmp = getlogin(); out = (char *)malloc(strlen(tmp)+1); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } strcpy(out, tmp); pplObjStr(&OUTPUT,0,1,out); return; } void pplfunc_osGetRealName(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *out,*tmp; tmp = ppl_unixGetIRLName(&c->errcontext); out = (char *)malloc(strlen(tmp)+1); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } strcpy(out, tmp); pplObjStr(&OUTPUT,0,1,out); return; } void pplfunc_osGlob(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { wordexp_t w; glob_t g; pplObj v; list *l; char *tmp; char escaped[FNAME_LENGTH], *raw=(char*)in[0].auxil; int i,j; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.glob() function requires a single string argument."); return; } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; { int j,k; for (j=k=0; ((raw[j]!='\0')&&(k1)&&(in[1].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The open() function requires string arguments."); return; } if (nArgs>1) mode=(char*)in[1].auxil; else mode="r"; f = popen((char*)in[0].auxil,mode); if (f==NULL) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } pplObjFile(&OUTPUT,0,1,f,1); } void pplfunc_osStat(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *tmp, permissions[]="---------"; dict *d; pplObj v; struct stat s; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.stat() function requires a single string argument."); return; } if (stat((char*)in[0].auxil,&s)!=0) { pplObjNull(&OUTPUT,0); return; } v.refCount=1; tmp = (char *)malloc(LSTR_LENGTH); if (pplObjDict(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } d = (dict *)OUTPUT.auxil; pplObjDate(&v,1,s.st_atime ); ppl_dictAppendCpy(d, "atime", &v, sizeof(v)); pplObjNum (&v,1,s.st_gid ,0); ppl_dictAppendCpy(d, "gid" , &v, sizeof(v)); pplObjDate(&v,1,s.st_ctime ); ppl_dictAppendCpy(d, "ctime", &v, sizeof(v)); pplObjNum (&v,1,s.st_ino ,0); ppl_dictAppendCpy(d, "ino" , &v, sizeof(v)); pplObjNum (&v,1,s.st_mode ,0); ppl_dictAppendCpy(d, "mode" , &v, sizeof(v)); pplObjDate(&v,1,s.st_mtime ); ppl_dictAppendCpy(d, "mtime", &v, sizeof(v)); pplObjNum (&v,1,s.st_nlink ,0); ppl_dictAppendCpy(d, "nlink", &v, sizeof(v)); pplObjNum (&v,1,s.st_size*8,0); v.exponent[UNIT_BIT]=1; v.dimensionless=0; ppl_dictAppendCpy(d, "size", &v, sizeof(v)); pplObjNum (&v,1,s.st_uid ,0); ppl_dictAppendCpy(d, "uid" , &v, sizeof(v)); if (S_ISREG (s.st_mode)) { COPYSTR(tmp,"regular file"); } else if (S_ISDIR (s.st_mode)) { COPYSTR(tmp,"directory"); } else if (S_ISCHR (s.st_mode)) { COPYSTR(tmp,"character special"); } else if (S_ISBLK (s.st_mode)) { COPYSTR(tmp,"block special"); } else if (S_ISFIFO(s.st_mode)) { COPYSTR(tmp,"fifo"); } else if (S_ISLNK (s.st_mode)) { COPYSTR(tmp,"symbolic link"); } else if (S_ISSOCK(s.st_mode)) { COPYSTR(tmp,"socket"); } else { COPYSTR(tmp,"other"); } pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "type", &v, sizeof(v)); if (s.st_mode & S_IRUSR) permissions[0] = 'r'; if (s.st_mode & S_IWUSR) permissions[1] = 'w'; if (s.st_mode & S_IXUSR) permissions[2] = 'x'; if (s.st_mode & S_IRGRP) permissions[3] = 'r'; if (s.st_mode & S_IWGRP) permissions[4] = 'w'; if (s.st_mode & S_IXGRP) permissions[5] = 'x'; if (s.st_mode & S_IROTH) permissions[6] = 'r'; if (s.st_mode & S_IWOTH) permissions[7] = 'w'; if (s.st_mode & S_IXOTH) permissions[8] = 'x'; COPYSTR(tmp,permissions); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "permissions", &v, sizeof(v)); return; } void pplfunc_osSystem(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.system() function requires a single string argument."); return; } pplObjNum(&OUTPUT,0, system((char*)in[0].auxil) ,0); } void pplfunc_osTmpfile(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjFile(&OUTPUT,0,1,tmpfile(),0); } void pplfunc_osUname(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *tmp; dict *d; pplObj v; struct utsname u; if (uname(&u)) { *status=1; *errType=ERR_INTERNAL; sprintf(errText,"The uname() function failed."); return; } v.refCount=1; tmp = (char *)malloc(LSTR_LENGTH); if (pplObjDict(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } d = (dict *)OUTPUT.auxil; COPYSTR(tmp,u.sysname ); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "sysname" , &v, sizeof(v)); COPYSTR(tmp,u.nodename); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "nodename", &v, sizeof(v)); COPYSTR(tmp,u.release ); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "release" , &v, sizeof(v)); COPYSTR(tmp,u.version ); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "version" , &v, sizeof(v)); COPYSTR(tmp,u.machine ); pplObjStr(&v,1,1,tmp); ppl_dictAppendCpy(d, "machine" , &v, sizeof(v)); return; } // Path operations void pplfunc_osPathExists(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.exists() function requires a single string argument."); return; } pplObjBool(&OUTPUT,0,!access((char*)in[0].auxil , F_OK)); } void pplfunc_osPathFilesize(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { struct stat buffer; int st; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.filesize() function requires a single string argument."); return; } st = stat((char*)in[0].auxil, &buffer); if (st) { pplObjNull(&OUTPUT,0); return; } pplObjNum(&OUTPUT,0,buffer.st_size*8,0); CLEANUP_APPLYUNIT(UNIT_BIT); } void pplfunc_osPathATime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { struct stat buffer; int st; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.atime() function requires a single string argument."); return; } st = stat((char*)in[0].auxil, &buffer); if (st) { pplObjNull(&OUTPUT,0); return; } pplObjDate(&OUTPUT,0,buffer.st_atime); } void pplfunc_osPathCTime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { struct stat buffer; int st; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.ctime() function requires a single string argument."); return; } st = stat((char*)in[0].auxil, &buffer); if (st) { pplObjNull(&OUTPUT,0); return; } pplObjDate(&OUTPUT,0,buffer.st_ctime); } void pplfunc_osPathMTime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { struct stat buffer; int st; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.mtime() function requires a single string argument."); return; } st = stat((char*)in[0].auxil, &buffer); if (st) { pplObjNull(&OUTPUT,0); return; } pplObjDate(&OUTPUT,0,buffer.st_mtime); } void pplfunc_osPathExpandUser(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { const int outlen=LSTR_LENGTH; char *out; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.expanduser() function requires a single string argument."); return; } out = (char *)malloc(outlen); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); } ppl_unixExpandUserHomeDir(&c->errcontext, (char*)in[0].auxil , c->errcontext.session_default.cwd , out); out[outlen-1]='\0'; pplObjStr(&OUTPUT,0,1,out); return; } void pplfunc_osPathJoin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { const int outstep=FNAME_LENGTH; int outlen=outstep, newlen, j=0; char *out; if (nArgs<1) return; out = (char *)malloc(outlen); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); } if (in[0].objType==PPLOBJ_LIST) { listIterator *iter = ppl_listIterateInit((list *)in[0].auxil); pplObj *item; int i=0; if (nArgs>1) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.join() function must be called with a single list of strings."); return; } out[0]='\0'; while ((item = (pplObj *)ppl_listIterate(&iter))!=NULL) { if (item->objType!=PPLOBJ_STR) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The os.path.join() function must be passed a list of string; input %d has type <%s>.",i+1,pplObjTypeNames[item->objType]); return; } if (i>0) { strcpy(out+j,PATHLINK); j+=strlen(out+j); } if (strncmp((char*)item->auxil,PATHLINK,strlen(PATHLINK))==0) j=0; newlen=j+item->auxilLen; if (newlen > outlen-10) { char *newout=(char *)realloc((void *)out,outlen+=outstep); if (newout==NULL) { free(out); *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); } out=newout; } strcpy(out+j, (char *)item->auxil); j+=strlen(out+j); while ((j>0)&&(out[j-1]==PATHLINK[0])) out[--j]='\0'; i++; } } else { int i; for (i=0; i.",i+1,pplObjTypeNames[in[i].objType]); return; } if (i>0) { strcpy(out+j,PATHLINK); j+=strlen(out+j); } if (strncmp((char*)in[i].auxil,PATHLINK,strlen(PATHLINK))==0) j=0; newlen=j+in[i].auxilLen; if (newlen > outlen-10) { char *newout=(char *)realloc((void *)out,outlen+=outstep); if (newout==NULL) { free(out); *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); } out=newout; } strcpy(out+j, (char *)in[i].auxil); j+=strlen(out+j); while ((j>0)&&(out[j-1]==PATHLINK[0])) out[--j]='\0'; } } pplObjStr(&OUTPUT,0,1,out); return; } pyxplot-0.9.2/src/defaultObjs/moduleRandom.h0000664000175000017500000000326412026340554017461 0ustar dcf21dcf21// moduleRandom.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleRandom.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_RANDOM_H #define _PPL_MODULE_RANDOM_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_setRandomSeed(long i); void pplfunc_frandom (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandombin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandomcs (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandomg (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandomln (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandomp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_frandomt (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/moduleTime.c0000664000175000017500000002270012026340554017126 0ustar dcf21dcf21// moduleTime.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleTime.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/calendars.h" #include "userspace/pplObj.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleTime.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" void pplfunc_timefromUnix(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "fromUnix(t)"; pplObjDate(&OUTPUT,0,in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_timefromJD (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "fromJD(t)"; pplObjDate(&OUTPUT,0, 86400.0 * (in[0].real - 2440587.5) ); CHECK_OUTPUT_OKAY; } void pplfunc_timefromMJD (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "fromMJD(t)"; pplObjDate(&OUTPUT,0, 86400.0 * (in[0].real - 40587.0) ); CHECK_OUTPUT_OKAY; } void pplfunc_timefromCalendar(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "fromCalendar(year,month,day,hour,min,sec)"; double t, offset; CHECK_NEEDSREAL(in[0], "year" ); CHECK_NEEDSREAL(in[1], "month"); CHECK_NEEDSREAL(in[2], "day" ); CHECK_NEEDSREAL(in[3], "hour" ); CHECK_NEEDSREAL(in[4], "min" ); CHECK_NEEDSREAL(in[5], "sec" ); CHECK_NEEDSINT(in[0], "year" ,"function's first input (year) must be an integer"); CHECK_NEEDINT (in[1], "month", "function's second input (month) must be an integer"); CHECK_NEEDINT (in[2], "day" , "function's third input (day) must be an integer"); CHECK_NEEDINT (in[3], "hour" , "function's fourth input (hours) must be an integer"); CHECK_NEEDINT (in[4], "min" , "function's fifth input (minutes) must be an integer"); CHECK_NEEDINT (in[5], "sec" , "function's sixth input (seconds) must be an integer"); if ((nArgs>6)&&(in[6].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its seventh argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[6].objType]); return; } if (nArgs>6) ppl_calendarTimezoneSet(c, 1, (char*)in[6].auxil); else ppl_calendarTimezoneSet(c, 0, NULL ); t = ppl_toUnixTime(c, (int)in[0].real, (int)in[1].real, (int)in[2].real, (int)in[3].real, (int)in[4].real, (int)in[5].real, status, errText); ppl_calendarTimezoneOffset(c, t, NULL, &offset); ppl_calendarTimezoneUnset(c); pplObjDate(&OUTPUT,0,t-offset); CHECK_OUTPUT_OKAY; } void pplfunc_timeInterval (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "interval(t2,t1)"; if (in[0].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if (in[1].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its second argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } pplObjNum(&OUTPUT,0,in[0].real-in[1].real,0); CLEANUP_APPLYUNIT(UNIT_TIME); } void pplfunc_timeIntervalStr (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "intervalStr(t2,t1,)"; char *format=NULL, *out=NULL; if (in[0].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if (in[1].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its second argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[1].objType]); return; } if ((nArgs>2)&&(in[2].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its third argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[2].objType]); return; } out = (char *)malloc(8192); if (out==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } if (nArgs>2) // Format specified { format = (char *)in[2].auxil; ppl_timeDiffStr(c, out, in[0].real, in[1].real, format, status, errText); if (*status) { *errType=ERR_NUMERICAL; return; } } else // Format not specified { int i=0,n,s; s = (int)fabs(in[1].real - in[0].real); out[0]='\0'; n = s/3600/24; if (n> 1) sprintf(out+i, "%d days", n); else if (n> 0) strcpy (out+i, "1 day"); i+=strlen(out+i); n = (s/3600) % 24; if ((n>0)&&(i>0)) out[i++]=' '; if (n> 1) sprintf(out+i, "%d hours", n); else if (n> 0) strcpy (out+i, "1 hour"); i+=strlen(out+i); n = (s/60) % 60; if ((n>0)&&(i>0)) out[i++]=' '; if (n> 1) sprintf(out+i, "%d minutes", n); else if (n> 0) strcpy (out+i, "1 minute"); i+=strlen(out+i); n = s % 60; if ((n>0)&&(i>0)) out[i++]=' '; if (n> 1) sprintf(out+i, "%d seconds", n); else if (n> 0) strcpy (out+i, "1 second"); i+=strlen(out+i); } pplObjStr(&OUTPUT,0,1,out); } void pplfunc_timenow (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "now()"; pplObjDate(&OUTPUT,0,(double)time(NULL)); CHECK_OUTPUT_OKAY; } void pplfunc_timestring (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "string(t,,)"; char *format=NULL, *out=NULL, timezone[FNAME_LENGTH]; double offset; if (in[0].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if ((nArgs>1)&&(in[1].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its second argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[1].objType]); return; } if ((nArgs>2)&&(in[2].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its third argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[2].objType]); return; } out = (char *)malloc(8192); if (out==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } if (nArgs>1) format = (char *)in[1].auxil; // Format specified else format = NULL; // Format not specified if (nArgs>2) ppl_calendarTimezoneSet(c, 1, (char*)in[2].auxil); else ppl_calendarTimezoneSet(c, 0, NULL ); ppl_calendarTimezoneOffset(c, in[0].real, timezone, &offset); ppl_dateString(c, out, in[0].real+offset, format, timezone, status, errText); ppl_calendarTimezoneUnset(c); if (*status) { *errType=ERR_NUMERICAL; return; } pplObjStr(&OUTPUT,0,1,out); } void pplfunc_sleep (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i; char *FunctionDescription = "sleep(t)"; struct timespec waitperiod, waitperiod2; // A time.h timespec specifier for a 50ms nanosleep wait CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "a time", UNIT_TIME, 1); waitperiod.tv_sec = floor(in[0].real); waitperiod.tv_nsec = fmod(in[0].real*1e9 , 1e9); for (i=0; i<1e6; i++) if (!nanosleep(&waitperiod,&waitperiod2)) break; else waitperiod=waitperiod2; pplObjNum(&OUTPUT,0,0,0); } void pplfunc_sleepUntil (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i; double p = in[0].real - time(NULL); char *FunctionDescription = "sleepUntil(d)"; struct timespec waitperiod, waitperiod2; // A time.h timespec specifier for a 50ms nanosleep wait if (in[0].objType!=PPLOBJ_DATE) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date as its argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if (p > 0) { waitperiod.tv_sec = floor(p); waitperiod.tv_nsec = fmod(p*1e9 , 1e9); for (i=0; i<1e6; i++) if (!nanosleep(&waitperiod,&waitperiod2)) break; else waitperiod=waitperiod2; } pplObjNum(&OUTPUT,0,0,0); } pyxplot-0.9.2/src/defaultObjs/defaultFuncsMacros.h0000664000175000017500000002411312026340554020617 0ustar dcf21dcf21// defaultFuncsMacros.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultFuncsMacros.h 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_DEFAULT_FUNCTIONS_MACROS_H #define _PPL_DEFAULT_FUNCTIONS_MACROS_H 1 #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/pplObj.h" #include "userspace/pplObjUnits.h" #include "userspace/unitsDisp.h" #define OUTPUT in[-1] #define NULL_OUTPUT \ { OUTPUT.real = GSL_NAN; OUTPUT.imag = 0; OUTPUT.flagComplex=0; return; } #define QUERY_OUT_OF_RANGE \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The function %s is not defined at the requested point in parameter space.", FunctionDescription); return; } \ else { NULL_OUTPUT; } \ } #define QUERY_MUST_BE_REAL \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The function %s only accepts real arguments; the supplied arguments are complex.", FunctionDescription); return; } \ else { NULL_OUTPUT; } \ } #define CHECK_NEEDLONG(X, VAR, DESCRIPTION) \ { \ if (((X).flagComplex) || ((X).real < 0) || ((X).real >= LONG_MAX)) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_RANGE; sprintf(errText, "The %s %s in the range 0 <= %s < %ld.",FunctionDescription,DESCRIPTION,VAR,LONG_MAX); return; } \ else { NULL_OUTPUT; } \ } \ } #define CHECK_NEEDINT(X, VAR, DESCRIPTION) \ { \ if (((X).flagComplex) || ((X).real < 0) || ((X).real >= INT_MAX)) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_RANGE; sprintf(errText, "The %s %s in the range 0 <= %s < %d.",FunctionDescription,DESCRIPTION,VAR,INT_MAX); return; } \ else { NULL_OUTPUT; } \ } \ } #define CHECK_NEEDSINT(X, VAR, DESCRIPTION) \ { \ if (((X).real <= INT_MIN) || ((X).real >= INT_MAX)) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_RANGE; sprintf(errText, "The %s %s in the range %d <= %s < %d.",FunctionDescription,DESCRIPTION,INT_MIN,VAR,INT_MAX); return; } \ else { NULL_OUTPUT; } \ } \ } #define CHECK_NEEDSREAL(X, VAR) \ { \ if ((X).flagComplex) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_TYPE; sprintf(c->errStat.errBuff,"The %s requires real arguments; argument %s is complex.",FunctionDescription,VAR); return; } \ else { NULL_OUTPUT; } \ } \ \ if (!(X).dimensionless) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_TYPE; sprintf(errText,"The %s requires dimensionless arguments; argument %s has dimensions of <%s>.",FunctionDescription,VAR,ppl_printUnit(c, &(X), NULL, NULL, 1, 1, 0)); return; } \ else { NULL_OUTPUT; } \ } \ \ if ((!gsl_finite((X).real)) || (!gsl_finite((X).imag))) \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_TYPE; sprintf(errText,"The %s requires finite arguments; argument %s is not finite.",FunctionDescription,VAR); return; } \ else { NULL_OUTPUT; } \ } \ } #define NAN_CHECK_FAIL \ { \ if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_RANGE; sprintf(errText, "The function %s has received a non-finite input.",FunctionDescription); return; } \ else { NULL_OUTPUT; } \ } #define CHECK_1NOTNAN \ { \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[0].flagComplex)) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[0].real)) || (!gsl_finite(in[0].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_2NOTNAN \ { \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && ((in[0].flagComplex) || (in[1].flagComplex))) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[0].real)) || (!gsl_finite(in[0].imag))) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[1].real)) || (!gsl_finite(in[1].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_3NOTNAN \ { \ CHECK_2NOTNAN; \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[2].flagComplex)) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[2].real)) || (!gsl_finite(in[2].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_4NOTNAN \ { \ CHECK_3NOTNAN; \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[3].flagComplex)) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[3].real)) || (!gsl_finite(in[3].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_5NOTNAN \ { \ CHECK_4NOTNAN; \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[4].flagComplex)) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[4].real)) || (!gsl_finite(in[4].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_6NOTNAN \ { \ CHECK_5NOTNAN; \ if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[5].flagComplex)) { NAN_CHECK_FAIL; } \ if ((!gsl_finite(in[5].real)) || (!gsl_finite(in[5].imag))) { NAN_CHECK_FAIL; } \ } #define CHECK_1INPUT_DIMLESS \ { \ if (!(in[0].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs. Supplied input has dimensions of <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 1, 1, 0)); \ return; \ } \ } #define CHECK_2INPUT_DIMLESS \ { \ if (!(in[0].dimensionless && in[1].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs. Supplied inputs have dimensions of <%s> and <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[1], NULL, NULL, 1, 1, 0)); \ return; \ } \ } #define CHECK_3INPUT_DIMLESS \ { \ if (!(in[0].dimensionless && in[1].dimensionless && in[2].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs. Supplied inputs have dimensions of <%s>, <%s> and <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[1], NULL, NULL, 1, 1, 0), ppl_printUnit(c, &in[2], NULL, NULL, 2, 1, 0)); \ return; \ } \ } #define CHECK_4INPUT_DIMLESS \ { \ if (!(in[0].dimensionless && in[1].dimensionless && in[2].dimensionless && in[3].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs.", FunctionDescription); \ return; \ } \ } #define CHECK_5INPUT_DIMLESS \ { \ if (!(in[0].dimensionless && in[1].dimensionless && in[2].dimensionless && in[3].dimensionless && in[4].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs.", FunctionDescription); \ return; \ } \ } #define CHECK_6INPUT_DIMLESS \ { \ if (!(in[0].dimensionless && in[1].dimensionless && in[2].dimensionless && in[3].dimensionless && in[4].dimensionless && in[5].dimensionless)) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless inputs.", FunctionDescription); \ return; \ } \ } #define CHECK_2INPUT_DIMMATCH \ { \ if ((!(in[0].dimensionless && in[1].dimensionless)) && (!(ppl_unitsDimEqual(&in[0], &in[1])))) \ { \ *status = 1; \ *errType=ERR_UNIT; \ sprintf(errText, "The %s function can only act upon inputs with matching dimensions. Supplied inputs have dimensions of <%s> and <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[1], NULL, NULL, 1, 1, 0)); \ return; \ } \ } #define CHECK_DIMLESS_OR_HAS_UNIT(X, DESCRIPTION, UNITNAME, UNIT, UNITN) \ { \ if (!((X).dimensionless)) \ for (i=0; i.", DESCRIPTION, FunctionDescription, UNITNAME, ppl_printUnit(c, &X, NULL, NULL, 1, 1, 0)); \ return; \ } \ } \ #define IF_1COMPLEX if (in[0].flagComplex) { #define IF_2COMPLEX if ((in[0].flagComplex) || (in[1].flagComplex)) { #define IF_3COMPLEX if ((in[0].flagComplex) || (in[1].flagComplex) || (in[2].flagComplex)) { #define IF_4COMPLEX if ((in[0].flagComplex) || (in[1].flagComplex) || (in[2].flagComplex) || (in[3].flagComplex)) { #define IF_5COMPLEX if ((in[0].flagComplex) || (in[1].flagComplex) || (in[2].flagComplex) || (in[3].flagComplex) || (in[4].flagComplex)) { #define IF_6COMPLEX if ((in[0].flagComplex) || (in[1].flagComplex) || (in[2].flagComplex) || (in[3].flagComplex) || (in[4].flagComplex) || (in[5].flagComplex)) { #define ELSE_REAL } else { #define ENDIF } #define CLEANUP_GSLCOMPLEX \ OUTPUT.real = GSL_REAL(z); \ OUTPUT.imag = GSL_IMAG(z); \ OUTPUT.flagComplex = !ppl_dblEqual(OUTPUT.imag,0); \ if (!OUTPUT.flagComplex) OUTPUT.imag=0.0; #define CLEANUP_APPLYUNIT(UNIT) \ OUTPUT.dimensionless = ((UNIT==UNIT_ANGLE)&&(c->set->term_current.UnitAngleDimless==SW_ONOFF_ON)); \ if (!OUTPUT.dimensionless) OUTPUT.exponent[UNIT] = 1; \ #define CHECK_OUTPUT_OKAY \ if ((!gsl_finite(OUTPUT.real)) || (!gsl_finite(OUTPUT.imag)) || ((OUTPUT.flagComplex) && (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF))) \ { QUERY_OUT_OF_RANGE; } #endif pyxplot-0.9.2/src/defaultObjs/moduleFractals.h0000664000175000017500000000221212026340554017770 0ustar dcf21dcf21// moduleFractals.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleFractals.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_FRACTALS_H #define _PPL_MODULE_FRACTALS_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_julia (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_mandelbrot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/moduleColor.h0000664000175000017500000000217412026340554017316 0ustar dcf21dcf21// moduleColor.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleColor.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_COLOR_H #define _PPL_MODULE_COLOR_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_colWavelen (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_colSpectrum(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/defaultVars.c0000664000175000017500000015357212026340554017316 0ustar dcf21dcf21// defaultVars.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultVars.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/dict.h" #include "settings/epsColors.h" #include "settings/settingTypes.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjUnits.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultVars.h" #include "defaultObjs/moduleAst.h" #include "defaultObjs/moduleColor.h" #include "defaultObjs/moduleFractals.h" #include "defaultObjs/moduleOs.h" #include "defaultObjs/modulePhy.h" #include "defaultObjs/moduleRandom.h" #include "defaultObjs/moduleStats.h" #include "defaultObjs/moduleTime.h" void ppl_makeDefaultVars(ppl_context *out) { out->ns_ptr = 1; out->ns_branch = 0; out->namespaces[0] = NULL; // Will be defaults namespace out->namespaces[1] = ppl_dictInit(1); // Will be root namespace // Default variables { pplObj v, m; dict *d, *d2, *d3; int i; m.refCount = v.refCount = 1; ppl_dictAppendCpy(out->namespaces[1] , "defaults" , pplObjModule(&m,1,1,1) , sizeof(v)); d = (dict *)m.auxil; out->namespaces[0] = d; // Root namespace pplObjNum(&v,1,M_PI,0); ppl_dictAppendCpy(d , "pi" , (void *)&v , sizeof(v)); // pi v.real = M_E; ppl_dictAppendCpy(d , "e" , (void *)&v , sizeof(v)); // e v.real = M_EULER; ppl_dictAppendCpy(d , "euler" , (void *)&v , sizeof(v)); // Euler constant v.real = (1.0+sqrt(5))/2.0; ppl_dictAppendCpy(d , "goldenRatio", (void *)&v , sizeof(v)); // Golden Ratio v.real = GSL_NAN; ppl_dictAppendCpy(d , "nan" , (void *)&v , sizeof(v)); // nan v.real = 0.0; v.imag = 1.0; v.flagComplex = 1; ppl_dictAppendCpy(d , "i" , (void *)&v , sizeof(v)); // i pplObjBool(&v,1,1); ppl_dictAppendCpy(d , "true" , (void *)&v , sizeof(v)); // True pplObjBool(&v,1,0); ppl_dictAppendCpy(d , "false" , (void *)&v , sizeof(v)); // False pplObjStr(&v,1,0,VERSION); ppl_dictAppendCpy(d , "version" , (void *)&v , sizeof(v)); // Pyxplot version string // types module ppl_dictAppendCpy(d , "types" , pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; for (i=0; i<=PPLOBJ_USER; i++) if ((i!=PPLOBJ_GLOB)&&(i!=PPLOBJ_ZOM)&&(i!=PPLOBJ_EXP)&&(i!=PPLOBJ_BYT)) { pplObjCpy(&v, &pplObjPrototypes[i], 0, 1, 1); ppl_dictAppendCpy(d2, pplObjTypeNames[i], (void *)&v, sizeof(v)); } // exceptions module ppl_dictAppendCpy(d , "exceptions", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; pplObjException(&v, 1, 0, "generic", ERR_GENERIC); ppl_dictAppendCpy(d2 , "generic" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "syntax", ERR_SYNTAX); ppl_dictAppendCpy(d2 , "syntax" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "numerical", ERR_NUMERICAL); ppl_dictAppendCpy(d2 , "numerical" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "file", ERR_FILE); ppl_dictAppendCpy(d2 , "file" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "range", ERR_RANGE); ppl_dictAppendCpy(d2 , "range" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "unit", ERR_UNIT); ppl_dictAppendCpy(d2 , "unit" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "overflow", ERR_OVERFLOW); ppl_dictAppendCpy(d2 , "overflow" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "namespace", ERR_NAMESPACE); ppl_dictAppendCpy(d2 , "namespace" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "type", ERR_TYPE); ppl_dictAppendCpy(d2 , "type" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "interrupt", ERR_INTERRUPT); ppl_dictAppendCpy(d2 , "interrupt" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "key", ERR_DICTKEY); ppl_dictAppendCpy(d2 , "key" , (void *)&v , sizeof(v)); pplObjException(&v, 1, 0, "assertion", ERR_ASSERT); ppl_dictAppendCpy(d2 , "assertion" , (void *)&v , sizeof(v)); // colors module ppl_dictAppendCpy(d , "colors" , pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; for (i=0; SW_COLOR_INT[i]>=0; i++) { pplObjColor(&v,1,SW_COLSPACE_CMYK,SW_COLOR_CMYK_C[i],SW_COLOR_CMYK_M[i],SW_COLOR_CMYK_Y[i],SW_COLOR_CMYK_K[i]); v.exponent[2] = SW_COLOR_INT[i]; ppl_dictAppendCpy(d2 , SW_COLOR_STR[i] , (void *)&v , sizeof(v)); } ppl_addSystemFunc(d2,"wavelength" ,2,2,1,1,1,0,(void *)&pplfunc_colWavelen , "wavelength(lambda,norm)", "\\mathrm{wavelength}@<@1,@2@>", "wavelength(lambda,norm) returns a color representation of monochromatic light at wavelength lambda, normalised to brightness norm"); ppl_addSystemFunc(d2,"spectrum" ,2,2,0,0,0,0,(void *)&pplfunc_colSpectrum , "spectrum(spec,norm)", "\\mathrm{spectrum}@<@1,@2@>", "spectrum(spec,norm) returns a color representation of the spectrum spec, normalised to brightness norm. spec should be a function that takes a single input (wavelength) with units of length, and may return an output with arbitrary units"); // phy module ppl_dictAppendCpy(d , "phy" , pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; pplObjNum(&v, 1, GSL_CONST_MKSA_SPEED_OF_LIGHT, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH]=1 ; v.exponent[UNIT_TIME]=-1; ppl_dictAppendCpy(d2 , "c" , (void *)&v , sizeof(v)); // Speed of light pplObjNum(&v, 1, GSL_CONST_MKSA_VACUUM_PERMEABILITY, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = 1; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_TIME] = -2; v.exponent[UNIT_CURRENT] = -2; ppl_dictAppendCpy(d2 , "mu_0" , (void *)&v , sizeof(v)); // The permeability of free space pplObjNum(&v, 1, GSL_CONST_MKSA_VACUUM_PERMITTIVITY, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] =-3; v.exponent[UNIT_MASS] =-1; v.exponent[UNIT_TIME] = 4; v.exponent[UNIT_CURRENT] = 2; ppl_dictAppendCpy(d2 , "epsilon_0" , (void *)&v , sizeof(v)); // The permittivity of free space pplObjNum(&v, 1, GSL_CONST_MKSA_ELECTRON_CHARGE, 0); v.dimensionless = 0; v.exponent[UNIT_CURRENT] = 1; v.exponent[UNIT_TIME] = 1; ppl_dictAppendCpy(d2 , "q" , (void *)&v , sizeof(v)); // The fundamental charge pplObjNum(&v, 1, GSL_CONST_MKSA_PLANCKS_CONSTANT_H, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_TIME] =-1; ppl_dictAppendCpy(d2 , "h" , (void *)&v , sizeof(v)); // The Planck constant v.real = GSL_CONST_MKSA_PLANCKS_CONSTANT_HBAR; ppl_dictAppendCpy(d2 , "hbar" , (void *)&v , sizeof(v)); // The Planck constant / 2pi pplObjNum(&v, 1, GSL_CONST_NUM_AVOGADRO, 0); v.dimensionless = 0; v.exponent[UNIT_MOLE] = -1; ppl_dictAppendCpy(d2 , "NA" , (void *)&v , sizeof(v)); // The Avogadro constant pplObjNum(&v, 1, 3.839e26, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_TIME] =-3; ppl_dictAppendCpy(d2 , "Lsun" , (void *)&v , sizeof(v)); // The solar luminosity pplObjNum(&v, 1, GSL_CONST_MKSA_UNIFIED_ATOMIC_MASS, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; ppl_dictAppendCpy(d2 , "m_u" , (void *)&v , sizeof(v)); // The universal mass constant v.real = GSL_CONST_MKSA_MASS_ELECTRON; ppl_dictAppendCpy(d2 , "m_e" , (void *)&v , sizeof(v)); // The electron mass v.real = GSL_CONST_MKSA_MASS_PROTON; ppl_dictAppendCpy(d2 , "m_p" , (void *)&v , sizeof(v)); // The proton mass v.real = GSL_CONST_MKSA_MASS_NEUTRON; ppl_dictAppendCpy(d2 , "m_n" , (void *)&v , sizeof(v)); // The neutron mass v.real = GSL_CONST_MKSA_MASS_MUON; ppl_dictAppendCpy(d2 , "m_muon" , (void *)&v , sizeof(v)); // The muon mass v.real = NASA_MG_SUN / NASA_G; ppl_dictAppendCpy(d2 , "Msun" , (void *)&v , sizeof(v)); // The solar mass pplObjNum(&v, 1, GSL_CONST_MKSA_RYDBERG / GSL_CONST_MKSA_SPEED_OF_LIGHT / GSL_CONST_MKSA_PLANCKS_CONSTANT_H, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = -1; ppl_dictAppendCpy(d2 , "Ry" , (void *)&v , sizeof(v)); // The Rydberg constant pplObjNum(&v, 1, GSL_CONST_NUM_FINE_STRUCTURE, 0); v.dimensionless = 1; ppl_dictAppendCpy(d2 , "alpha" , (void *)&v , sizeof(v)); // The fine structure constant pplObjNum(&v, 1, 6.955e8, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = 1; ppl_dictAppendCpy(d2 , "Rsun" , (void *)&v , sizeof(v)); // The solar radius pplObjNum(&v, 1, GSL_CONST_MKSA_BOHR_MAGNETON, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_CURRENT] = 1; ppl_dictAppendCpy(d2 , "mu_b" , (void *)&v , sizeof(v)); // The Bohr magneton pplObjNum(&v, 1, GSL_CONST_MKSA_MOLAR_GAS, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_TIME] =-2; v.exponent[UNIT_TEMPERATURE] =-1; v.exponent[UNIT_MOLE] =-1; ppl_dictAppendCpy(d2 , "R" , (void *)&v , sizeof(v)); // The gas constant pplObjNum(&v, 1, GSL_CONST_MKSA_BOLTZMANN, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_TIME] =-2; v.exponent[UNIT_TEMPERATURE] =-1; ppl_dictAppendCpy(d2 , "kB" , (void *)&v , sizeof(v)); // The Boltzmann constant v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_LENGTH] = 2; v.exponent[UNIT_TIME] =-2; pplObjNum(&v, 1, GSL_CONST_MKSA_STEFAN_BOLTZMANN_CONSTANT, 0); v.dimensionless = 0; v.exponent[UNIT_MASS] = 1; v.exponent[UNIT_TIME] =-3; v.exponent[UNIT_TEMPERATURE] =-4; ppl_dictAppendCpy(d2 , "sigma" , (void *)&v , sizeof(v)); // The Stefan-Boltzmann constant pplObjNum(&v, 1, NASA_G, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = 3; v.exponent[UNIT_TIME] =-2; v.exponent[UNIT_MASS] =-1; ppl_dictAppendCpy(d2 , "G" , (void *)&v , sizeof(v)); // The gravitational constant pplObjNum(&v, 1, GSL_CONST_MKSA_GRAV_ACCEL, 0); v.dimensionless = 0; v.exponent[UNIT_LENGTH] = 1; v.exponent[UNIT_TIME] =-2; ppl_dictAppendCpy(d2 , "g" , (void *)&v , sizeof(v)); // The standard acceleration due to gravity on Earth ppl_addSystemFunc(d2,"Bv" ,2,2,1,1,1,0,(void *)&pplfunc_planck_Bv , "Bv(nu,T)", "\\mathrm{B_\\nu}@<@1,@2@>", "Bv(nu,T) returns the power emitted by a blackbody of temperature T per unit area, per unit solid angle, per unit frequency"); ppl_addSystemFunc(d2,"Bvmax" ,1,1,1,1,1,0,(void *)&pplfunc_planck_Bvmax, "Bvmax(T)", "\\mathrm{B_{\\nu,max}}@<@1@>", "Bvmax(T) returns the frequency of the maximum of the function Bv(nu,T)"); // OS module ppl_dictAppendCpy(d , "os" , pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"chdir" ,1,1,0,0,0,0,(void *)&pplfunc_osChdir , "chdir(x)", "\\mathrm{chdir}@<@1@>", "chdir(x) changes working directory to x"); ppl_addSystemFunc(d2,"getcwd" ,0,0,1,1,1,1,(void *)&pplfunc_osGetCwd , "getcwd()", "\\mathrm{getcwd}@<@>", "getcwd() returns the path of the current working directory"); ppl_addSystemFunc(d2,"getegid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetEgid , "getegid()" , "\\mathrm{getegid}@<@>", "getegid() returns the effective group id of the Pyxplot process"); ppl_addSystemFunc(d2,"geteuid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetEuid , "geteuid()" , "\\mathrm{geteuid}@<@>", "geteuid() returns the effective user id of the Pyxplot process"); ppl_addSystemFunc(d2,"getgid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetGid , "getgid()" , "\\mathrm{getgid}@<@>", "getgid() returns the group id of the Pyxplot process"); ppl_addSystemFunc(d2,"getpid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetPid , "getpid()" , "\\mathrm{getpid}@<@>", "getpid() returns the process id of the Pyxplot process"); ppl_addSystemFunc(d2,"getpgrp" ,0,0,1,1,1,1,(void *)&pplfunc_osGetPgrp , "getpgrp()" , "\\mathrm{getpgrp}@<@>", "getpgrp() returns the process group id of the Pyxplot process"); ppl_addSystemFunc(d2,"getppid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetPpid , "getppid()" , "\\mathrm{getppid}@<@>", "getpid() returns the parent process id of the Pyxplot process"); ppl_addSystemFunc(d2,"getuid" ,0,0,1,1,1,1,(void *)&pplfunc_osGetUid , "getuid()" , "\\mathrm{getuid}@<@>", "getuid() returns the user id of the Pyxplot process"); ppl_addSystemFunc(d2,"gethomedir" ,0,0,1,1,1,1,(void *)&pplfunc_osGetHome , "gethomedir()" , "\\mathrm{gethomedir}@<@>", "gethomedir() returns the path of the user's home directory"); ppl_addSystemFunc(d2,"gethostname" ,0,0,1,1,1,1,(void *)&pplfunc_osGetHost , "gethostname()", "\\mathrm{gethostname}@<@>", "gethostname() returns the system's host name"); ppl_addSystemFunc(d2,"getlogin" ,0,0,1,1,1,1,(void *)&pplfunc_osGetLogin, "getlogin()", "\\mathrm{getlogin}@<@>", "getlogin() returns the system login of the user"); ppl_addSystemFunc(d2,"getrealname" ,0,0,1,1,1,1,(void *)&pplfunc_osGetRealName, "getrealname()", "\\mathrm{getrealname}@<@>", "getrealname() returns the user's real name"); ppl_addSystemFunc(d2,"glob" ,1,1,0,0,0,0,(void *)&pplfunc_osGlob , "glob(x)", "\\mathrm{glob}@<@1@>", "glob(x) returns a list of files which match the supplied wildcard"); ppl_addSystemFunc(d2,"popen" ,1,2,0,0,0,0,(void *)&pplfunc_osPopen , "popen(x[,y])", "\\mathrm{popen}@<@0@>", "popen(x[,y]) opens a pipe to the command x with access mode y, and returns a file object"); ppl_addSystemFunc(d2,"stat" ,1,1,0,0,0,0,(void *)&pplfunc_osStat , "stat(x)", "\\mathrm{stat}@<@1@>", "stat(x) returns a dictionary of information about the file x"); ppl_addSystemFunc(d2,"system" ,1,1,0,0,0,0,(void *)&pplfunc_osSystem , "system(x)", "\\mathrm{system}@<@1@>", "system(x) executes a command in a subshell"); ppl_addSystemFunc(d2,"tmpfile" ,0,0,1,1,1,1,(void *)&pplfunc_osTmpfile , "tmpfile()", "\\mathrm{tmpfile}@<@>", "tmpfile() returns a file handle for a temporary file"); ppl_addSystemFunc(d2,"uname" ,0,0,1,1,1,1,(void *)&pplfunc_osUname , "uname()", "\\mathrm{uname}@<@>", "uname() returns a dictionary of information about the operating system"); ppl_dictAppendCpy(d2 , "path" , pplObjModule(&m,1,1,1) , sizeof(v)); d3 = (dict *)m.auxil; ppl_addSystemFunc(d3,"atime" ,1,1,0,0,0,0,(void *)&pplfunc_osPathATime, "atime(x)", "\\mathrm{atime}@<@0@>", "atime(x) returns a date object representing the time of the last access of the file with pathname x"); ppl_addSystemFunc(d3,"ctime" ,1,1,0,0,0,0,(void *)&pplfunc_osPathCTime, "ctime(x)", "\\mathrm{ctime}@<@0@>", "ctime(x) returns a date object representing the time of the last status change to the file with pathname x"); ppl_addSystemFunc(d3,"exists" ,1,1,0,0,0,0,(void *)&pplfunc_osPathExists, "exists(x)", "\\mathrm{exists}@<@0@>", "exists(x) returns a boolean flag indicating whether a file with pathname x exists"); ppl_addSystemFunc(d3,"expanduser" ,1,1,0,0,0,0,(void *)&pplfunc_osPathExpandUser, "expanduser(x)", "\\mathrm{expanduser@<@0@>", "expanduser(x) returns its argument with ~s indicating home directories expanded"); ppl_addSystemFunc(d3,"filesize" ,1,1,0,0,0,0,(void *)&pplfunc_osPathFilesize, "filesize(x)", "\\mathrm{filesize}@<@0@>", "filesize(x) returns the size, in bytes, of the file with pathname x"); ppl_addSystemFunc(d3,"join" ,1,9999,0,0,0,0,(void *)&pplfunc_osPathJoin , "join(...)", "\\mathrm{join}@<@0@>", "join(...) joins a series of strings intelligently into a pathname"); ppl_addSystemFunc(d3,"mtime" ,1,1,0,0,0,0,(void *)&pplfunc_osPathMTime, "mtime(x)", "\\mathrm{mtime}@<@0@>", "mtime(x) returns a date object representing the time of the last modification of the file with pathname x"); pplObjFile(&v, 1, 1, stderr, 2); ppl_dictAppendCpy(d2 , "stderr" , (void *)&v , sizeof(v)); // stderr pplObjFile(&v, 1, 1, stdin, 2); ppl_dictAppendCpy(d2 , "stdin" , (void *)&v , sizeof(v)); // stdin pplObjFile(&v, 1, 1, stdout, 2); ppl_dictAppendCpy(d2 , "stdout" , (void *)&v , sizeof(v)); // stdout // Default functions (default namespace) ppl_addSystemFunc(d,"abs" ,1,1,1,1,0,0,(void *)&pplfunc_abs , "abs(z)", "\\mathrm{abs}@<@1@>", "abs(z) returns the absolute magnitude of z"); ppl_addSystemFunc(d,"acos" ,1,1,1,1,0,1,(void *)&pplfunc_acos , "acos(z)", "\\mathrm{acos}@<@1@>", "acos(z) returns the arccosine of z"); ppl_addSystemFunc(d,"acosh" ,1,1,1,1,0,1,(void *)&pplfunc_acosh , "acosh(z)", "\\mathrm{acosh}@<@1@>", "acosh(z) returns the hyperbolic arccosine of z"); ppl_addSystemFunc(d,"acot" ,1,1,1,1,0,1,(void *)&pplfunc_acot , "acot(z)", "\\mathrm{acot}@<@1@>", "acot(z) returns the arccotangent of z"); ppl_addSystemFunc(d,"acoth" ,1,1,1,1,0,1,(void *)&pplfunc_acoth , "acoth(z)", "\\mathrm{acoth}@<@1@>", "acoth(z) returns the hyperbolic arccotangent of z"); ppl_addSystemFunc(d,"acsc" ,1,1,1,1,0,1,(void *)&pplfunc_acsc , "acsc(z)", "\\mathrm{acsc}@<@1@>", "acsc(z) returns the arccosecant of z"); ppl_addSystemFunc(d,"acosec" ,1,1,1,1,0,1,(void *)&pplfunc_acsc , "acosec(z)", "\\mathrm{acosec}@<@1@>", "acosec(z) returns the arccosecant of z"); ppl_addSystemFunc(d,"acsch" ,1,1,1,1,0,1,(void *)&pplfunc_acsch , "acsch(z)", "\\mathrm{acsch}@<@1@>", "acsch(z) returns the hyperbolic arccosecant of z"); ppl_addSystemFunc(d,"acosech" ,1,1,1,1,0,1,(void *)&pplfunc_acsch , "acosech(z)", "\\mathrm{acosech}@<@1@>", "acosech(z) returns the hyperbolic arccosecant of z"); ppl_addSystemFunc(d,"airy_ai" ,1,1,1,1,0,1,(void *)&pplfunc_airy_ai , "airy_ai(z)", "\\mathrm{airy\\_ai}@<@1@>", "airy_ai(z) returns the Airy function Ai evaluated at z"); ppl_addSystemFunc(d,"airy_ai_diff" ,1,1,1,1,0,1,(void *)&pplfunc_airy_ai_diff, "airy_ai_diff(z)", "\\mathrm{airy\\_ai\\_diff}@<@1@>", "airy_ai_diff(z) returns the first derivative of the Airy function Ai evaluated at z"); ppl_addSystemFunc(d,"airy_bi" ,1,1,1,1,0,1,(void *)&pplfunc_airy_bi , "airy_bi(z)", "\\mathrm{airy\\_bi}@<@1@>", "airy_bi(z) returns the Airy function Bi evaluated at z"); ppl_addSystemFunc(d,"airy_bi_diff" ,1,1,1,1,0,1,(void *)&pplfunc_airy_bi_diff, "airy_bi_diff(z)", "\\mathrm{airy\\_bi\\_diff}@<@1@>", "airy_bi_diff(z) returns the first derivative of the Airy function Bi evaluated at z"); ppl_addSystemFunc(d,"arg" ,1,1,1,1,0,0,(void *)&pplfunc_arg , "arg(z)", "\\mathrm{arg}@<@1@>", "arg(z) returns the argument of the complex number z"); ppl_addSystemFunc(d,"asec" ,1,1,1,1,0,1,(void *)&pplfunc_asec , "asec(z)", "\\mathrm{asec}@<@1@>", "asec(z) returns the arcsecant of z"); ppl_addSystemFunc(d,"asech" ,1,1,1,1,0,1,(void *)&pplfunc_asech , "asech(z)", "\\mathrm{asech}@<@1@>", "asech(z) returns the hyperbolic arcsecant of z"); ppl_addSystemFunc(d,"asin" ,1,1,1,1,0,1,(void *)&pplfunc_asin , "asin(z)", "\\mathrm{asin}@<@1@>", "asin(z) returns the arcsine of z"); ppl_addSystemFunc(d,"asinh" ,1,1,1,1,0,1,(void *)&pplfunc_asinh , "asinh(z)", "\\mathrm{asinh}@<@1@>", "asinh(z) returns the hyperbolic arcsine of z"); ppl_addSystemFunc(d,"atan" ,1,1,1,1,0,1,(void *)&pplfunc_atan , "atan(z)", "\\mathrm{atan}@<@1@>", "atan(z) returns the arctangent of z"); ppl_addSystemFunc(d,"atan2" ,2,2,1,1,1,0,(void *)&pplfunc_atan2 , "atan2(x,y)", "\\mathrm{atan2}@<@1,@2@>", "atan2(x,y) returns the arctangent of x/y. Unlike atan(y/x), atan2(x,y) takes account of the signs of both x and y to remove the degeneracy between (1,1) and (-1,-1)"); ppl_addSystemFunc(d,"atanh" ,1,1,1,1,0,1,(void *)&pplfunc_atanh , "atanh(z)", "\\mathrm{atanh}@<@1@>", "atanh(z) returns the hyperbolic arctangent of z"); ppl_addSystemFunc(d,"besseli" ,2,2,1,1,1,1,(void *)&pplfunc_besseli , "besseli(l,x)", "\\mathrm{besseli}@<@1,@2@>", "besseli(l,x) evaluates the lth regular modified spherical Bessel function at x"); ppl_addSystemFunc(d,"besselI" ,2,2,1,1,1,1,(void *)&pplfunc_besselI , "besselI(l,x)", "\\mathrm{besselI}@<@1,@2@>", "besselI(l,x) evaluates the lth regular modified cylindrical Bessel function at x"); ppl_addSystemFunc(d,"besselj" ,2,2,1,1,1,1,(void *)&pplfunc_besselj , "besselj(l,x)", "\\mathrm{besselj}@<@1,@2@>", "besselj(l,x) evaluates the lth regular spherical Bessel function at x"); ppl_addSystemFunc(d,"besselJ" ,2,2,1,1,1,1,(void *)&pplfunc_besselJ , "besselJ(l,x)", "\\mathrm{besselJ}@<@1,@2@>", "besselJ(l,x) evaluates the lth regular cylindrical Bessel function at x"); ppl_addSystemFunc(d,"besselk" ,2,2,1,1,1,1,(void *)&pplfunc_besselk , "besselk(l,x)", "\\mathrm{besselk}@<@1,@2@>", "besselk(l,x) evaluates the lth irregular modified spherical Bessel function at x"); ppl_addSystemFunc(d,"besselK" ,2,2,1,1,1,1,(void *)&pplfunc_besselK , "besselK(l,x)", "\\mathrm{besselK}@<@1,@2@>", "besselK(l,x) evaluates the lth irregular modified cylindrical Bessel function at x"); ppl_addSystemFunc(d,"bessely" ,2,2,1,1,1,1,(void *)&pplfunc_bessely , "bessely(l,x)", "\\mathrm{bessely}@<@1,@2@>", "bessely(l,x) evaluates the lth irregular spherical Bessel function at x"); ppl_addSystemFunc(d,"besselY" ,2,2,1,1,1,1,(void *)&pplfunc_besselY , "besselY(l,x)", "\\mathrm{besselY}@<@1,@2@>", "besselY(l,x) evaluates the lth irregular cylindrical Bessel function at x"); ppl_addSystemFunc(d,"beta" ,2,2,1,1,1,1,(void *)&pplfunc_beta , "beta(a,b)", "\\mathrm{B}@<@1,@2@>", "beta(a,b) evaluates the beta function B(a,b)"); ppl_addSystemFunc(d,"call" ,2,2,0,0,0,0,(void *)&pplfunc_call , "call(f,a)", "\\mathrm{call}@<@1,@2@>", "call(f,a) calls the function f with the arguments contained in the list a"); ppl_addSystemFunc(d,"ceil" ,1,1,1,1,1,1,(void *)&pplfunc_ceil , "ceil(x)", "\\mathrm{ceil}@<@1@>", "ceil(x) returns the smallest integer value greater than or equal to x"); ppl_addSystemFunc(d,"chr" ,1,1,1,1,1,1,(void *)&pplfunc_chr , "chr(x)", "\\mathrm{chr}@<@1@>", "chr(x) returns the character with ASCII code x"); ppl_addSystemFunc(d,"classOf" ,1,1,0,0,0,0,(void *)&pplfunc_classOf , "classOf(x)", "\\mathrm{classOf}@<@1@>", "classOf(x) returns the class prototype of the object x"); ppl_addSystemFunc(d,"cmp" ,2,2,0,0,0,0,(void *)&pplfunc_cmp , "cmp(a,b)", "\\mathrm{cmp}@<@1,@2@>", "cmp(a,b) returns 1 if a>b, -1 if a", "cmyk(c,m,y,k) returns a color with specified CMYK components in the range 0-1"); ppl_addSystemFunc(d,"conjugate" ,1,1,1,1,0,0,(void *)&pplfunc_conjugate , "conjugate(z)", "\\mathrm{conjugate}@<@1@>", "conjugate(z) returns the complex conjugate of z"); ppl_addSystemFunc(d,"copy" ,1,1,0,0,0,0,(void *)&pplfunc_copy , "copy(x)", "\\mathrm{copy}@<@1@>", "copy(x) returns a copy of the data structure x. Nested data structures are not copied; see deepcopy(x) for this"); ppl_addSystemFunc(d,"cos" ,1,1,1,1,0,0,(void *)&pplfunc_cos , "cos(z)", "\\mathrm{cos}@<@1@>", "cos(x) returns the cosine of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"cosh" ,1,1,1,1,0,0,(void *)&pplfunc_cosh , "cosh(z)", "\\mathrm{cosh}@<@1@>", "cosh(x) returns the hyperbolic cosine of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"cot" ,1,1,1,1,0,0,(void *)&pplfunc_cot , "cot(z)", "\\mathrm{cot}@<@1@>", "cot(x) returns the cotangent of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"coth" ,1,1,1,1,0,0,(void *)&pplfunc_coth , "coth(z)", "\\mathrm{coth}@<@1@>", "coth(x) returns the hyperbolic cotangent of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"csc" ,1,1,1,1,0,0,(void *)&pplfunc_csc , "csc(z)", "\\mathrm{csc}@<@1@>", "csc(x) returns the cosecant of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"cosec" ,1,1,1,1,0,0,(void *)&pplfunc_csc , "cosec(z)", "\\mathrm{cosec}@<@1@>", "cosec(x) returns the cosecant of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"cross" ,2,2,0,0,0,0,(void *)&pplfunc_cross , "cross(a,b)", "\\mathrm{cross}@<@1,@2@>", "cross(a,b) returns the vector cross product of the three-component vectors a and b"); ppl_addSystemFunc(d,"csch" ,1,1,1,1,0,0,(void *)&pplfunc_csch , "csch(z)", "\\mathrm{csch}@<@1@>", "csch(x) returns the hyperbolic cosecant of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"cosech" ,1,1,1,1,0,0,(void *)&pplfunc_csch , "cosech(z)", "\\mathrm{cosech}@<@1@>", "cosech(x) returns the hyperbolic cosecant of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"deepcopy" ,1,1,0,0,0,0,(void *)&pplfunc_deepcopy , "deepcopy(x)", "\\mathrm{deepcopy}@<@1@>", "deepcopy(x) returns a deep copy of the data structure x, copying also any nested data structures"); ppl_addSystemFunc(d,"degrees" ,1,1,1,1,1,0,(void *)&pplfunc_degrees , "degrees(x)", "\\mathrm{degrees}@<@1@>", "degrees(x) converts angles measured in radians into degrees"); ppl_addMagicFunction(d, "diff_d", 2, "diff_d...(e,min,max)", "\\left.\\frac{\\mathrm{d}}{\\mathrm{d}@?}\\right|_{@?=@2}@<@1@>", "diff_d(e,x,step) numerically differentiates an expression e wrt at x, using a step size of step. can be any variable name"); ppl_addSystemFunc(d,"ellipticintK" ,1,1,1,1,1,1,(void *)&pplfunc_ellK , "ellipticintK(k)", "\\mathrm{ellipticintK}@<@1@>", "ellipticintK(k) evaluates the complete elliptic integral K(k)"); ppl_addSystemFunc(d,"ellipticintE" ,1,1,1,1,1,1,(void *)&pplfunc_ellE , "ellipticintE(k)", "\\mathrm{ellipticintE}@<@1@>", "ellipticintE(k) evaluates the complete elliptic integral E(k)"); ppl_addSystemFunc(d,"ellipticintP" ,2,2,1,1,1,1,(void *)&pplfunc_ellP , "ellipticintP(k,n)", "\\mathrm{ellipticintP}@<@1,@2@>", "ellipticintP(k,n) evaluates the complete elliptic integral P(k,n)"); ppl_addSystemFunc(d,"erf" ,1,1,1,1,1,1,(void *)&pplfunc_erf , "erf(x)", "\\mathrm{erf}@<@1@>", "erf(x) evaluates the error function at x"); ppl_addSystemFunc(d,"erfc" ,1,1,1,1,1,1,(void *)&pplfunc_erfc , "erfc(x)", "\\mathrm{erfc}@<@1@>", "erfc(x) evaluates the complimentary error function at x"); ppl_addSystemFunc(d,"eval" ,1,1,0,0,0,0,(void *)&pplfunc_eval , "eval(s)", "\\mathrm{eval}@<@0@>", "eval(s) evaluates the string expression s and returns the result"); ppl_addSystemFunc(d,"exp" ,1,1,1,1,0,0,(void *)&pplfunc_exp , "exp(z)", "\\mathrm{exp}@<@1@>", "exp(x) returns e to the power of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"expm1" ,1,1,1,1,0,0,(void *)&pplfunc_expm1 , "expm1(x)", "\\mathrm{expm1}@<@1@>", "expm1(x) accurately evaluates exp(x)-1"); ppl_addSystemFunc(d,"expint" ,2,2,1,1,1,1,(void *)&pplfunc_expint , "expint(n,x)", "\\mathrm{expint}@<@1,@2@>", "expint(n,x) evaluates the integral of exp(-xt)/t**n between one and infinity"); ppl_addSystemFunc(d,"factors" ,1,1,1,1,1,1,(void *)&pplfunc_factors , "factors(x)", "\\mathrm{factors}@<@1@>", "factors(x) returns a list of the factors of the integer x"); ppl_addSystemFunc(d,"finite" ,1,1,1,0,0,0,(void *)&pplfunc_finite , "finite(z)", "\\mathrm{finite}@<@1@>", "finite(x) returns true if x is a finite number, and false otherwise"); ppl_addSystemFunc(d,"floor" ,1,1,1,1,1,1,(void *)&pplfunc_floor , "floor(x)", "\\mathrm{floor}@<@1@>", "floor(x) returns the largest integer value smaller than or equal to x"); ppl_addSystemFunc(d,"gamma" ,1,1,1,1,1,1,(void *)&pplfunc_gamma , "gamma(x)", "\\mathrm{\\Gamma}@<@1@>", "gamma(x) evaluates the gamma function at x"); ppl_addSystemFunc(d,"gcd" ,2,1e9,1,1,1,1,(void *)&pplfunc_gcd , "gcd(x,...)", "\\mathrm{gcd}@<@0@>", "gcd(x,...) returns the greatest common divisor (a.k.a. highest common factor) of its arguments, which should be dimensionless non-zero integers"); ppl_addSystemFunc(d,"globals" ,0,0,1,1,1,1,(void *)&pplfunc_globals , "globals()", "\\mathrm{globals}@<@>", "globals() returns a dictionary of all currently-defined global variables"); ppl_addSystemFunc(d,"gray" ,1,1,1,1,1,1,(void *)&pplfunc_gray , "gray(x)", "\\mathrm{gray}@<@1@>", "gray(x) returns a shade of gray with brightness x in the range 0-1"); ppl_addSystemFunc(d,"grey" ,1,1,1,1,1,1,(void *)&pplfunc_gray , "grey(x)", "\\mathrm{grey}@<@1@>", "grey(x) returns a shade of grey with brightness x in the range 0-1"); ppl_addSystemFunc(d,"heaviside" ,1,1,1,1,1,0,(void *)&pplfunc_heaviside , "heaviside(x)", "\\mathrm{heaviside}@<@1@>", "heaviside(x) returns the Heaviside function, defined to be one for x>=0 and zero otherwise"); ppl_addSystemFunc(d,"hcf" ,2,1e9,1,1,1,1,(void *)&pplfunc_gcd , "hcf(x,...)", "\\mathrm{hcf}@<@0@>", "hcf(x,...) returns the highest common factor (a.k.a. greatest common divisor) of its arguments, which should be dimensionless non-zero integers"); ppl_addSystemFunc(d,"hsb" ,3,3,1,1,1,1,(void *)&pplfunc_hsb , "hsb(h,s,b)", "\\mathrm{hsb}@<@1,@2,@3@>", "hsb(h,s,b) returns a color with specified hue, saturation and brightness in the range 0-1"); ppl_addSystemFunc(d,"hyperg_0F1" ,2,2,1,1,1,1,(void *)&pplfunc_hyperg_0F1 , "hyperg_0F1(c,x)", "\\mathrm{hyperg\\_}_0\\mathrm{F}_1}@<@1,@2@>", "hyperg_0F1(c,x) evaluates the hypergeometric function 0F1(c,x)"); ppl_addSystemFunc(d,"hyperg_1F1" ,3,3,1,1,1,1,(void *)&pplfunc_hyperg_1F1 , "hyperg_1F1(a,b,x)", "\\mathrm{hyperg\\_}_1\\mathrm{F}_1}@<@1,@2,@3@>", "hyperg_1F1(a,b,x) evaluates the confluent hypergeometric function 1F1(a,b,x)"); ppl_addSystemFunc(d,"hyperg_2F0" ,3,3,1,1,1,1,(void *)&pplfunc_hyperg_2F0 , "hyperg_2F0(a,b,x)", "\\mathrm{hyperg\\_}_2\\mathrm{F}_0}@<@1,@2,@3@>", "hyperg_2F0(a,b,x) evaluates the hypergeometric function 2F0(a,b,x)"); ppl_addSystemFunc(d,"hyperg_2F1" ,4,4,1,1,1,1,(void *)&pplfunc_hyperg_2F1 , "hyperg_2F1(a,b,c,x)", "\\mathrm{hyperg\\_}_2\\mathrm{F}_1}@<@1,@2,@3,@4@>", "hyperg_2F1(a,b,c,x) evaluates the Gauss hypergeometric function 2F1(a,b,c,x)"); ppl_addSystemFunc(d,"hyperg_U" ,3,3,1,1,1,1,(void *)&pplfunc_hyperg_U , "hyperg_U(a,b,x)", "\\mathrm{hyperg\\_U}@<@1,@2,@3@>", "hyperg_U(a,b,x) evaluates the confluent hypergeometric function U(m,n,x)"); ppl_addSystemFunc(d,"hypot" ,0,1e9,1,1,0,0,(void *)&pplfunc_hypot , "hypot(x,...)", "\\mathrm{hypot}@<@0@>", "hypot(x,...) returns the quadrature sum of its arguments"); ppl_addSystemFunc(d,"Im" ,1,1,1,1,0,0,(void *)&pplfunc_imag , "Im(z)", "\\mathrm{Im}@<@1@>", "Im(z) returns the magnitude of the imaginary part of z"); ppl_addMagicFunction(d, "int_d", 3, "int_d...(e,min,max)", "\\int_{@2}^{@3}@<@1@>\\,\\mathrm{d}@?", "int_d(e,min,max) numerically integrates an expression e wrt between min and max"); ppl_addSystemFunc(d,"jacobi_cn" ,2,2,1,1,1,1,(void *)&pplfunc_jacobi_cn , "jacobi_cn(u,m)", "\\mathrm{jacobi\\_cn}@<@1,@2@>", "jacobi_cn(u,m) returns the Jacobi elliptic function cn(u,m)"); ppl_addSystemFunc(d,"jacobi_dn" ,2,2,1,1,1,1,(void *)&pplfunc_jacobi_dn , "jacobi_dn(u,m)", "\\mathrm{jacobi\\_dn}@<@1,@2@>", "jacobi_dn(u,m) returns the Jacobi elliptic function dn(u,m)"); ppl_addSystemFunc(d,"jacobi_sn" ,2,2,1,1,1,1,(void *)&pplfunc_jacobi_sn , "jacobi_sn(u,m)", "\\mathrm{jacobi\\_sn}@<@1,@2@>", "jacobi_sn(u,m) returns the Jacobi elliptic function sn(u,m)"); ppl_addSystemFunc(d,"lambert_W0" ,1,1,1,1,1,1,(void *)&pplfunc_lambert_W0 , "lambert_W0(x)", "\\mathrm{lambert\\_W0}@<@1@>", "lambert_W0(x) returns the principal branch of the Lambert W function"); ppl_addSystemFunc(d,"lambert_W1" ,1,1,1,1,1,1,(void *)&pplfunc_lambert_W1 , "lambert_W1(x)", "\\mathrm{lambert\\_W1}@<@1@>", "lambert_W1(x) returns the secondary branch of the Lambert W function"); ppl_addSystemFunc(d,"lcm" ,2,1e9,1,1,1,1,(void *)&pplfunc_lcm , "lcm(x,...)", "\\mathrm{lcm}@<@0@>", "lcm(x,...) returns the lowest common multiple of its arguments, which should be dimensionless positive integers"); ppl_addSystemFunc(d,"ldexp" ,2,2,1,1,1,1,(void *)&pplfunc_ldexp , "ldexp(x,y)", "\\mathrm{ldexp}@<@1,@2@>", "ldexp(x,y) returns x times 2 to the power of an integer y"); ppl_addSystemFunc(d,"legendreP" ,2,2,1,1,1,1,(void *)&pplfunc_legendreP , "legendreP(l,x)", "\\mathrm{legendreP}@<@1,@2@>", "legendreP(l,x) evaluates the lth Legendre polynomial at x"); ppl_addSystemFunc(d,"legendreQ" ,2,2,1,1,1,1,(void *)&pplfunc_legendreQ , "legendreQ(l,x)", "\\mathrm{legendreQ}@<@1,@2@>", "legendreQ(l,x) evaluates the lth Legendre function at x"); ppl_addSystemFunc(d,"len" ,1,1,0,0,0,0,(void *)&pplfunc_len , "len(x)", "\\mathrm{len}@<@1@>", "len(x) returns the length of the object x. The may be the length of a string, or the number of entries in a compound data type"); ppl_addSystemFunc(d,"locals" ,0,0,1,1,1,1,(void *)&pplfunc_locals , "locals()", "\\mathrm{locals}@<@>", "locals() returns a dictionary of all currently-defined local variables"); ppl_addSystemFunc(d,"log" ,1,1,1,1,0,1,(void *)&pplfunc_log , "log(z)", "\\mathrm{log}@<@1@>", "log(x) returns the natural logarithm of x"); ppl_addSystemFunc(d,"log10" ,1,1,1,1,0,1,(void *)&pplfunc_log10 , "log10(z)", "\\mathrm{log_{10}}@<@1@>", "log10(x) returns the logarithm of x to base 10"); ppl_addSystemFunc(d,"logn" ,2,2,1,1,0,1,(void *)&pplfunc_logn , "logn(z,n)", "\\mathrm{log}_n@<@1@>", "logn(x,n) returns the logarithm of x to base n"); ppl_addSystemFunc(d,"ln" ,1,1,1,1,0,1,(void *)&pplfunc_log , "ln(z)", "\\mathrm{ln}@<@1@>", "ln(x) is an alias for log(x): it returns the natural logarithm of x"); ppl_addSystemFunc(d,"lrange" ,1,3,1,1,1,0,(void *)&pplfunc_lrange , "lrange([f],l,[s])", "\\mathrm{lrange@<@0@>", "lrange([f],l,[s]) returns a vector of numbers between f and l with uniform multiplicative spacing s"); ppl_addSystemFunc(d,"max" ,0,1e9,0,0,0,0,(void *)&pplfunc_max , "max(x,...)", "\\mathrm{max}@<@0@>", "max(x,...) returns the greatest of its arguments"); ppl_addSystemFunc(d,"min" ,0,1e9,0,0,0,0,(void *)&pplfunc_min , "min(x,...)", "\\mathrm{min}@<@0@>", "min(x,...) returns the least of its arguments"); ppl_addSystemFunc(d,"mod" ,2,2,1,1,1,0,(void *)&pplfunc_mod , "mod(x,y)", "\\mathrm{mod}@<@1,@2@>", "mod(x,y) returns the remainder of x/y"); ppl_addSystemFunc(d,"open" ,1,2,0,0,0,0,(void *)&pplfunc_open , "open(x[,y])", "\\mathrm{open}@<@0@>", "open(x[,y]) opens the file x with access mode y, and returns a file object"); ppl_addSystemFunc(d,"ord" ,1,1,0,0,0,0,(void *)&pplfunc_ord , "ord(s)", "\\mathrm{ord}@<@1@>", "ord(s) returns the ASCII code of the first character of the string s"); ppl_addSystemFunc(d,"ordinal" ,1,1,1,1,1,1,(void *)&pplfunc_ordinal , "ordinal(n)", "\\mathrm{ordinal}@<@1@>", "ordinal(n) returns the ordinal string, e.g. '1st', '2nd', '3rd' for the positive integer n"); ppl_addSystemFunc(d,"pow" ,2,2,1,1,0,0,(void *)&pplfunc_pow , "pow(x,y)", "\\mathrm{pow}@<@1,@2@>", "pow(x,y) returns x to the power of y"); ppl_addSystemFunc(d,"prime" ,1,1,1,1,1,1,(void *)&pplfunc_prime , "prime(x)", "\\mathrm{prime}@<@1@>", "prime(x) returns true if floor(x) is a prime number; false otherwise"); ppl_addSystemFunc(d,"primeFactors" ,1,1,1,1,1,1,(void *)&pplfunc_primefactors, "primeFactors(x)", "\\mathrm{primeFactors}@<@1@>", "primeFactors(x) returns a list of the prime factors of the integer x"); ppl_addSystemFunc(d,"radians" ,1,1,1,1,1,0,(void *)&pplfunc_radians , "radians(x)", "\\mathrm{radians}@<@1@>", "radians(x) converts angles measured in degrees into radians"); ppl_addSystemFunc(d,"raise" ,2,2,0,0,0,0,(void *)&pplfunc_raise , "raise(e,s)", "\\mathrm{raise@<@1,@2@>", "raise(e,s) raises the exception e, with error string s"); ppl_addSystemFunc(d,"range" ,1,3,1,1,1,0,(void *)&pplfunc_range , "range([f],l,[s])", "\\mathrm{range@<@0@>", "range([f],l,[s]) returns a vector of uniformly-spaced numbers between f and l, with stepsize s"); ppl_addSystemFunc(d,"Re" ,1,1,1,1,0,0,(void *)&pplfunc_real , "Re(z)", "\\mathrm{Re}@<@1@>", "Re(z) returns the magnitude of the real part of z"); ppl_addSystemFunc(d,"rgb" ,3,3,1,1,1,1,(void *)&pplfunc_rgb , "rgb(r,g,b)", "\\mathrm{rgb}@<@1,@2,@3@>", "rgb(r,g,b) returns a color with specified RGB components in the range 0-1"); ppl_addSystemFunc(d,"romanNumeral" ,1,1,1,1,1,1,(void *)&pplfunc_romanNum , "romanNum(n)", "\\mathrm{romanNum}@<@1@>", "romanNum(n) returns the Roman numeral representing the number n"); ppl_addSystemFunc(d,"root" ,2,2,1,1,0,1,(void *)&pplfunc_root , "root(z,n)", "\\mathrm{root}@<@1,@2@>", "root(z,n) returns the nth root of z"); ppl_addSystemFunc(d,"round" ,1,1,1,1,1,1,(void *)&pplfunc_round , "round(x)", "\\mathrm{round}@<@1@>", "round(x) returns the nearest integer value to x. If x is exactly half way between integers, it is rounded away from zero"); ppl_addSystemFunc(d,"sec" ,1,1,1,1,0,0,(void *)&pplfunc_sec , "sec(z)", "\\mathrm{sec}@<@1@>", "sec(x) returns the secant of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"sech" ,1,1,1,1,0,0,(void *)&pplfunc_sech , "sech(z)", "\\mathrm{sech}@<@1@>", "sech(x) returns the hyperbolic secant of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"sgn" ,1,1,1,1,1,1,(void *)&pplfunc_sgn , "sgn(x)", "\\mathrm{sgn}@<@1@>", "sgn(x) returns 1 if x is greater than zero, -1 if x is less than zero, and 0 if x equals zero"); ppl_addSystemFunc(d,"sin" ,1,1,1,1,0,0,(void *)&pplfunc_sin , "sin(z)", "\\mathrm{sin}@<@1@>", "sin(x) returns the sine of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"sinc" ,1,1,1,1,0,0,(void *)&pplfunc_sinc , "sinc(z)", "\\mathrm{sinc}@<@1@>", "sinc(x) returns the function sin(pi*x)/(pi*x). If x is dimensionless, it is assumed to be measured in radians. The output is dimensionless"); ppl_addSystemFunc(d,"sinh" ,1,1,1,1,0,0,(void *)&pplfunc_sinh , "sinh(z)", "\\mathrm{sinh}@<@1@>", "sinh(x) returns the hyperbolic sine of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"sqrt" ,1,1,1,1,0,0,(void *)&pplfunc_sqrt , "sqrt(z)", "\\sqrt{@1}", "sqrt(x) returns the square root of x"); ppl_addSystemFunc(d,"sum" ,0,1e9,0,0,0,0,(void *)&pplfunc_sum , "sum(...)", "\\mathrm{sum}@<@0@>", "sum(...) returns the sum of its arguments"); ppl_addSystemFunc(d,"tan" ,1,1,1,1,0,0,(void *)&pplfunc_tan , "tan(z)", "\\mathrm{tan}@<@1@>", "tan(x) returns the tangent of x. If x is dimensionless, it is assumed to be measured in radians"); ppl_addSystemFunc(d,"tanh" ,1,1,1,1,0,0,(void *)&pplfunc_tanh , "tanh(z)", "\\mathrm{tanh}@<@1@>", "tanh(x) returns the hyperbolic tangent of x. x may either be a dimensionless number or may have units of angle"); ppl_addSystemFunc(d,"texify" ,1,1,0,0,0,0,(void *)&pplfunc_texify , "texify(e)", "\\mathrm{texify}@<@0@>", "texify(str) converts an algebraic expression into a LaTeX representation"); ppl_addSystemFunc(d,"texifyText" ,1,1,0,0,0,0,(void *)&pplfunc_texifyText , "texifyText(s)", "\\mathrm{texifyText}@<@0@>", "texifyText(str) converts a text string into a LaTeX representation"); ppl_addSystemFunc(d,"tophat" ,2,2,1,1,1,0,(void *)&pplfunc_tophat , "tophat(x,sigma)", "\\mathrm{tophat}@<@1,@2@>", "tophat(x,sigma) returns one if |x| <= |sigma|, and zero otherwise"); ppl_addSystemFunc(d,"typeOf" ,1,1,0,0,0,0,(void *)&pplfunc_typeOf , "typeOf(x)", "\\mathrm{typeOf}@<@1@>", "typeof(x) returns the type of the object x"); ppl_addMagicFunction(d, "unit", 1, "unit(...)", "\\mathrm{unit}@<@0@>", "unit(...) multiplies a number by a physical unit"); ppl_addSystemFunc(d,"zernike" ,4,4,1,1,1,0,(void *)&pplfunc_zernike , "zernike(n,m,r,phi)", "\\mathrm{zernike}@<@1,@2,@3,@4@>", "zernike(n,m,r,phi) evaluates the (n,m)th Zernike polynomial at radius r and position angle phi"); ppl_addSystemFunc(d,"zernikeR" ,3,3,1,1,1,1,(void *)&pplfunc_zernikeR , "zernikeR(n,m,r)", "\\mathrm{zernikeR}@<@1,@2,@3@>", "zernikeR(n,m,r) evaluates the (n,m)th radial Zernike polynomial at radius r"); ppl_addSystemFunc(d,"zeta" ,1,1,1,1,0,1,(void *)&pplfunc_zeta , "zeta(z)", "\\zeta@<@1@>", "zeta(x) evaluates the Riemann zeta function at x"); // Shortcuts to module, vector and matrix pplObjCpy(&v, &pplObjPrototypes[PPLOBJ_MAT], 0, 1, 1); ppl_dictAppendCpy(d, pplObjTypeNames[PPLOBJ_MAT], (void *)&v, sizeof(v)); pplObjCpy(&v, &pplObjPrototypes[PPLOBJ_MOD], 0, 1, 1); ppl_dictAppendCpy(d, pplObjTypeNames[PPLOBJ_MOD], (void *)&v, sizeof(v)); pplObjCpy(&v, &pplObjPrototypes[PPLOBJ_VEC], 0, 1, 1); ppl_dictAppendCpy(d, pplObjTypeNames[PPLOBJ_VEC], (void *)&v, sizeof(v)); // Ast module ppl_dictAppendCpy(d, "ast", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"Lcdm_age" ,3,3,1,1,1,0,(void *)&pplfunc_Lcdm_age , "Lcdm_age(H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_age}@<@1,@2,@3@>", "Lcdm_age(H0,w_m,w_l) returns the current age of the Universe in an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_angscale",4,4,1,1,1,0,(void *)&pplfunc_Lcdm_angscale, "Lcdm_age(z,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_angscale}@<@1,@2,@3,@4@>", "Lcdm_angscale(z,H0,w_m,w_l) returns the angular scale of the sky in distance per unit angle for an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_DA" ,4,4,1,1,1,0,(void *)&pplfunc_Lcdm_DA , "Lcdm_DA(z,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_D_A}@<@1,@2,@3,@4@>", "Lcdm_DA(z,H0,w_m,w_l) returns the angular size distance corresponding to redshift z in an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_DL" ,4,4,1,1,1,0,(void *)&pplfunc_Lcdm_DL , "Lcdm_DL(z,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_D_L}@<@1,@2,@3,@4@>", "Lcdm_DL(z,H0,w_m,w_l) returns the luminosity distance corresponding to redshift z in an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_DM" ,4,4,1,1,1,0,(void *)&pplfunc_Lcdm_DM , "Lcdm_DM(z,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_D_M}@<@1,@2,@3,@4@>", "Lcdm_DM(z,H0,w_m,w_l) returns the comoving distance corresponding to redshift z in an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_t" ,4,4,1,1,1,0,(void *)&pplfunc_Lcdm_t , "Lcdm_t(z,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_t}@<@1,@2,@3,@4@>", "Lcdm_t(z,H0,w_m,w_l) returns the lookback time corresponding to redshift z in an L_CDM cosmology"); ppl_addSystemFunc(d2,"Lcdm_z" ,4,4,1,1,1,0,(void *)&pplfunc_Lcdm_z , "Lcdm_z(t,H0,w_m,w_l)", "\\mathrm{\\Lambda_{CDM}\\_z}@<@1,@2,@3,@4@>", "Lcdm_z(t,H0,w_m,w_l) returns the redshift corresponding to a lookback time t in an L_CDM cosmology"); ppl_addSystemFunc(d2,"moonPhase" ,1,1,0,1,1,1,(void *)&pplfunc_moonphase , "moonPhase(d)" , "\\mathrm{moonPhase}@<@1@>", "moonPhase(d) returns the phase of the Moon at time d, specified either as a date object or a Unix time"); ppl_addSystemFunc(d2,"siderealTime" ,1,1,0,1,1,1,(void *)&pplfunc_sidereal_time, "siderealTime(d)" , "\\mathrm{siderealTime}@<@1@>", "siderealTime(d) returns the sidereal time at Greenwich at time d, specified either as a date object or a Unix time"); // Fractals module ppl_dictAppendCpy(d, "fractals", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"julia" ,3,3,1,1,0,1,(void *)&pplfunc_julia ,"julia(z,cz,MaxIter)", "\\mathrm{julia}@<@1,@2,@3@>", "julia(z,cz,MaxIter) returns the number of iterations required before the Julia set iterator diverges outside the circle |z'|<2"); ppl_addSystemFunc(d2,"mandelbrot" ,2,2,1,1,0,1,(void *)&pplfunc_mandelbrot ,"mandelbrot(z,MaxIter)", "\\mathrm{mandelbrot}@<@1,@2@>", "mandelbrot(z,MaxIter) returns the number of iterations required before the Mandelbrot set iterator diverges outside the circle |z'|<2"); // Stats module ppl_dictAppendCpy(d, "stats", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"binomialPDF" ,3,3,1,1,1,1,(void *)&pplfunc_binomialPDF , "binomialPDF(k,p,n)", "\\mathrm{binomialPDF}@<@1,@2,@3@>", "binomialPDF(k,p,n) evaulates the probability of getting k successes out of n trials in a binomial distribution with success probability p"); ppl_addSystemFunc(d2,"binomialCDF" ,3,3,1,1,1,1,(void *)&pplfunc_binomialCDF , "binomialCDF(k,p,n)", "\\mathrm{binomialCDF}@<@1,@2,@3@>", "binomialCDF(k,p,n) evaulates the probability of getting fewer than or exactly k successes out of n trials in a binomial distribution with success probability p"); ppl_addSystemFunc(d2,"chisqPDF" ,2,2,1,1,1,1,(void *)&pplfunc_chisqPDF , "chisqPDF(x,nu)", "\\mathrm{\\chi^2 PDF}@<@1,@2@>", "chisqPDF(x,nu) returns the probability density at x in a chi-squared distribution with nu degrees of freedom"); ppl_addSystemFunc(d2,"chisqCDF" ,2,2,1,1,1,1,(void *)&pplfunc_chisqCDF , "chisqCDF(x,nu)", "\\mathrm{\\chi^2 CDF}@<@1,@2@>", "chisqCDF(x,nu) returns the cumulative probability density at x in a chi-squared distribution with nu degrees of freedom"); ppl_addSystemFunc(d2,"chisqCDFi" ,2,2,1,1,1,1,(void *)&pplfunc_chisqCDFi , "chisqCDFi(P,nu)", "\\mathrm{\\chi^2 CDFi}@<@1,@2@>", "chisqCDFi(P,nu) returns the point x at which the cumulative probability density in a chi-squared distribution with nu degrees of freedom is P"); ppl_addSystemFunc(d2,"gaussianPDF" ,2,2,1,1,1,0,(void *)&pplfunc_gaussianPDF , "gaussianPDF(x,sigma)", "\\mathrm{gaussianPDF}@<@1,@2@>", "gaussianPDF(x,sigma) evaluates the Gaussian probability density function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"gaussianCDF" ,2,2,1,1,1,0,(void *)&pplfunc_gaussianCDF , "gaussianCDF(x,sigma)", "\\mathrm{gaussianCDF}@<@1,@2@>", "gaussianCDF(x,sigma) evaluates the Gaussian cumulative distribution function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"gaussianCDFi" ,2,2,1,1,1,0,(void *)&pplfunc_gaussianCDFi, "gaussianCDFi(x,sigma)", "\\mathrm{gaussianCDFi}@<@1,@2@>", "gaussianCDFi(x,sigma) evaluates the inverse Gaussian cumulative distribution function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"lognormalPDF" ,3,3,1,1,1,0,(void *)&pplfunc_lognormalPDF, "lognormalPDF(x,zeta,sigma)", "\\mathrm{lognormalPDF}@<@1,@2,@3@>", "lognormalPDF(x,zeta,sigma) evaluates the log normal probability density function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"lognormalCDF" ,3,3,1,1,1,0,(void *)&pplfunc_lognormalCDF, "lognormalCDF(x,zeta,sigma)", "\\mathrm{lognormalCDF}@<@1,@2,@3@>", "lognormalCDF(x,zeta,sigma) evaluates the log normal cumulative distribution function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"lognormalCDFi" ,3,3,1,1,1,0,(void *)&pplfunc_lognormalCDFi,"lognormalCDFi(x,zeta,sigma)", "\\mathrm{lognormalCDFi}@<@1,@2,@3@>", "lognormalCDFi(x,zeta,sigma) evaluates the inverse log normal cumulative distribution function of standard deviation sigma at x"); ppl_addSystemFunc(d2,"poissonPDF" ,2,2,1,1,1,1,(void *)&pplfunc_poissonPDF , "poissonPDF(x,mu)", "\\mathrm{poissonPDF}@<@1,@2@>", "poissonPDF(x,mu) returns the probability of getting x from a Poisson distribution with mean mu"); ppl_addSystemFunc(d2,"poissonCDF" ,2,2,1,1,1,1,(void *)&pplfunc_poissonCDF , "poissonCDF(x,mu)", "\\mathrm{poissonCDF}@<@1,@2@>", "poissonCDF(x,mu) returns the probability of getting <= x from a Poisson distribution with mean mu"); ppl_addSystemFunc(d2,"tdistPDF" ,2,2,1,1,1,1,(void *)&pplfunc_tdistPDF , "tdistPDF(x,nu)", "\\mathrm{tdistPDF}@<@1,@2@>", "tdistPDF(x,nu) returns the probability density at x in a t-distribution with nu degrees of freedom"); ppl_addSystemFunc(d2,"tdistCDF" ,2,2,1,1,1,1,(void *)&pplfunc_tdistCDF , "tdistCDF(x,nu)", "\\mathrm{tdistCDF}@<@1,@2@>", "tdistCDF(x,nu) returns the cumulative probability density at x in a t-distribution with nu degrees of freedom"); ppl_addSystemFunc(d2,"tdistCDFi" ,2,2,1,1,1,1,(void *)&pplfunc_tdistCDFi , "tdistCDFi(P,nu)", "\\mathrm{tdistCDFi}@<@1,@2@>", "tdistCDFi(P,nu) returns the point x at which the cumulative probability density in a t-distribution with nu degrees of freedom is P"); // Random module ppl_dictAppendCpy(d , "random", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"random" ,0,0,1,1,1,1,(void *)&pplfunc_frandom , "random()", "\\mathrm{random}@<@>", "random() returns a random number between 0 and 1"); ppl_addSystemFunc(d2,"binomial" ,2,2,1,1,1,1,(void *)&pplfunc_frandombin , "binomial(p,n)", "\\mathrm{binomial}@<@1,@2@>", "binomial(p,n) returns a random sample from a binomial distribution with n independent trials and a success probability p"); ppl_addSystemFunc(d2,"chisq" ,1,1,1,1,1,1,(void *)&pplfunc_frandomcs , "chisq(nu)", "\\mathrm{\\chi^2}@<@1@>", "chisq(nu) returns a random sample from a chi-squared distribution with nu degrees of freedom"); ppl_addSystemFunc(d2,"gaussian" ,1,1,1,1,1,0,(void *)&pplfunc_frandomg , "gaussian(sigma)", "\\mathrm{gaussian}@<@1@>", "gaussian(sigma) returns a random sample from a Gaussian (normal) distribution of standard deviation sigma"); ppl_addSystemFunc(d2,"lognormal" ,2,2,1,1,1,0,(void *)&pplfunc_frandomln , "lognormal(zeta,sigma)", "\\mathrm{lognormal}@<@1,@2@>", "lognormal(zeta,sigma) returns a random sample from the log normal distribution centred on zeta, and of width sigma"); ppl_addSystemFunc(d2,"poisson" ,1,1,1,1,1,1,(void *)&pplfunc_frandomp , "poisson(n)", "\\mathrm{poisson}@<@1@>", "poisson(n) returns a random integer from a Poisson distribution with mean n"); ppl_addSystemFunc(d2,"tdist" ,1,1,1,1,1,1,(void *)&pplfunc_frandomt , "tdist(nu)", "\\mathrm{tdist}@<@1@>", "tdist(nu) returns a random sample from a t-distribution with nu degrees of freedom"); // Time module ppl_dictAppendCpy(d , "time", pplObjModule(&m,1,1,1) , sizeof(v)); d2 = (dict *)m.auxil; ppl_addSystemFunc(d2,"fromCalendar" ,6,7,0,0,0,0,(void *)&pplfunc_timefromCalendar, "fromCalendar(year,month,day,hour,min,sec)", "\\mathrm{fromCalendar@<@1@>", "fromCalendar(year,month,day,hour,min,sec) creates a date object from the specified calendar date. See also 'set calendar'"); ppl_addSystemFunc(d2,"fromJD" ,1,1,1,1,1,1,(void *)&pplfunc_timefromJD , "fromJD(t)", "\\mathrm{fromJD}@<@1@>", "fromJD(t) creates a date object from the specified Julian date"); ppl_addSystemFunc(d2,"fromMJD" ,1,1,1,1,1,1,(void *)&pplfunc_timefromMJD , "fromMJD(t)", "\\mathrm{fromMJD}@<@1@>", "fromMJD(t) creates a date object from the specified modified Julian date"); ppl_addSystemFunc(d2,"fromUnix" ,1,1,1,1,1,1,(void *)&pplfunc_timefromUnix, "fromUnix(t)", "\\mathrm{fromUnix}@<@1@>", "fromUnix(t) creates a date object from the specified unix time"); ppl_addSystemFunc(d2,"interval" ,2,2,0,0,0,0,(void *)&pplfunc_timeInterval, "interval(t2,t1)", "\\mathrm{interval}@<@1,@2@>", "interval(t2,t1) returns the numerical time interval between date objects t1 and t2"); ppl_addSystemFunc(d2,"intervalStr" ,2,3,0,0,0,0,(void *)&pplfunc_timeIntervalStr, "interval(t2,t1,)", "\\mathrm{intervalStr}@<@0@>", "intervalStr(t2,t1,) returns a string representation of the time interval between date objects t1 and t2; a format string may optionally be supplied"); ppl_addSystemFunc(d2,"now" ,0,0,1,1,1,1,(void *)&pplfunc_timenow , "now()", "\\mathrm{now}@<@>", "now() returns a date object representing the current time"); ppl_addSystemFunc(d2,"sleep" ,1,1,1,1,1,0,(void *)&pplfunc_sleep , "sleep(t)", "\\mathrm{sleep}@<@1@>", "sleep(t) sleeps for t seconds, or for time period t if it has dimensions of time"); ppl_addSystemFunc(d2,"sleepUntil" ,1,1,0,0,0,0,(void *)&pplfunc_sleepUntil , "sleepUntil(d)", "\\mathrm{sleepUntil}@<@1@>", "sleepUntil(d) sleeps until the specified date and time. Its argument should be a date object"); ppl_addSystemFunc(d2,"string" ,1,3,0,0,0,0,(void *)&pplfunc_timestring , "string(t,)", "\\mathrm{string}@<@0@>", "string(t,) returns a string representation of the date object t; a format string may optionally be supplied"); } return; } pyxplot-0.9.2/src/defaultObjs/modulePhy.c0000664000175000017500000000574012026340554016775 0ustar dcf21dcf21// modulePhy.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: modulePhy.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/modulePhy.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" void pplfunc_planck_Bv (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Bv(nu,T)"; int i; pplObj kelvin; CHECK_DIMLESS_OR_HAS_UNIT(in[0], "first", "a frequency", UNIT_TIME, -1); CHECK_DIMLESS_OR_HAS_UNIT(in[1], "second", "a temperature", UNIT_TEMPERATURE, 1); pplObjNum(&kelvin,0,1,0); kelvin.exponent[UNIT_TEMPERATURE] = 1; kelvin.tempType = 1; ppl_uaDiv(c, &in[1], &kelvin, &kelvin, status, errType, errText); // Convert in[1] into kelvin if (*status) kelvin.real = GSL_NAN; OUTPUT.dimensionless = 0; OUTPUT.exponent[UNIT_MASS] = 1; OUTPUT.exponent[UNIT_TIME] = -2; OUTPUT.exponent[UNIT_ANGLE] = -2; OUTPUT.real = 2 * GSL_CONST_MKSA_PLANCKS_CONSTANT_H / pow(GSL_CONST_MKSA_SPEED_OF_LIGHT, 2) * pow(in[0].real,3) / expm1(GSL_CONST_MKSA_PLANCKS_CONSTANT_H * in[0].real / GSL_CONST_MKSA_BOLTZMANN / kelvin.real); CHECK_OUTPUT_OKAY; } void pplfunc_planck_Bvmax(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Bvmax(T)"; int i; pplObj kelvin; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first" , "a temperature", UNIT_TEMPERATURE, 1); pplObjNum(&kelvin,0,1,0); kelvin.exponent[UNIT_TEMPERATURE] = 1; kelvin.tempType = 1; ppl_uaDiv(c, &in[0], &kelvin, &kelvin, status, errType, errText); // Convert in into kelvin if (*status) kelvin.real = GSL_NAN; OUTPUT.dimensionless = 0; OUTPUT.exponent[UNIT_TIME] = -1; OUTPUT.real = 2.821439 * GSL_CONST_MKSA_BOLTZMANN / GSL_CONST_MKSA_PLANCKS_CONSTANT_H * kelvin.real; // Wien displacement law CHECK_OUTPUT_OKAY; } pyxplot-0.9.2/src/defaultObjs/airyFuncs.h0000664000175000017500000000231212026340554016767 0ustar dcf21dcf21// airyFuncs.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: airyFuncs.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_AIRY_FUNCTIONS_H #define _PPL_AIRY_FUNCTIONS_H 1 #include void airy_ai (gsl_complex in, gsl_complex *out, int *status, char *errtext); void airy_bi (gsl_complex in, gsl_complex *out, int *status, char *errtext); void airy_ai_diff(gsl_complex in, gsl_complex *out, int *status, char *errtext); void airy_bi_diff(gsl_complex in, gsl_complex *out, int *status, char *errtext); #endif pyxplot-0.9.2/src/defaultObjs/modulePhy.h0000664000175000017500000000222212026340554016772 0ustar dcf21dcf21// modulePhy.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: modulePhy.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_PHY_H #define _PPL_MODULE_PHY_H 1 #include "coreUtils/dict.h" #include "settings/settings.h" #include "userspace/pplObj.h" void pplfunc_planck_Bv (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_planck_Bvmax(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/moduleTime.h0000664000175000017500000000400212026340554017126 0ustar dcf21dcf21// moduleTime.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleTime.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_TIME_H #define _PPL_MODULE_TIME_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_timefromCalendar(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timefromJD (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timefromMJD (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timefromUnix (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timeInterval (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timeIntervalStr (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timenow (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_timestring (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sleep (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sleepUntil (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/zetaRiemann.h0000664000175000017500000000173712026340554017313 0ustar dcf21dcf21// zetaRiemann.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: zetaRiemann.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_ZETA_RIEMANN_H #define _PPL_ZETA_RIEMANN_H 1 #include void riemann_zeta_complex(gsl_complex in, gsl_complex *out, int *status, char *errtext); #endif pyxplot-0.9.2/src/defaultObjs/moduleStats.c0000664000175000017500000001462012026340554017330 0ustar dcf21dcf21// moduleStats.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleStats.c 1287 2012-08-10 17:57:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleStats.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" void pplfunc_binomialPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "binomialPDF(k,p,n)"; CHECK_NEEDINT(in[0] , "k", "function's first argument must be"); CHECK_NEEDINT(in[2] , "n", "function's third argument must be"); OUTPUT.real = gsl_ran_binomial_pdf((unsigned int)in[0].real, in[1].real, (unsigned int)in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_binomialCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "binomialCDF(k,p,n)"; CHECK_NEEDINT(in[0] , "k", "function's first argument must be"); CHECK_NEEDINT(in[2] , "n", "function's third argument must be"); OUTPUT.real = gsl_cdf_binomial_P((unsigned int)in[0].real, in[1].real, (unsigned int)in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_chisqPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "chisqPDF(x,nu)"; OUTPUT.real = gsl_ran_chisq_pdf(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_chisqCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "chisqCDF(x,nu)"; OUTPUT.real = gsl_cdf_chisq_P(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_chisqCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "chisqCDFi(P,nu)"; OUTPUT.real = gsl_cdf_chisq_Pinv(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_gaussianPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gaussianPDF(x,sigma)"; CHECK_2INPUT_DIMMATCH; OUTPUT.real = gsl_ran_gaussian_pdf(in[0].real, in[1].real); CHECK_OUTPUT_OKAY; ppl_unitsDimInverse(&OUTPUT, &in[0]); } void pplfunc_gaussianCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gaussianCDF(x,sigma)"; CHECK_2INPUT_DIMMATCH; OUTPUT.real = gsl_cdf_gaussian_P(in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_gaussianCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gaussianCDFi(x,sigma)"; CHECK_1INPUT_DIMLESS; OUTPUT.real = gsl_cdf_gaussian_Pinv(in[0].real, in[1].real); CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, &in[1]); } void pplfunc_lognormalPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lognormalPDF(x,zeta,sigma)"; in+=2; CHECK_1INPUT_DIMLESS; in-=2; CHECK_2INPUT_DIMMATCH; OUTPUT.real = gsl_ran_lognormal_pdf(in[0].real, in[1].real, in[2].real); CHECK_OUTPUT_OKAY; ppl_unitsDimInverse(&OUTPUT, &in[0]); } void pplfunc_lognormalCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lognormalCDF(x,zeta,sigma)"; in+=2; CHECK_1INPUT_DIMLESS; in-=2; CHECK_2INPUT_DIMMATCH; OUTPUT.real = gsl_cdf_lognormal_P(in[0].real, in[1].real, in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_lognormalCDFi(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lognormalCDFi(x,zeta,sigma)"; in+=2; CHECK_1INPUT_DIMLESS; in-=2; CHECK_2INPUT_DIMMATCH; OUTPUT.real = gsl_cdf_lognormal_Pinv(in[0].real, in[1].real, in[2].real); CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, &in[1]); } void pplfunc_poissonPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "poissonPDF(x,mu)"; OUTPUT.real = gsl_ran_poisson_pdf(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_poissonCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "poissonCDF(x,mu)"; OUTPUT.real = gsl_cdf_poisson_P(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_tdistPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "tdistPDF(x,nu)"; OUTPUT.real = gsl_ran_tdist_pdf(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_tdistCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "tdistCDF(x,nu)"; OUTPUT.real = gsl_cdf_tdist_P(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_tdistCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "tdistCDFi(P,nu)"; OUTPUT.real = gsl_cdf_tdist_Pinv(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; } pyxplot-0.9.2/src/defaultObjs/moduleStats.h0000664000175000017500000000516612026340554017342 0ustar dcf21dcf21// moduleStats.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleStats.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_STATS_H #define _PPL_MODULE_STATS_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_binomialPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_binomialCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_chisqPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_chisqCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_chisqCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gaussianPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gaussianCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gaussianCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lognormalPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lognormalCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lognormalCDFi(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_poissonPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_poissonCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tdistPDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tdistCDF (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tdistCDFi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/airyFuncs.c0000664000175000017500000014435712026340554017002 0ustar dcf21dcf21// airyFuncs.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // 2009-2010 Matthew Smith // // $Id: airyFuncs.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // This file contains an implementation of the Airy functions for general // complex inputs provided courtesy of Matthew Smith. #include #include #include #include #include #include #include "defaultObjs/airyFuncs.h" #define ADDON *dp = gsl_complex_add(*dp,gsl_complex_mul(f,c)); \ *dq = gsl_complex_add(*dq,gsl_complex_mul(g,c)); \ c = gsl_complex_mul(c,zd) gsl_complex airy_series_y1(gsl_complex z) { int i; gsl_complex c,d; c = gsl_complex_mul(z,z); z = gsl_complex_mul(c,z); c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=45;i+=3) { d = gsl_complex_add(d,c); c = gsl_complex_mul(c,z); c = gsl_complex_div_real(c,((double) (i+2)*(i+3))); } return d; } gsl_complex airy_series_y1_diff(gsl_complex z) { int i; gsl_complex c,d; c = gsl_complex_mul(z,z); z = gsl_complex_mul(c,z); c = gsl_complex_div_real(c,2.0); d = GSL_COMPLEX_ZERO; for (i=0;i<=45;i+=3) { d = gsl_complex_add(d,c); c = gsl_complex_mul(c,z); c = gsl_complex_div_real(c,((double) (i+3)*(i+5))); } return d; } gsl_complex airy_series_y2(gsl_complex z) { int i; gsl_complex c,d; c = z; z = gsl_complex_mul(z,z); z = gsl_complex_mul(c,z); d = GSL_COMPLEX_ZERO; for (i=0;i<=45;i+=3) { d = gsl_complex_add(d,c); c = gsl_complex_mul(c,z); c = gsl_complex_div_real(c,((double) (i+3)*(i+4))); } return d; } gsl_complex airy_series_y2_diff(gsl_complex z) { int i; gsl_complex c,d; c = z; z = gsl_complex_mul(z,z); z = gsl_complex_mul(c,z); c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=45;i+=3) { d = gsl_complex_add(d,c); c = gsl_complex_mul(c,z); c = gsl_complex_div_real(c,((double) (i+1)*(i+3))); } return d; } void airy_lookup_ai(double mod, double arg, gsl_complex *a, gsl_complex *b, gsl_complex *z0) { int sector; if (mod>6.0) { if (mod>7.4) { sector = (int) floor(arg/0.174532925199432957); if (sector==18) sector = 17; *z0 = gsl_complex_polar(8.1,M_PI/36+((double) sector)*M_PI/18); switch (sector) { case 0: *a = gsl_complex_rect(-0.0000000177089032495511053,-0.0000000360617804208924853); *b = gsl_complex_rect(0.0000000464975585245366009,0.000000105770668476231643); break; case 1: *a = gsl_complex_rect(0.000000107088798376430528,0.0000000376445041341328399); *b = gsl_complex_rect(-0.000000291595748545378589,-0.000000146296178088760197); break; case 2: *a = gsl_complex_rect(-0.000000843663635658861037,0.0000000316868610357800936); *b = gsl_complex_rect(0.00000238658884361740962,0.000000420355834910498508); break; case 3: *a = gsl_complex_rect(0.0000140556717230700034,0.00000320688133083177304); *b = gsl_complex_rect(-0.0000358156878450108478,-0.0000205769639137091060); break; case 4: *a = gsl_complex_rect(-0.000117019946243633813,-0.000450917530047182554); *b = gsl_complex_rect(-0.000171337835527373982,0.00132059445165182243); break; case 5: *a = gsl_complex_rect(-0.0218589721702940673,-0.00523876961256432212); *b = gsl_complex_rect(0.0488267177114627294,0.0415074442551386387); break; case 6: *a = gsl_complex_rect(-1.220790901269847527,-0.236893925052021750); *b = gsl_complex_rect(2.591486551263149471,2.404933894000426047); break; case 7: *a = gsl_complex_rect(-22.514625855155557690,-55.623907050365362497); *b = gsl_complex_rect(-43.675188242376714544,164.421821533868615198); break; case 8: *a = gsl_complex_rect(1939.251073448379473234,12.475098475038992649); *b = gsl_complex_rect(-4052.273683400929841763,-3694.490657407860271925); break; case 9: *a = gsl_complex_rect(-31195.242506641886866766,11129.366826404318139359); *b = gsl_complex_rect(82915.787936565613332283,43101.341852362617253660); break; case 10: *a = gsl_complex_rect(246008.113121887508591838,-13409.753242896082955272); *b = gsl_complex_rect(-454161.417817375165755840,-524788.703881302459800912); break; case 11: *a = gsl_complex_rect(-560698.611396051473207968,-412629.256090998659764942); *b = gsl_complex_rect(-128601.959446731032061736,1955193.832628681094297427); break; case 12: *a = gsl_complex_rect(76998.112421476293620880,691893.869381105492291665); *b = gsl_complex_rect(1628946.548655847031109700,-1088969.480171653175994800); break; case 13: *a = gsl_complex_rect(134617.243527793463413968,-206344.398879070883749585); *b = gsl_complex_rect(-681561.058089277244582407,-130920.973307774865193561); break; case 14: *a = gsl_complex_rect(-25235.935653472152988056,21451.189074051074287957); *b = gsl_complex_rect(78784.750951183600305216,50256.507799831144930004); break; case 15: *a = gsl_complex_rect(958.821788780688620313,-1685.678229384048972271); *b = gsl_complex_rect(-5225.659640787960704555,-1662.126603479601054409); break; case 16: *a = gsl_complex_rect(36.914735631845878659,47.309864671438115295); *b = gsl_complex_rect(120.556938263078583107,-120.033924619755946995); break; case 17: *a = gsl_complex_rect(-0.411631872053758450,1.154133085728225467); *b = gsl_complex_rect(3.438836982285023958,1.020294784165429366); } if (arg<0.04) { *z0=gsl_complex_rect(8.3,0.0); *a=gsl_complex_rect(1.97486174966769314e-8,0.0); *b=gsl_complex_rect(-5.74753973633800903e-8,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-8.1,0.0); *a=gsl_complex_rect(-0.142908147093581424,0.0); *b=gsl_complex_rect(0.856218586328624562,0.0); } } else { sector = (int) floor(arg/0.209439510239319549); if (sector==15) sector = 14; *z0 = gsl_complex_polar(6.7,M_PI/30+((double) sector)*M_PI/15); switch (sector) { case 0: *a = gsl_complex_rect(-0.000000498013167756023292,-0.00000184854213885407739); *b = gsl_complex_rect(0.00000106141207289439112,0.00000491032321159520191); break; case 1: *a = gsl_complex_rect(0.00000336764005452339539,0.00000479272362847353000); *b = gsl_complex_rect(-0.00000683653066279643336,-0.0000137462950976495803); break; case 2: *a = gsl_complex_rect(-0.0000213017825830797453,-0.0000442950017766455178); *b = gsl_complex_rect(0.0000250377490153729240,0.000126060988405383066); break; case 3: *a = gsl_complex_rect(-0.000453121182937822238,0.000798928981097729518); *b = gsl_complex_rect(0.00182980866079213440,-0.00154339067057850096); break; case 4: *a = gsl_complex_rect(0.0174497968637443698,0.0227858328776185344); *b = gsl_complex_rect(-0.0145310120436193822,-0.0730669102254068242); break; case 5: *a = gsl_complex_rect(0.694446791856491758,0.814918881243262267); *b = gsl_complex_rect(-0.397518235624576301,-2.738120635415331876); break; case 6: *a = gsl_complex_rect(-11.764490767924425694,31.325544406980328369); *b = gsl_complex_rect(73.649566627644512546,-44.568572652297977178); break; case 7: *a = gsl_complex_rect(-407.494058366312338032,-474.534327075926538419); *b = gsl_complex_rect(-104.113703049367037165,1599.301554627228909985); break; case 8: *a = gsl_complex_rect(4356.084334264410458947,2930.518760022207682451); *b = gsl_complex_rect(-1280.027816992929934135,-13349.872276666335219657); break; case 9: *a = gsl_complex_rect(-10764.964007299631029460,-11926.966584303603583136); *b = gsl_complex_rect(-10459.124120878866095322,39615.596540039307247224); break; case 10: *a = gsl_complex_rect(4946.574049797097648430,15286.215591942850369831); *b = gsl_complex_rect(29078.550934092689266044,-28865.665458499383732925); break; case 11: *a = gsl_complex_rect(-359.861527780700026412,-5237.739069198683865596); *b = gsl_complex_rect(-12201.342452690017259261,5566.399530314013605794); break; case 12: *a = gsl_complex_rect(207.211780742055496102,590.167329379022769924); *b = gsl_complex_rect(1332.979044785335753163,-889.815847689268182778); break; case 13: *a = gsl_complex_rect(-33.011881081169634562,-5.474417285844980876); *b = gsl_complex_rect(-1.773154524678477923,86.064325647284144866); break; case 14: *a = gsl_complex_rect(-0.369525268938545475,-0.982363120132267512); *b = gsl_complex_rect(-2.640584453161403622,1.000850197648983227); } if (arg<0.04) { *z0=gsl_complex_rect(6.9,0.0); *a=gsl_complex_rect(9.78611333926603763e-7,0.0); *b=gsl_complex_rect(-2.60492608708626216e-6,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-6.7,0.0); *a=gsl_complex_rect(-0.0783124718012559192,0.0); *b=gsl_complex_rect(-0.887907965255553545,0.0); } } } else { if (mod>4.6) { sector = (int) floor(arg/0.261799387799149436); if (sector==12) sector = 11; *z0 = gsl_complex_polar(5.3,M_PI/24+((double) sector)*M_PI/12); switch (sector) { case 0: *a = gsl_complex_rect(-0.00000299476080804093545,-0.0000631787904853607215); *b = gsl_complex_rect(-0.00000215173224969956916,0.000148395647117400246); break; case 1: *a = gsl_complex_rect(-0.0000211526279135184427,0.000212253053197331656); *b = gsl_complex_rect(0.000140525421643900777,-0.000479067973173668073); break; case 2: *a = gsl_complex_rect(0.00162049409876805045,-0.00119965804791216987); *b = gsl_complex_rect(-0.00444923652903960177,0.00150378944888197446); break; case 3: *a = gsl_complex_rect(-0.0128350452818642183,-0.0357139465644490702); *b = gsl_complex_rect(-0.00820980981803076405,0.0874268449810398382); break; case 4: *a = gsl_complex_rect(-0.362782027418170725,-0.834518057823886484); *b = gsl_complex_rect(-0.329814762520317216,2.062891102183896320); break; case 5: *a = gsl_complex_rect(11.531506362296704366,-12.676590465250343557); *b = gsl_complex_rect(-38.696733591956182277,5.095298554790873631); break; case 6: *a = gsl_complex_rect(36.473947017219054415,157.956742301825197010); *b = gsl_complex_rect(210.460846217145665009,-300.356420369671554427); break; case 7: *a = gsl_complex_rect(-264.708864377609537581,-478.734565951523681485); *b = gsl_complex_rect(-560.542602601722304465,1097.894429871872581481); break; case 8: *a = gsl_complex_rect(282.241916811988637682,468.611849950767167360); *b = gsl_complex_rect(670.533293080147449217,-1034.391272631194629515); break; case 9: *a = gsl_complex_rect(-118.557772416653216305,-110.565648036298482925); *b = gsl_complex_rect(-154.886211743644654305,332.442288278282390695); break; case 10: *a = gsl_complex_rect(16.745851738821476342,-3.647478660993395055); *b = gsl_complex_rect(-14.936631106062903128,-36.055398564922105481); break; case 11: *a = gsl_complex_rect(0.565834486636532210,0.702465032137459288); *b = gsl_complex_rect(1.693217682289265054,-1.266250187624501159); } if (arg<0.04) { *z0=gsl_complex_rect(5.5,0.0); *a=gsl_complex_rect(0.0000336853119085998144,0.0); *b=gsl_complex_rect(-0.0000804633913055651434,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-5.3,0.0); *a=gsl_complex_rect(0.182567931068339499,0.0); *b=gsl_complex_rect(0.754575419947011041,0.0); } } else { sector = (int) floor(arg/0.349065850398865915); if (sector==9) sector = 8; *z0 = gsl_complex_polar(3.9,M_PI/18+((double) sector)*M_PI/9); switch (sector) { case 0: *a = gsl_complex_rect(0.000278077618161181118,-0.00136330080544352249); *b = gsl_complex_rect(-0.000785309515894828443,0.00271731738202666136); break; case 1: *a = gsl_complex_rect(-0.00431400446443127479,0.00302535550848715075); *b = gsl_complex_rect(0.00992381135829497437,-0.00384892534814174421); break; case 2: *a = gsl_complex_rect(0.0231635768410815889,0.0475722413876221875); *b = gsl_complex_rect(-0.00488612358065397538,-0.105500920047767831); break; case 3: *a = gsl_complex_rect(0.390152428728285509,0.652075853485570872); *b = gsl_complex_rect(0.0586221986844014905,-1.491459402174807467); break; case 4: *a = gsl_complex_rect(-4.926039939271872626,5.848213169295779524); *b = gsl_complex_rect(14.674847227356971188,-1.648177173542352832); break; case 5: *a = gsl_complex_rect(-6.720520194312951484,-28.240386236681307535); *b = gsl_complex_rect(-36.332727991434027176,41.793639654928228293); break; case 6: *a = gsl_complex_rect(21.097951488433551829,19.939893505140831342); *b = gsl_complex_rect(18.029950273188565088,-52.359846500154332147); break; case 7: *a = gsl_complex_rect(-7.532498177950830124,1.339745783114311969); *b = gsl_complex_rect(5.911688950003561545,13.522360346905228438); break; case 8: *a = gsl_complex_rect(-0.399255021084886709,-0.620073474688977667); *b = gsl_complex_rect(-1.356140170328659265,0.747979061496786733); } if (arg<0.04) { *z0=gsl_complex_rect(4.1,0.0); *a=gsl_complex_rect(0.000773629663781597187,0.0); *b=gsl_complex_rect(-0.00161061146122698678,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-3.9,0.0); *a=gsl_complex_rect(-0.147419905640744195,0.0); *b=gsl_complex_rect(-0.747558085535477472,0.0); } if (mod<3.2) { if (arg<0.349) { *z0=gsl_complex_rect(2.7,0.0); *a=gsl_complex_rect(0.0111985354510658809,0.0); *b=gsl_complex_rect(-0.0193255606923776375,0.0); } else if (arg<0.698) { *z0=gsl_complex_rect(2.25,1.3); *a=gsl_complex_rect(-0.0151244789566325122,-0.0263137408361838169); *b=gsl_complex_rect(0.0147456584151680829,0.0487809489452374034); } else { *z0=gsl_complex_rect(1.67,1.99); *a=gsl_complex_rect(-0.103601851239231523,-0.0262786874985897695); *b=gsl_complex_rect(0.141916105307775135,0.104258228554974092); } } } } return; } void airy_lookup_bi(double mod, double arg, gsl_complex *a, gsl_complex *b, gsl_complex *z0) { int sector; if (mod>6.0) { if (mod>7.4) { sector = (int) floor(arg/0.174532925199432957); if (sector==18) sector = 17; *z0 = gsl_complex_polar(8.1,M_PI/36+((double) sector)*M_PI/18); switch (sector) { case 0: *a = gsl_complex_rect(-558529.226580244337773619,1275393.447634993072821797); *b = gsl_complex_rect(-1732448.704914136372739047,3515097.016204972926171122); break; case 1: *a = gsl_complex_rect(439508.304244119416649424,-222781.739188122888161954); *b = gsl_complex_rect(1311419.354378659708640699,-454799.280543550765239732); break; case 2: *a = gsl_complex_rect(-65161.111802372053136092,11918.613706394351010666); *b = gsl_complex_rect(-186715.699308521217501252,-8262.073971492103717457); break; case 3: *a = gsl_complex_rect(3346.406286163157518109,-1960.858563780900306996); *b = gsl_complex_rect(10713.234583809513708257,-2346.771879133714761528); break; case 4: *a = gsl_complex_rect(16.627882073362101451,118.857941961930807513); *b = gsl_complex_rect(-88.775497062388944113,328.461965674224140787); break; case 5: *a = gsl_complex_rect(-1.872339171752590886,1.609244243294068826); *b = gsl_complex_rect(-6.935027712174787454,1.622807859701515936); break; case 6: *a = gsl_complex_rect(0.204271844264402619,-1.189858113961444132); *b = gsl_complex_rect(-2.531011694098641311,2.614552835893919778); break; case 7: *a = gsl_complex_rect(55.624155283403016727,-22.513727823137248870); *b = gsl_complex_rect(-164.422845362483874729,-43.672729567854732653); break; case 8: *a = gsl_complex_rect(-12.475077336782764614,1939.251053838226351319); *b = gsl_complex_rect(3694.490740019415241220,-4052.273683225588960808); break; case 9: *a = gsl_complex_rect(-11129.366827897273281854,-31195.242505853106484354); *b = gsl_complex_rect(-43101.341856916666222493,82915.787934907102151989); break; case 10: *a = gsl_complex_rect(13409.753243043921690847,246008.113121715217599676); *b = gsl_complex_rect(524788.703881953814630753,-454161.417817336962420697); break; case 11: *a = gsl_complex_rect(412629.256091004048825189,-560698.611395971303468818); *b = gsl_complex_rect(-1955193.832628867401099696,-128601.959446594329448509); break; case 12: *a = gsl_complex_rect(-691893.869381172226792260,76998.112421431541688229); *b = gsl_complex_rect(1088969.480171678410529483,1628946.548655617333379424); break; case 13: *a = gsl_complex_rect(206344.398879294011493429,134617.243527751576809377); *b = gsl_complex_rect(130920.973308133627667224,-681561.058088732256420459); break; case 14: *a = gsl_complex_rect(-21451.189075480655708380,-25235.935652573606099151); *b = gsl_complex_rect(-50256.507803544482229015,78784.750948068933798276); break; case 15: *a = gsl_complex_rect(1685.678256936067861969,958.821780279498296088); *b = gsl_complex_rect(1662.126644937228196286,-5225.659569331925895489); break; case 16: *a = gsl_complex_rect(-47.310518273460555430,36.914071639720057107); *b = gsl_complex_rect(120.035541980043991109,120.554822264227655964); break; case 17: *a = gsl_complex_rect(-1.197232705740973243,-0.398846715021573711); *b = gsl_complex_rect(-1.063357695753367352,3.318117262231328193); } if (arg<0.04) { *z0=gsl_complex_rect(7.9,0.0); *a=gsl_complex_rect(907790.616061993809,0.0); *b=gsl_complex_rect(2.52192411395678168e6,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-8.1,0.0); *a=gsl_complex_rect(-0.302303309060702033,0.0); *b=gsl_complex_rect(-0.416156639540127581,0.0); } } else { sector = (int) floor(arg/0.209439510239319549); if (sector==15) sector = 14; *z0 = gsl_complex_polar(6.7,M_PI/30+((double) sector)*M_PI/15); switch (sector) { case 0: *a = gsl_complex_rect(-6718.498016141077682781,31423.076110991688451355); *b = gsl_complex_rect(-21499.862164918266666618,79075.350101438181438665); break; case 1: *a = gsl_complex_rect(4614.440624185876042327,-9431.891715788980139568); *b = gsl_complex_rect(15566.945504545861683191,-21842.629247584893125288); break; case 2: *a = gsl_complex_rect(-231.266041501962188690,1229.411601495542069767); *b = gsl_complex_rect(-1418.971457242574856197,2874.185277325368810183); break; case 3: *a = gsl_complex_rect(-51.703039071181529005,-42.493396840903517232); *b = gsl_complex_rect(-82.994675311540956918,-150.842769073588611175); break; case 4: *a = gsl_complex_rect(0.365112412527771787,-2.088477901353265809); *b = gsl_complex_rect(3.499709326677641330,-4.359576834211176093); break; case 5: *a = gsl_complex_rect(-0.807480779371119503,0.637530774755938730); *b = gsl_complex_rect(2.836355996785682733,-0.509542824443435467); break; case 6: *a = gsl_complex_rect(-31.327128164872260118,-11.765421432328388375); *b = gsl_complex_rect(44.566946721399934137,73.645063587926350648); break; case 7: *a = gsl_complex_rect(474.534334475158589384,-407.493960343336156448); *b = gsl_complex_rect(-1599.301724054870717152,-104.113509743079282063); break; case 8: *a = gsl_complex_rect(-2930.518758982007634886,4356.084322595529573272); *b = gsl_complex_rect(13349.872302253848772773,-1280.027833965680796302); break; case 9: *a = gsl_complex_rect(11926.96658528956161259918428,-10764.964003599848957277); *b = gsl_complex_rect(-39615.596546788050096839,-10459.124113435348884149); break; case 10: *a = gsl_complex_rect(-15286.215594653976618077,4946.574047093341911759); *b = gsl_complex_rect(28865.665461571287306500,29078.550924526347909082); break; case 11: *a = gsl_complex_rect(5237.739079824331170108,-359.861522847099249784); *b = gsl_complex_rect(-5566.399532219090247978,-12201.342422044205071501); break; case 12: *a = gsl_complex_rect(-590.167410569794272249,207.211725322644480679); *b = gsl_complex_rect(889.815930383603186378,1332.978801403549967315); break; case 13: *a = gsl_complex_rect(5.474431385915244585,-33.010044174399796237); *b = gsl_complex_rect(-86.069038359523344910,-1.772311102281900293); break; case 14: *a = gsl_complex_rect(1.035372887759647344,-0.347508845565481187); *b = gsl_complex_rect(-1.048748656729446018,-2.499497840255305692); } if (arg<0.04) { *z0=gsl_complex_rect(6.5,0.0); *a=gsl_complex_rect(22340.6077183969982,0.0); *b=gsl_complex_rect(56062.4958425228607,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-6.7,0.0); *a=gsl_complex_rect(0.341727738606750260,0.0); *b=gsl_complex_rect(-0.190098777163749660,0.0); } } } else { if (mod>4.6) { sector = (int) floor(arg/0.261799387799149436); if (sector==12) sector = 11; *z0 = gsl_complex_polar(5.3,M_PI/24+((double) sector)*M_PI/12); switch (sector) { case 0: *a = gsl_complex_rect(20.245426814435152207,1093.901452950321269133); *b = gsl_complex_rect(-127.006310754446323167,2462.151534334939077966); break; case 1: *a = gsl_complex_rect(-94.782225168479687982,-310.063071234672342043); *b = gsl_complex_rect(-64.171979214391714810,-730.693286151510822793); break; case 2: *a = gsl_complex_rect(32.650945030599909028,10.426612884358851175); *b = gsl_complex_rect(61.927906323985651690,47.517600332057208716); break; case 3: *a = gsl_complex_rect(0.241875100827218364,1.795374658120980130); *b = gsl_complex_rect(-1.579062021393483240,3.894637152166555444); break; case 4: *a = gsl_complex_rect(0.848001053842699526,-0.288088612147880764); *b = gsl_complex_rect(-2.136098139439629076,-0.170177215249677354); break; case 5: *a = gsl_complex_rect(12.680596901410687529,11.531963736888629092); *b = gsl_complex_rect(-5.089096040516567615,-38.689679715697793095); break; case 6: *a = gsl_complex_rect(-157.956991192304654155,36.473600536774768535); *b = gsl_complex_rect(300.356656040474685820,210.459875921654205271); break; case 7: *a = gsl_complex_rect(478.734623943236290803,-264.708751953973648146); *b = gsl_complex_rect(-1097.894574540610118117,-560.542343421189625366); break; case 8: *a = gsl_complex_rect(-468.611918316635528764,282.241810377874364329); *b = gsl_complex_rect(1034.391424753751327680,670.533038203079269517); break; case 9: *a = gsl_complex_rect(110.565823651925420443,-118.557383630953103388); *b = gsl_complex_rect(-332.443010743425606638,-154.885522498996482369); break; case 10: *a = gsl_complex_rect(3.649085781057914687,16.742153376032015515); *b = gsl_complex_rect(36.064608658094175446,-14.934786509263213107); break; case 11: *a = gsl_complex_rect(-0.760409929247544386,0.516811161929970686); *b = gsl_complex_rect(1.367896840330848079,1.549999754654686720); } if (arg<0.04) { *z0=gsl_complex_rect(5.1,0.0); *a=gsl_complex_rect(819.209658679961277,0.0); *b=gsl_complex_rect(1807.33448135136778,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-5.3,0.0); *a=gsl_complex_rect(-0.323716076748792404,0.0); *b=gsl_complex_rect(0.405556940883315528,0.0); } } else { sector = (int) floor(arg/0.349065850398865915); if (sector==9) sector = 8; *z0 = gsl_complex_polar(3.9,M_PI/18+((double) sector)*M_PI/9); switch (sector) { case 0: *a = gsl_complex_rect(16.601467107644055289,55.634582059231978874); *b = gsl_complex_rect(21.133773886433404870,108.720649997479224303); break; case 1: *a = gsl_complex_rect(-14.383389979736656919,-5.207676407906256874); *b = gsl_complex_rect(-23.765554892203047221,-17.519650020449298055); break; case 2: *a = gsl_complex_rect(-0.023884265619407301,-1.496417360513051860); *b = gsl_complex_rect(1.495423695649794520,-2.646791784258125683); break; case 3: *a = gsl_complex_rect(-0.659527602899413950,0.284591312773911343); *b = gsl_complex_rect(1.605423336516328350,-0.119224631502940362); break; case 4: *a = gsl_complex_rect(-5.858710599720740606,-4.926966004259099473); *b = gsl_complex_rect(1.634837553413198568,14.658256881741154983); break; case 5: *a = gsl_complex_rect(28.242231182049853961,-6.718436965670084911); *b = gsl_complex_rect(-41.794996776329057792,-36.327236150152172121); break; case 6: *a = gsl_complex_rect(-19.940775161383171961,21.095312104554362894); *b = gsl_complex_rect(52.363924013517555970,18.026029050938499690); break; case 7: *a = gsl_complex_rect(-1.344192502522298750,-7.522944104034740729); *b = gsl_complex_rect(-13.543397817730666190,5.908431672902787801); break; case 8: *a = gsl_complex_rect(0.707766208050378964,-0.340021058812675720); *b = gsl_complex_rect(-0.845016967250801511,-1.168521092980009461); } if (arg<0.04) { *z0=gsl_complex_rect(3.7,0.0); *a=gsl_complex_rect(47.5607474995894429,0.0); *b=gsl_complex_rect(87.8907272628334109,0.0); } if (arg>3.0543) { *z0=gsl_complex_rect(-3.9,0.0); *a=gsl_complex_rect(0.372890578319395619,0.0); *b=gsl_complex_rect(-0.268298362892145679,0.0); } } } return; } void airy_series_taylor(gsl_complex *dp, gsl_complex *dq, gsl_complex zd, gsl_complex z0, double k) { // If k=0, compute Ai or Bi; if k=1, compute Ai' or Bi'. gsl_complex c,f,g,z2,z3; c = GSL_COMPLEX_ONE; z2 = gsl_complex_mul(z0,z0); z3 = gsl_complex_mul(z2,z0); *dp = GSL_COMPLEX_ZERO; if (k<0.5) { *dp = c; c = gsl_complex_mul(c,zd); } *dq = c; c = gsl_complex_mul(c,zd); c = gsl_complex_div_real(c,2.0-k); *dp = gsl_complex_add(*dp,gsl_complex_mul(z0,c)); c = gsl_complex_mul(c,zd); c = gsl_complex_div_real(c,3.0-k); *dp = gsl_complex_add(*dp,c); *dq = gsl_complex_add(*dq,gsl_complex_mul(z0,c)); c = gsl_complex_mul(c,zd); c = gsl_complex_div_real(c,4.0-k); f = z2; g = gsl_complex_rect(2.0,0.0); ADDON; c = gsl_complex_div_real(c,5.0-k); f = gsl_complex_mul_real(z0,4.0); g = z2; ADDON; c = gsl_complex_div_real(c,6.0-k); f = gsl_complex_add_real(z3,4.0); g = gsl_complex_mul_real(z0,6.0); ADDON; c = gsl_complex_div_real(c,7.0-k); f = gsl_complex_mul_real(z2,9.0); g = gsl_complex_add_real(z3,10.0); ADDON; c = gsl_complex_div_real(c,8.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(z3,28.0)); g = gsl_complex_mul_real(z2,12.0); ADDON; c = gsl_complex_div_real(c,9.0-k); f = gsl_complex_add_real(gsl_complex_mul_real(z3,16.0),28.0); g = gsl_complex_mul(z0,gsl_complex_add_real(z3,52.0)); ADDON; c = gsl_complex_div_real(c,10.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(z3,100.0)); g = gsl_complex_add_real(gsl_complex_mul_real(z3,20.0),80.0); ADDON; c = gsl_complex_div_real(c,11.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul_real(z3,25.0),280.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(z3,160.0)); ADDON; c = gsl_complex_div_real(c,12.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,260.0),z3),280.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul_real(z3,30.0),600.0)); ADDON; c = gsl_complex_div_real(c,13.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul_real(z3,36.0),1380.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,380.0),z3),880.0); ADDON; c = gsl_complex_div_real(c,14.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,560.0),z3),3640.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul_real(z3,42.0),2520.0)); ADDON; c = gsl_complex_div_real(c,15.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,49.0),4760.0),z3),3640.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,770.0),z3),8680.0)); ADDON; c = gsl_complex_div_real(c,16.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,1064.0),z3),22960.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,56.0),7840.0),z3),12320.0); ADDON; c = gsl_complex_div_real(c,17.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,64.0),13160.0),z3),58240.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,1400.0),z3),46480.0)); ADDON; c = gsl_complex_div_real(c,18.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,1848.0),z3),99120.0),z3),58240.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,72.0),20160.0),z3),151200.0)); ADDON; c = gsl_complex_div_real(c,19.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,81.0),31248.0),z3),448560.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,2352.0),z3),179760.0),z3),209440.0); ADDON; c = gsl_complex_div_real(c,20.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,3000.0),z3),336000.0),z3),1106560.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,90.0),45360.0),z3),987840.0)); ADDON; c = gsl_complex_div_real(c,21.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,100.0),66360.0),z3),2331840.0),z3),1106560.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,3720.0),z3),562800.0),z3),3082240.0)); ADDON; c = gsl_complex_div_real(c,22.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,4620.0),z3),960960.0),z3),10077760.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,110.0),92400.0),z3),4583040.0),z3),4188800.0); ADDON; c = gsl_complex_div_real(c,23.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,121.0),129360.0),z3),9387840.0),z3),24344320.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,5610.0),z3),1515360.0),z3),23826880.0)); ADDON; c = gsl_complex_div_real(c,24.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,6820.0),z3),2420880.0),z3),61378240.0),z3),24344320.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,132.0),174240.0),z3),16964640.0),z3),71998080.0)); ADDON; c = gsl_complex_div_real(c,25.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,144.0),235620.0),z3),31489920.0),z3),256132800.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,8140.0),z3),3640560.0),z3),129236800.0),z3),96342400.0); ADDON; c = gsl_complex_div_real(c,26.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,9724.0),z3),5525520.0),z3),286686400.0),z3),608608000.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,156.0),308880.0),z3),53333280.0),z3),643843200.0)); ADDON; c = gsl_complex_div_real(c,27.0-k); f = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,169.0),406120.0),z3),92011920.0),z3),1790588800.0),z3),608608000.0); g = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,11440.0),z3),7996560.0),z3),553352800.0),z3),1896294400.0)); ADDON; c = gsl_complex_div_real(c,28.0-k); f = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,13468.0),z3),11651640.0),z3),1105424320.0),z3),7268060800.0)); g = gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,182.0),520520.0),z3),147987840.0),z3),4004000000.0),z3),2504902400.0); ADDON; c = gsl_complex_div_real(c,29.0-k); f = gsl_complex_mul(z0,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul_real(z3,196.0),668668.0),z3),241200960.0),z3),9531121600.0),z3),17041024000.0)); g = gsl_complex_mul(z2,gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(gsl_complex_mul(gsl_complex_add_real(z3,15652.0),z3),16336320.0),z3),1993351360.0),z3),19280060800.0)); *dp = gsl_complex_add(*dp,gsl_complex_mul(f,c)); *dq = gsl_complex_add(*dq,gsl_complex_mul(g,c)); return; } void airy_ai(gsl_complex in, gsl_complex *out, int *status, char *errText) { int conjugate,i,max; double mod,arg; gsl_complex a,b,c,d,dp,dq,zah,zd,z0; mod = gsl_complex_abs(in); arg = gsl_complex_arg(in); if (mod<3.2 && (mod<2.0 || arg>1.05 || arg<-1.05)) { d = gsl_complex_mul_real(airy_series_y1(in),0.355028053887817239); d = gsl_complex_sub(d,gsl_complex_mul_real(airy_series_y2(in),0.258819403792806798)); *status = 0; *out = d; return; } else if (mod<8.8) { if (arg<0.0) { conjugate = 1; in = gsl_complex_conjugate(in); arg = -arg; } else { conjugate = 0; } airy_lookup_ai(mod,arg,&a,&b,&z0); zd = gsl_complex_sub(in,z0); airy_series_taylor(&dp,&dq,zd,z0,0.0); dp = gsl_complex_mul(a,dp); dq = gsl_complex_mul(b,dq); d = gsl_complex_add(dp,dq); *status = 0; if (conjugate==1) { *out = gsl_complex_conjugate(d); return; } else { *out = d; return; } } else { if (log(mod)>440.0) { *status = 2; // calculation will overflow sprintf(errText,"Overflow error within Airy function"); return; } if (arg<-2.094395102393195492 || arg>2.094395102393195492) { zah = gsl_complex_pow_real(gsl_complex_negative(in),1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; dp = GSL_COMPLEX_ZERO; dq = GSL_COMPLEX_ZERO; for (i=0;i<=max;i+=2) { dp = gsl_complex_add(dp,c); c = gsl_complex_mul_real(c,((double) (6*i+1)*(6*i+5))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); dq = gsl_complex_add(dq,c); c = gsl_complex_mul_real(c,((double) (6*i+7)*(6*i+11))/((double) -48*(i+2))); c = gsl_complex_div(c,zah); } c = gsl_complex_add_real(gsl_complex_div_real(zah,1.5),0.785398163397448309); if (GSL_IMAG(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } dp = gsl_complex_mul(dp,gsl_complex_sin(c)); dq = gsl_complex_mul(dq,gsl_complex_cos(c)); d = gsl_complex_sub(dp,dq); d = gsl_complex_mul(d,gsl_complex_pow_real(gsl_complex_negative(in),-0.25)); d = gsl_complex_div_real(d,1.772453850905516027); } else { zah = gsl_complex_pow_real(in,1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=max;i++) { d = gsl_complex_add(d,c); c = gsl_complex_mul_real(c,((double) (6*i+1)*(6*i+5))/((double) -48*(i+1))); c = gsl_complex_div(c,zah); } d = gsl_complex_mul(d,gsl_complex_pow_real(in,-0.25)); d = gsl_complex_div_real(d,3.544907701811032054); c = gsl_complex_div_real(zah,-1.5); if (GSL_REAL(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } d = gsl_complex_mul(d,gsl_complex_exp(c)); } *status = 0; *out = d; return; } } void airy_bi(gsl_complex in, gsl_complex *out, int *status, char *errText) { int conjugate,i,max; double mod,arg; gsl_complex a,b,c,d,dp,dq,zah,zd,z0; mod = gsl_complex_abs(in); arg = gsl_complex_arg(in); if (mod<3.2) { d = gsl_complex_mul_real(airy_series_y1(in), 0.614926627446000735); d = gsl_complex_add(d,gsl_complex_mul_real(airy_series_y2(in),0.448288357353826357)); *status = 0; *out = d; return; } else if (mod<8.8) { if (arg<0.0) { conjugate = 1; in = gsl_complex_conjugate(in); arg = -arg; } else { conjugate = 0; } airy_lookup_bi(mod,arg,&a,&b,&z0); zd = gsl_complex_sub(in,z0); airy_series_taylor(&dp,&dq,zd,z0,0.0); dp = gsl_complex_mul(a,dp); dq = gsl_complex_mul(b,dq); d = gsl_complex_add(dp,dq); *status = 0; if (conjugate==1) { *out = gsl_complex_conjugate(d); return; } else { *out = d; return; } } else { if (log(mod)>440.0) { *status = 2; // calculation will overflow sprintf(errText,"Overflow error within Airy function"); return; } if (arg<-1.63 || arg>1.63) { zah = gsl_complex_pow_real(gsl_complex_negative(in),1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; dp = GSL_COMPLEX_ZERO; dq = GSL_COMPLEX_ZERO; for (i=0;i<=max;i+=2) { dp = gsl_complex_add(dp,c); c = gsl_complex_mul_real(c,((double) (6*i+1)*(6*i+5))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); dq = gsl_complex_add(dq,c); c = gsl_complex_mul_real(c,((double) (6*i+7)*(6*i+11))/((double) -48*(i+2))); c = gsl_complex_div(c,zah); } c = gsl_complex_add_real(gsl_complex_div_real(zah,1.5),0.785398163397448309); if (GSL_IMAG(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } dp = gsl_complex_mul(dp,gsl_complex_cos(c)); dq = gsl_complex_mul(dq,gsl_complex_sin(c)); d = gsl_complex_add(dp,dq); d = gsl_complex_mul(d,gsl_complex_pow_real(gsl_complex_negative(in),-0.25)); d = gsl_complex_div_real(d,1.772453850905516027); } else if (arg>-0.51 && arg<0.51) { zah = gsl_complex_pow_real(in,1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=max;i++) { d = gsl_complex_add(d,c); c = gsl_complex_mul_real(c,((double) (6*i+1)*(6*i+5))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); } d = gsl_complex_mul(d,gsl_complex_pow_real(in,-0.25)); d = gsl_complex_div_real(d,1.772453850905516027); c = gsl_complex_div_real(zah,1.5); if (GSL_REAL(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } d = gsl_complex_mul(d,gsl_complex_exp(c)); } else { /* The asymptotic expansion is poor here due to Stokes' Phenomenon. */ c = gsl_complex_polar(1,2.094395102393195492); d = gsl_complex_conjugate(c); airy_ai(gsl_complex_mul(in,c),&a,status,errText); if (*status==2) return; airy_ai(gsl_complex_mul(in,d),&b,status,errText); if (*status==2) return; a = gsl_complex_mul(a,c); b = gsl_complex_mul(b,d); d = gsl_complex_sub(a,b); d = gsl_complex_mul_imag(d,-1.0); } *status = 0; *out = d; return; } } void airy_ai_diff(gsl_complex in, gsl_complex *out, int *status, char *errText) { int conjugate,i,max; double mod,arg; gsl_complex a,b,c,d,dp,dq,zah,zd,z0; mod = gsl_complex_abs(in); arg = gsl_complex_arg(in); if (mod<3.2 && (mod<2.0 || arg>1.05 || arg<-1.05)) { d = gsl_complex_mul_real(airy_series_y1_diff(in),0.355028053887817239); d = gsl_complex_sub(d,gsl_complex_mul_real(airy_series_y2_diff(in),0.258819403792806798)); *status = 0; *out = d; return; } else if (mod<8.8) { if (arg<0.0) { conjugate = 1; in = gsl_complex_conjugate(in); arg = -arg; } else { conjugate = 0; } airy_lookup_ai(mod,arg,&a,&b,&z0); zd = gsl_complex_sub(in,z0); airy_series_taylor(&dp,&dq,zd,z0,1.0); dp = gsl_complex_mul(a,dp); dq = gsl_complex_mul(b,dq); d = gsl_complex_add(dp,dq); *status = 0; if (conjugate==1) { *out = gsl_complex_conjugate(d); return; } else { *out = d; return; } } else { if (log(mod)>440.0) { *status = 2; // calculation will overflow sprintf(errText,"Overflow error within Airy function"); return; } if (arg<-2.094395102393195492 || arg>2.094395102393195492) { zah = gsl_complex_pow_real(gsl_complex_negative(in),1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; dp = GSL_COMPLEX_ZERO; dq = GSL_COMPLEX_ZERO; for (i=0;i<=max;i+=2) { dp = gsl_complex_add(dp,c); c = gsl_complex_mul_real(c,((double) (6*i-1)*(6*i+7))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); dq = gsl_complex_add(dq,c); c = gsl_complex_mul_real(c,((double) (6*i+5)*(6*i+13))/((double) -48*(i+2))); c = gsl_complex_div(c,zah); } c = gsl_complex_add_real(gsl_complex_div_real(zah,1.5),0.785398163397448309); if (GSL_IMAG(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } dp = gsl_complex_mul(dp,gsl_complex_cos(c)); dq = gsl_complex_mul(dq,gsl_complex_sin(c)); d = gsl_complex_add(dp,dq); d = gsl_complex_mul(d,gsl_complex_pow_real(gsl_complex_negative(in),+0.25)); d = gsl_complex_div_real(d,-1.772453850905516027); } else { zah = gsl_complex_pow_real(in,1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=max;i++) { d = gsl_complex_add(d,c); c = gsl_complex_mul_real(c,((double) (6*i-1)*(6*i+7))/((double) -48*(i+1))); c = gsl_complex_div(c,zah); } d = gsl_complex_mul(d,gsl_complex_pow_real(in,0.25)); d = gsl_complex_div_real(d,-3.544907701811032054); c = gsl_complex_div_real(zah,-1.5); if (GSL_REAL(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } d = gsl_complex_mul(d,gsl_complex_exp(c)); } *status = 0; *out = d; return; } } void airy_bi_diff(gsl_complex in, gsl_complex *out, int *status, char *errText) { int conjugate,i,max; double mod,arg; gsl_complex a,b,c,d,dp,dq,zah,zd,z0; mod = gsl_complex_abs(in); arg = gsl_complex_arg(in); if (mod<3.2) { d = gsl_complex_mul_real(airy_series_y1_diff(in), 0.614926627446000735); d = gsl_complex_add(d,gsl_complex_mul_real(airy_series_y2_diff(in),0.448288357353826357)); *status = 0; *out = d; return; } else if (mod<8.8) { if (arg<0.0) { conjugate = 1; in = gsl_complex_conjugate(in); arg = -arg; } else { conjugate = 0; } airy_lookup_bi(mod,arg,&a,&b,&z0); zd = gsl_complex_sub(in,z0); airy_series_taylor(&dp,&dq,zd,z0,1.0); dp = gsl_complex_mul(a,dp); dq = gsl_complex_mul(b,dq); d = gsl_complex_add(dp,dq); *status = 0; if (conjugate==1) { *out = gsl_complex_conjugate(d); return; } else { *out = d; return; } } else { if (log(mod)>440.0) { *status = 2; // calculation will overflow sprintf(errText,"Overflow error within Airy function"); return; } if (arg<-1.63 || arg>1.63) { zah = gsl_complex_pow_real(gsl_complex_negative(in),1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; dp = GSL_COMPLEX_ZERO; dq = GSL_COMPLEX_ZERO; for (i=0;i<=max;i+=2) { dp = gsl_complex_add(dp,c); c = gsl_complex_mul_real(c,((double) (6*i-1)*(6*i+7))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); dq = gsl_complex_add(dq,c); c = gsl_complex_mul_real(c,((double) (6*i+5)*(6*i+13))/((double) -48*(i+2))); c = gsl_complex_div(c,zah); } c = gsl_complex_add_real(gsl_complex_div_real(zah,1.5),0.785398163397448309); if (GSL_IMAG(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } dp = gsl_complex_mul(dp,gsl_complex_sin(c)); dq = gsl_complex_mul(dq,gsl_complex_cos(c)); d = gsl_complex_sub(dq,dp); d = gsl_complex_mul(d,gsl_complex_pow_real(gsl_complex_negative(in),+0.25)); d = gsl_complex_div_real(d,-1.772453850905516027); } else if (arg>-0.51 && arg<0.51) { zah = gsl_complex_pow_real(in,1.5); max = 29; if (mod>10.0) max = 20; if (mod>12.0) max = 16; if (mod>16.0) max = 12; c = GSL_COMPLEX_ONE; d = GSL_COMPLEX_ZERO; for (i=0;i<=max;i++) { d = gsl_complex_add(d,c); c = gsl_complex_mul_real(c,((double) (6*i-1)*(6*i+7))/((double) 48*(i+1))); c = gsl_complex_div(c,zah); } d = gsl_complex_mul(d,gsl_complex_pow_real(in,0.25)); d = gsl_complex_div_real(d,1.772453850905516027); c = gsl_complex_div_real(zah,1.5); if (GSL_REAL(c)>650.0) { *status = 2; // risk of overflow sprintf(errText,"Overflow error within Airy function"); return; } d = gsl_complex_mul(d,gsl_complex_exp(c)); } else { c = gsl_complex_polar(1,2.094395102393195492); d = gsl_complex_conjugate(c); airy_ai_diff(gsl_complex_mul(in,c),&a,status,errText); if (*status==2) return; airy_ai_diff(gsl_complex_mul(in,d),&b,status,errText); if (*status==2) return; a = gsl_complex_mul(a,d); b = gsl_complex_mul(b,c); d = gsl_complex_sub(a,b); d = gsl_complex_mul_imag(d,-1.0); } *status = 0; *out = d; return; } } pyxplot-0.9.2/src/defaultObjs/moduleAst.c0000664000175000017500000002560412026340554016765 0ustar dcf21dcf21// moduleAst.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleAst.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleAst.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" // Lambda Cold Dark Matter Cosmology Engine typedef struct Lcdm_comm { double OmegaM, OmegaL, H, t; } Lcdm_comm; double __Lcdm_DA_integrand(double z, void *params) { // All equations below are from // Distance Measured in Cosmology // David W. Hogg // http://arxiv.org/abs/astro-ph/9905116 Lcdm_comm *p = (Lcdm_comm *)params; return 1.0 / sqrt(p->OmegaM*pow(1+z,3) + p->OmegaL); // Eq (14), as substituted into eq (15) and (16). Assume omega_k is zero } double __Lcdm_t_integrand(double z, void *params) { // The equations for the following are taken from: // THE COSMOLOGICAL CONSTANT // Sean M. Carroll and William H. Press // http://nedwww.ipac.caltech.edu/level5/Carroll/frames.html Lcdm_comm *p = (Lcdm_comm *)params; return pow(1+z,-1) * pow(pow(1+z,2)*(1+p->OmegaM*z) - z*(2+z)*p->OmegaL,-0.5); // Equation (16) } double Lcdm_age(double H, double OmegaM, double OmegaL) { double OmegaA = OmegaM - 0.3*(OmegaM+OmegaL) + 0.3; if (OmegaA<=1.0) return 2.0/3.0/H * gsl_asinh(sqrt(fabs(1.0-OmegaA)/OmegaA)) / sqrt(fabs(1.0-OmegaA)); else return 2.0/3.0/H * asin (sqrt(fabs(1.0-OmegaA)/OmegaA)) / sqrt(fabs(1.0-OmegaA)); } double Lcdm_DA(double z, double H, double OmegaM, double OmegaL) { Lcdm_comm p; gsl_integration_workspace *ws; gsl_function fn; double result, error; if (z<=0) return GSL_NAN; p.OmegaM = OmegaM; p.OmegaL = OmegaL; ws = gsl_integration_workspace_alloc(1000); fn.function = &__Lcdm_DA_integrand; fn.params = &p; gsl_integration_qags (&fn, 1e-8, z, 0, 1e-7, 1000, ws, &result, &error); gsl_integration_workspace_free(ws); if ((result<=0)||(error>result*0.01)) return GSL_NAN; // Something went wrong return (GSL_CONST_MKSA_SPEED_OF_LIGHT / H) * result / (1+z); } double Lcdm_t_from_z(double z, double H, double OmegaM, double OmegaL) { Lcdm_comm p; gsl_integration_workspace *ws; gsl_function fn; double result, error; if (z<=0) return GSL_NAN; p.OmegaM = OmegaM; p.OmegaL = OmegaL; ws = gsl_integration_workspace_alloc(1000); fn.function = &__Lcdm_t_integrand; fn.params = &p; gsl_integration_qags (&fn, 1e-8, z, 0, 1e-7, 1000, ws, &result, &error); gsl_integration_workspace_free(ws); if ((result<=0)||(error>result*0.01)) return GSL_NAN; // Something went wrong return (1/H) * result; } double __Lcdm_z_from_t_slave(double z, void *params) { Lcdm_comm *p = (Lcdm_comm *)params; return fabs(Lcdm_t_from_z(pow(10.0,z), p->H, p->OmegaM, p->OmegaL) - p->t); } double Lcdm_z_from_t(double t, double H, double OmegaM, double OmegaL) { Lcdm_comm p; int iter = 0, max_iter = 100, status; double m, a, b; const gsl_min_fminimizer_type *T = gsl_min_fminimizer_goldensection; gsl_min_fminimizer *s; gsl_function fn; if ((t<=0)||(t>Lcdm_age(H,OmegaM,OmegaL))) return GSL_NAN; p.OmegaM = OmegaM; p.OmegaL = OmegaL; p.H = H; p.t = t; fn.function = &__Lcdm_z_from_t_slave; fn.params = &p; s = gsl_min_fminimizer_alloc(T); if (s==NULL) return GSL_NAN; gsl_min_fminimizer_set(s, &fn, 0.0, -3.0, 8.0); do { iter++; status = gsl_min_fminimizer_iterate(s); m = gsl_min_fminimizer_x_minimum(s); a = gsl_min_fminimizer_x_lower(s); b = gsl_min_fminimizer_x_upper(s); status = gsl_min_test_interval (a, b, 0.001, 0.0); } while ((status == GSL_CONTINUE) && (iter < max_iter)); gsl_min_fminimizer_free(s); return pow(10.0,m); } // Lambda Cold Dark Matter Cosmology Wrappers #define CHECK_LCDM_INPUTS(XN,H0NUM) \ CHECK_DIMLESS_OR_HAS_UNIT(in[XN], H0NUM, "a recession velocity per unit distance", UNIT_TIME, -1); \ if (in[XN].dimensionless) in[XN].real *= 1e3 / (GSL_CONST_MKSA_PARSEC * 1e6); \ if (!(in[XN+1].dimensionless && in[XN+2].dimensionless)) \ { \ *status = 1; \ *errType = ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless values for w_m and w_l. Supplied values have dimensions of <%s> and <%s>.", FunctionDescription, ppl_printUnit(c, &in[XN+1], NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[XN+2], NULL, NULL, 1, 1, 0)); \ return; \ } \ #define CHECK_LCDM_REDSHIFT \ if (!(in[0].dimensionless)) \ { \ *status = 1; \ *errType = ERR_UNIT; \ sprintf(errText, "The %s function can only act upon dimensionless values for redshift. Supplied value has dimensions of <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 0, 1, 0)); \ return; \ } \ void pplfunc_Lcdm_age (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_age(H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(0,"first"); OUTPUT.real = Lcdm_age(in[0].real, in[1].real, in[2].real); CLEANUP_APPLYUNIT(UNIT_TIME); CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_angscale(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_age(z,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_LCDM_REDSHIFT; OUTPUT.real = Lcdm_DA(in[0].real, in[1].real, in[2].real, in[3].real); CLEANUP_APPLYUNIT(UNIT_LENGTH); OUTPUT.exponent[UNIT_ANGLE] = -1; CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_DA (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_DA(z,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_LCDM_REDSHIFT; OUTPUT.real = Lcdm_DA(in[0].real, in[1].real, in[2].real, in[3].real); CLEANUP_APPLYUNIT(UNIT_LENGTH); CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_DL (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_DL(z,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_LCDM_REDSHIFT; OUTPUT.real = Lcdm_DA(in[0].real, in[1].real, in[2].real, in[3].real) * pow(1+in[0].real, 2); CLEANUP_APPLYUNIT(UNIT_LENGTH); CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_DM (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_DM(z,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_LCDM_REDSHIFT; OUTPUT.real = Lcdm_DA(in[0].real, in[1].real, in[2].real, in[3].real) * (1+in[0].real); CLEANUP_APPLYUNIT(UNIT_LENGTH); CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_t (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_t(z,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_LCDM_REDSHIFT; OUTPUT.real = Lcdm_t_from_z(in[0].real, in[1].real, in[2].real, in[3].real); CLEANUP_APPLYUNIT(UNIT_TIME); CHECK_OUTPUT_OKAY; } void pplfunc_Lcdm_z (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Lcdm_z(t,H0,w_m,w_l)"; int i; CHECK_LCDM_INPUTS(1,"second"); CHECK_DIMLESS_OR_HAS_UNIT(in[0], "first", "a time", UNIT_TIME, 1); OUTPUT.real = Lcdm_z_from_t(in[0].real, in[1].real, in[2].real, in[3].real); CHECK_OUTPUT_OKAY; } void pplfunc_sidereal_time(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "siderealTime(d)"; if ((nArgs!=1)&&((in[0].objType!=PPLOBJ_NUM)||(in[0].objType!=PPLOBJ_DATE))) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date object or numeric Unix time as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } CHECK_1NOTNAN; CHECK_1INPUT_DIMLESS; IF_1COMPLEX { QUERY_MUST_BE_REAL } ELSE_REAL { double JD = in->real / 86400.0 + 40587.5; double T = (JD - 51545.0) / 36525.0; // See pages 87-88 of Astronomical Algorithms, by Jean Meeus OUTPUT.real = fmod( M_PI/180 * ( 280.46061837 + 360.98564736629 * (JD - 51545.0) + 0.000387933 * T*T + T*T*T / 38710000.0 ), 2*M_PI); } ENDIF CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_moonphase (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "moonPhase(d)"; if ((nArgs!=1)&&((in[0].objType!=PPLOBJ_NUM)||(in[0].objType!=PPLOBJ_DATE))) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a date object or numeric Unix time as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } CHECK_1NOTNAN; CHECK_1INPUT_DIMLESS; IF_1COMPLEX { QUERY_MUST_BE_REAL } ELSE_REAL { double JD = in->real / 86400.0 + 40587.5; double t = (JD - 51545)/36525; // Time in Julian Centuries since 2000.0 double Msun = 2*M_PI*fmod(0.993133+99.997361*t, 1); double Lsun = 2*M_PI*fmod(0.7859453+Msun/(2*M_PI)+(6893.0*sin(Msun)+72.0*sin(2*Msun)+6191.2*t)/1296e3, 1); double L0 = 2*M_PI*fmod(0.606433+1336.855225*t, 1); double l = 2*M_PI*fmod(0.374897+1325.552410*t, 1); double ls = 2*M_PI*fmod(0.993133+99.997361*t, 1); double D = 2*M_PI*fmod(0.827361+1236.853086*t, 1); double F = 2*M_PI*fmod(0.259086+1342.227825*t, 1); double dL = 22640*sin(l) - 4586*sin(l-2*D) + 2370*sin(2*D) + 769*sin(2*l) - 668*sin(ls) - 412*sin(2*F) - 212*sin(2*l-2*D) - 206*sin(l+ls-2*D) + 192*sin(l+2*D) - 165*sin(ls-2*D) - 125*sin(D) - 110*sin(l+ls) + 148*sin(l-ls) - 55*sin(2*F-2*D); OUTPUT.real = fmod(L0 + dL/1296e3*2*M_PI - Lsun , 2*M_PI); while (OUTPUT.real<0) OUTPUT.real += 2*M_PI; } ENDIF CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } pyxplot-0.9.2/src/defaultObjs/defaultFuncs.c0000664000175000017500000017542412026340554017461 0ustar dcf21dcf21// defaultFuncs.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultFuncs.c 1299 2012-08-31 23:32:22Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define GSL_RANGE_CHECK_OFF 1 #include "coreUtils/dict.h" #include "mathsTools/dcfmath.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/expEvalOps.h" #include "expressions/fnCall.h" #include "expressions/traceback_fns.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjCmp.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/airyFuncs.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" #include "defaultObjs/zetaRiemann.h" #include "texify.h" #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { fprintf(stderr,"Stack forward reference detected."); } \ } void ppl_addMagicFunction(dict *n, char *name, int id, char *shortdesc, char *latex, char *desc) { pplObj v; pplFunc *f = malloc(sizeof(pplFunc)); if (f==NULL) return; f->functionType = PPL_FUNC_MAGIC; f->refCount = 1; f->minArgs = id; f->maxArgs = 0; f->functionPtr = NULL; f->argList = NULL; f->minActive = NULL; f->maxActive = NULL; f->numOnly = 0; f->notNan = 0; f->realOnly = 0; f->dimlessOnly = 0; f->next = NULL; f->LaTeX = latex; f->descriptionShort = shortdesc; f->description = desc; f->needSelfThis = 0; v.refCount = 1; if (pplObjFunc(&v,1,1,f)!=NULL) ppl_dictAppendCpy(n , name , (void *)&v , sizeof(v)); return; } pplFunc *ppl_addSystemFunc(dict *n, char *name, int minArgs, int maxArgs, int numOnly, int notNan, int realOnly, int dimlessOnly, void *fn, char *shortdesc, char *latex, char *desc) { pplObj v; pplFunc *f = malloc(sizeof(pplFunc)); if (f==NULL) return NULL; f->functionType = PPL_FUNC_SYSTEM; f->refCount = 1; f->minArgs = minArgs; f->maxArgs = maxArgs; f->functionPtr = fn; f->argList = NULL; f->minActive = NULL; f->maxActive = NULL; f->numOnly = numOnly; f->notNan = notNan; f->realOnly = realOnly; f->dimlessOnly = dimlessOnly; f->next = NULL; f->LaTeX = latex; f->descriptionShort = shortdesc; f->description = desc; f->needSelfThis = 0; v.refCount = 1; if (pplObjFunc(&v,1,1,f)!=NULL) ppl_dictAppendCpy(n , name , (void *)&v , sizeof(v)); return f; } void ppl_addSystemMethod(dict *n, char *name, int minArgs, int maxArgs, int numOnly, int notNan, int realOnly, int dimlessOnly, void *fn, char *shortdesc, char *latex, char *desc) { pplFunc *f = ppl_addSystemFunc(n, name, minArgs, maxArgs, numOnly, notNan, realOnly, dimlessOnly, fn, shortdesc, latex, desc); f->needSelfThis = 1; } void pplfunc_abs (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "abs(z)"; IF_1COMPLEX { OUTPUT.real = hypot(in[0].real , in[0].imag); } ELSE_REAL { OUTPUT.real = fabs(in[0].real); } ENDIF; ppl_unitsDimCpy(&OUTPUT, in); CHECK_OUTPUT_OKAY; } void pplfunc_acos (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acos(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccos(z); } ELSE_REAL { z=gsl_complex_arccos_real(in[0].real); } ENDIF; CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_acosh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acosh(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccosh(z); } ELSE_REAL { z=gsl_complex_arccosh_real(in[0].real); } ENDIF; CHECK_OUTPUT_OKAY; } void pplfunc_acot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acot(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccot(z); CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_acoth (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acoth(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccoth(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_acsc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acsc(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccsc(z); } ELSE_REAL { z=gsl_complex_arccsc_real(in[0].real); } ENDIF; CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_acsch (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "acsch(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arccsch(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_airy_ai (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "airy_ai(z)"; gsl_complex zi, z; GSL_SET_COMPLEX(&zi,in[0].real,in[0].imag); airy_ai(zi,&z,status,errText); if (*status) { *errType = ERR_NUMERICAL; return; } CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_airy_ai_diff(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "airy_ai_diff(z)"; gsl_complex zi,z; GSL_SET_COMPLEX(&zi,in[0].real,in[0].imag); airy_ai_diff(zi,&z,status,errText); if (*status) { *errType = ERR_NUMERICAL; return; } CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_airy_bi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "airy_bi(z)"; gsl_complex zi,z; GSL_SET_COMPLEX(&zi,in[0].real,in[0].imag); airy_bi(zi,&z,status,errText); if (*status) { *errType = ERR_NUMERICAL; return; } CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_airy_bi_diff(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "airy_bi_diff(z)"; gsl_complex zi,z; GSL_SET_COMPLEX(&zi,in[0].real,in[0].imag); airy_bi_diff(zi,&z,status,errText); if (*status) { *errType = ERR_NUMERICAL; return; } CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_arg (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "arg(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); OUTPUT.real = gsl_complex_arg(z); CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_asec (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "asec(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arcsec(z); } ELSE_REAL { z=gsl_complex_arcsec_real(in[0].real); } ENDIF; CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_asech (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "asech(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arcsech(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_asin (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "asin(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arcsin(z); } ELSE_REAL { z=gsl_complex_arcsin_real(in[0].real); } ENDIF; CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_asinh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "asinh(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arcsinh(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_atan (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "atan(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arctan(z); CLEANUP_GSLCOMPLEX; CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_atanh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "atanh(z)"; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_arctanh(z); } ELSE_REAL { z=gsl_complex_arctanh_real(in[0].real); } ENDIF; CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_atan2 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "atan2(x,y)"; CHECK_2INPUT_DIMMATCH; OUTPUT.real = atan2(in[0].real, in[1].real); CLEANUP_APPLYUNIT(UNIT_ANGLE); CHECK_OUTPUT_OKAY; } void pplfunc_besseli (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besseli(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_il_scaled((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselI (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselI(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_In((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselj (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselj(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_jl((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselJ (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselJ(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_Jn((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselk (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselk(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_kl_scaled((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselK (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselK(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_Kn((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_bessely (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "bessely(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_yl((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_besselY (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "besselY(l,x)"; CHECK_NEEDINT(in[0], "l", "function can only evaluate integer-order Bessel functions"); OUTPUT.real = gsl_sf_bessel_Yn((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_beta (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "beta(a,b)"; OUTPUT.real = gsl_sf_beta(in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_call (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "call(f,a)"; const int stkLevelOld = c->stackPtr; list *argList; pplExpr dummy; pplFunc *fi; pplObj *item; listIterator *li; if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (in[1].objType != PPLOBJ_LIST) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s function requires a list object as its second argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[1].objType]); return; } argList = (list *)in[1].auxil; li = ppl_listIterateInit(argList); STACK_MUSTHAVE(c,argList->length); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push arguments while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObjCpy(&c->stack[c->stackPtr], item, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; } // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, argList->length, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } pplObjCpy(&OUTPUT, &c->stack[c->stackPtr-1], 0, 0, 1); while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } void pplfunc_ceil (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ceil(x)"; OUTPUT.real = ceil(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_chr (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "chr(x)"; char *out; CHECK_NEEDINT(in[0], "s", "function can only evaluate integer ASCII codes"); out = (char *)malloc(2); if (out==NULL) { *status=1; sprintf(errText,"Out of memory."); return; } out[0] = ((int)in[0].real) & 255; out[1] = '\0'; pplObjStr(&OUTPUT,0,1,out); } void pplfunc_classOf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjCpy(&OUTPUT,in[0].objPrototype,0,0,1); } void pplfunc_cmp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { void *a = &in[0]; void *b = &in[1]; OUTPUT.real = pplObjCmpQuiet(&a,&b); } void pplfunc_cmyk (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjColor(&OUTPUT,0,SW_COLSPACE_CMYK,in[0].real,in[1].real,in[2].real,in[3].real); } void pplfunc_conjugate (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "conjugate(z)"; memcpy(&OUTPUT, in, sizeof(pplObj)); OUTPUT.imag *= -1; CHECK_OUTPUT_OKAY; } void pplfunc_copy (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjDeepCpy(&OUTPUT,&in[0],0,0,1); } void pplfunc_cos (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "cos(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_cos(z); CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = cos(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } void pplfunc_cosh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "cosh(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_cosh(z); CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = cosh(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } void pplfunc_cot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "cot(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_cot(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_coth (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "coth(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_coth(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_cross (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "cross(a,b)"; int t1 = in[0].objType; int t2 = in[1].objType; gsl_vector *va, *vb, *vo; if (t1!=PPLOBJ_VEC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "First argument to %s must be a vector. Supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[t1]); return; } if (t2!=PPLOBJ_VEC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Second argument to %s must be a vector. Supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[t2]); return; } va = ((pplVector *)in[0].auxil)->v; vb = ((pplVector *)in[1].auxil)->v; if (va->size != 3) { *status=1; *errType=ERR_TYPE; sprintf(errText, "%s can only act on three-component vectors. Supplied vector has %ld components.", FunctionDescription, (long)va->size); return; } if (vb->size != 3) { *status=1; *errType=ERR_TYPE; sprintf(errText, "%s can only act on three-component vectors. Supplied vector has %ld components.", FunctionDescription, (long)vb->size); return; } if (pplObjVector(&OUTPUT,0,1,3)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(OUTPUT.auxil))->v; gsl_vector_set(vo, 0, gsl_vector_get(va,1)*gsl_vector_get(vb,2) - gsl_vector_get(vb,1)*gsl_vector_get(va,2) ); gsl_vector_set(vo, 1, gsl_vector_get(va,2)*gsl_vector_get(vb,0) - gsl_vector_get(vb,2)*gsl_vector_get(va,0) ); gsl_vector_set(vo, 2, gsl_vector_get(va,0)*gsl_vector_get(vb,1) - gsl_vector_get(vb,0)*gsl_vector_get(va,1) ); in[0].real=in[1].real=1; in[0].imag=in[1].imag=0; in[0].flagComplex=in[1].flagComplex=0; ppl_uaMul(c, &in[0], &in[1], &OUTPUT, status, errType, errText); } void pplfunc_csc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "csc(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_csc(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_csch (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "csch(x)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_csch(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_deepcopy (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjDeepCpy(&OUTPUT,&in[0],1,0,1); } void pplfunc_degrees (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "degrees(x)"; int i; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); OUTPUT.real = ppl_degs(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_ellK (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ellipticintK(k)"; OUTPUT.real = gsl_sf_ellint_Kcomp(in[0].real , GSL_PREC_DOUBLE); CHECK_OUTPUT_OKAY; } void pplfunc_ellE (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ellipticintE(k)"; OUTPUT.real = gsl_sf_ellint_Ecomp(in[0].real , GSL_PREC_DOUBLE); CHECK_OUTPUT_OKAY; } void pplfunc_ellP (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ellipticintP(k,n)"; OUTPUT.real = gsl_sf_ellint_Pcomp(in[0].real , in[1].real , GSL_PREC_DOUBLE); CHECK_OUTPUT_OKAY; } void pplfunc_erf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "erf(x)"; OUTPUT.real = gsl_sf_erf(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_erfc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "erfc(x)"; OUTPUT.real = gsl_sf_erfc(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_eval (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { const int stkLevelOld = c->stackPtr; int explen=-1, errPos=-1, lastOpAssign; char *exp; pplExpr *e; pplObj *output; if (in[0].objType!=PPLOBJ_STR) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The eval() function requires a string argument."); return; } exp = (char *)in[0].auxil; explen = strlen(exp); ppl_error_setstreaminfo(&c->errcontext, 1, "evaluated expression"); ppl_expCompile(c,c->errcontext.error_input_linenumber,c->errcontext.error_input_sourceId,c->errcontext.error_input_filename,exp,&explen,1,1,1,&e,&errPos,errType,errText); if (errPos>=0) { pplExpr_free(e); *status=1; return; } if (explenerrStat.status) { *status=1; *errType=ERR_GENERIC; strcpy(errText, "Error in evaluated expression"); return; } pplObjCpy(&OUTPUT,output,0,0,1); while (c->stackPtr>stkLevelOld) { c->stackPtr--; if (c->stack[c->stackPtr].objType!=PPLOBJ_NUM) // optimisation: Don't waste time garbage collecting numbers { ppl_garbageObject(&c->stack[c->stackPtr]); if (c->stack[c->stackPtr].refCount != 0) { ppl_error(&c->errcontext,ERR_INTERNAL,-1,-1,"Stack forward reference detected."); } } } return; } void pplfunc_exp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "exp(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "dimensionless or an angle", UNIT_ANGLE, 1); IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_exp(z); CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = exp(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } void pplfunc_expm1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "expm1(x)"; int i; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "dimensionless or an angle", UNIT_ANGLE, 1); OUTPUT.real = expm1(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_expint (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "expint(n,x)"; CHECK_NEEDSINT(in[0], "n", "function's first argument must be"); OUTPUT.real = gsl_sf_expint_En((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_factors(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj v; list *l; int i,n=(int)in[0].real; char *FunctionDescription = "factors(x)"; CHECK_NEEDINT(in[0], "x", "function's argument must be"); if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; for (i=1; i<=n/2; i++) { if ((n%i)!=0) continue; pplObjNum(&v,0,i,0); ppl_listAppendCpy(l, &v, sizeof(v)); } pplObjNum(&v,0,n,0); ppl_listAppendCpy(l, &v, sizeof(v)); return; } void pplfunc_finite (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjBool(&OUTPUT,0,0); if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in[0].flagComplex)) return; if ((!gsl_finite(in[0].real)) || (!gsl_finite(in[0].imag))) return; OUTPUT.real = 1; } void pplfunc_floor (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "floor(x)"; OUTPUT.real = floor(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_gamma (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gamma(x)"; OUTPUT.real = gsl_sf_gamma(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_gcd (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "gcd(x,...)"; int i, out; for (i=0; inamespaces[1]); __sync_add_and_fetch(&c->namespaces[1]->refCount,1); } void pplfunc_gray (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,in[0].real,in[0].real,in[0].real,0); } void pplfunc_heaviside (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "heaviside(x)"; if (in[0].real >= 0) OUTPUT.real = 1.0; CHECK_OUTPUT_OKAY; } void pplfunc_hsb (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjColor(&OUTPUT,0,SW_COLSPACE_HSB,in[0].real,in[1].real,in[2].real,0); } void pplfunc_hyperg_0F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hyperg_0F1(c,x)"; OUTPUT.real = gsl_sf_hyperg_0F1(in[0].real,in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_hyperg_1F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hyperg_1F1(a,b,x)"; OUTPUT.real = gsl_sf_hyperg_1F1(in[0].real,in[1].real,in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_hyperg_2F0 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hyperg_2F0(a,b,x)"; OUTPUT.real = gsl_sf_hyperg_2F0(in[0].real,in[1].real,in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_hyperg_2F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hyperg_2F1(a,b,c,x)"; OUTPUT.real = gsl_sf_hyperg_2F1(in[0].real,in[1].real,in[2].real,in[3].real); CHECK_OUTPUT_OKAY; } void pplfunc_hyperg_U (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hyperg_U(a,b,x)"; OUTPUT.real = gsl_sf_hyperg_U(in[0].real,in[1].real,in[2].real); CHECK_OUTPUT_OKAY; } void pplfunc_hypot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "hypot(...)"; int i; double acc=0, *buffer; if (nArgs<1) { pplObjNum(&OUTPUT,0,0,0); return; } for (i=1; i, but input %d has dimensions of <%s>.", FunctionDescription, ppl_printUnit(c, &in[0], NULL, NULL, 0, 1, 0), i+1, ppl_printUnit(c, &in[i], NULL, NULL, 1, 1, 0)); return; } buffer = (double *)malloc(nArgs * sizeof(double)); if (buffer==NULL) { *status = 1; *errType=ERR_MEMORY; sprintf(errText, "Out of memory."); return; } for (i=0; iset->term_current.ComplexNumbers == SW_ONOFF_OFF) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; *errText=ERR_NUMERICAL; sprintf(errText, "The function %s can only be used when complex arithmetic is enabled; type 'set numerics complex' first.", FunctionDescription); return; } else { NULL_OUTPUT; } } OUTPUT.real = in[0].imag; CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, in); } void pplfunc_jacobi_cn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "jacobi_cn(u,m)"; { double t1,t2,t3; if (gsl_sf_elljac_e(in[0].real,in[1].real,&t1,&t2,&t3)!=GSL_SUCCESS) { OUTPUT.real=GSL_NAN; } else { OUTPUT.real=t2; } } CHECK_OUTPUT_OKAY; } void pplfunc_jacobi_dn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "jacobi_dn(u,m)"; { double t1,t2,t3; if (gsl_sf_elljac_e(in[0].real,in[1].real,&t1,&t2,&t3)!=GSL_SUCCESS) { OUTPUT.real=GSL_NAN; } else { OUTPUT.real=t3; } } CHECK_OUTPUT_OKAY; } void pplfunc_jacobi_sn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "jacobi_sn(u,m)"; { double t1,t2,t3; if (gsl_sf_elljac_e(in[0].real,in[1].real,&t1,&t2,&t3)!=GSL_SUCCESS) { OUTPUT.real=GSL_NAN; } else { OUTPUT.real=t1; } } CHECK_OUTPUT_OKAY; } void pplfunc_lambert_W0 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lambert_W0(x)"; OUTPUT.real = gsl_sf_lambert_W0(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_lambert_W1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lambert_W1(x)"; OUTPUT.real = gsl_sf_lambert_Wm1(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_lcm (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lcm(x,...)"; int i, gcd, lcm_i, zero=0; double lcm; for (i=0; i INT_MAX) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_OVERFLOW; sprintf(errText, "Integer overflow in the %s function.",FunctionDescription); return; } else { NULL_OUTPUT; } } lcm_i = (int)round(lcm); for (i=2; i INT_MAX) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_OVERFLOW; sprintf(errText, "Integer overflow in the %s function.",FunctionDescription); return; } else { NULL_OUTPUT; } } lcm_i = (int)round(lcm); } OUTPUT.real = lcm; CHECK_OUTPUT_OKAY; } void pplfunc_ldexp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ldexp(x,y)"; CHECK_NEEDSINT(in[1], "y", "function's second argument must be"); OUTPUT.real = ldexp(in[0].real, (int)in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_legendreP (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "legendreP(l,x)"; CHECK_NEEDINT(in[0] , "l", "function's first argument must be"); OUTPUT.real = gsl_sf_legendre_Pl((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_legendreQ (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "legendreQ(l,x)"; CHECK_NEEDINT(in[0] , "l", "function's first argument must be"); OUTPUT.real = gsl_sf_legendre_Ql((int)in[0].real, in[1].real); CHECK_OUTPUT_OKAY; } void pplfunc_len (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int t = in->objType; if ((t==PPLOBJ_DICT)||(t==PPLOBJ_MOD)||(t==PPLOBJ_USER)) OUTPUT.real = ((dict *)in->auxil)->length; else if (t==PPLOBJ_LIST) OUTPUT.real = ((list *)in->auxil)->length; else if ((t==PPLOBJ_STR)||(t==PPLOBJ_EXC)) OUTPUT.real = strlen((char *)in->auxil); else if (t==PPLOBJ_VEC) OUTPUT.real = ((pplVector *)in->auxil)->v->size; else if (t==PPLOBJ_MAT) OUTPUT.real = ((pplMatrix *)in->auxil)->m->size1; else { *status=1; *errType=ERR_TYPE; sprintf(errText, "Object of type <%s> is not a compound object and has no property of length", pplObjTypeNames[t]); return; } return; } void pplfunc_locals (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjDict(&OUTPUT, 0, 1, c->namespaces[c->ns_ptr]); __sync_add_and_fetch(&c->namespaces[c->ns_ptr]->refCount,1); } void pplfunc_log (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "log(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_log(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_log10 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "log10(z)"; gsl_complex z; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_log10(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_logn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "logn(z,n)"; gsl_complex z; pplObj base; GSL_SET_COMPLEX(&z,in[1].real,in[1].imag); z=gsl_complex_log(z); CLEANUP_GSLCOMPLEX; base=OUTPUT; GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_log(z); CLEANUP_GSLCOMPLEX; ppl_uaDiv(c, &OUTPUT, &base, &OUTPUT, status, errType, errText); CHECK_OUTPUT_OKAY; } void pplfunc_lrange (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "lrange([f],l,[s])"; double start, end, step, n; int i; if (nArgs>1) { CHECK_2INPUT_DIMMATCH; } if (nArgs>2) { in++; CHECK_2INPUT_DIMMATCH; in--; } if (nArgs==1) { start=1; end=in[0].real; step=2; } else if (nArgs==2) { start=in[0].real; end=in[1].real; step=2; } else { start=in[0].real; end=in[1].real; step=in[2].real; } n = ceil(log(end/start) / log(step)); if ((!gsl_finite(n))||(n>INT_MAX)) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText,"Invalid step size."); return; } if (n<0) n=0; if (pplObjVector(&OUTPUT,0,1,n)==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText,"Out of memory."); return; } for (i=0; iv, i, start * pow(step,i)); ppl_unitsDimCpy(&OUTPUT, &in[0]); } void pplfunc_max (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if (nArgs==0) { pplObjNull(&OUTPUT,0); return; } if ((nArgs==1)&&(in[0].objType==PPLOBJ_LIST)) { pplObj *item, *best=NULL; listIterator *li = ppl_listIterateInit((list *)in[0].auxil); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { if ((best==NULL)||(pplObjCmpQuiet((void*)&item, (void*)&best)==1)) best=item; } if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,best,0,0,1); } else if ((nArgs==1)&&((in[0].objType==PPLOBJ_DICT)||(in[0].objType==PPLOBJ_MOD)||(in[0].objType==PPLOBJ_USER))) { char *key; pplObj *item, *best=NULL; dictIterator *di = ppl_dictIterateInit((dict *)in[0].auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { if ((best==NULL)||(pplObjCmpQuiet((void*)&item, (void*)&best)==1)) best=item; } if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,best,0,0,1); } else if ((nArgs==1)&&(in[0].objType==PPLOBJ_VEC)) { int i; double *best=NULL; gsl_vector *v=((pplVector *)(in[0].auxil))->v; for (i=0; isize; i++) if ((best==NULL)||(gsl_vector_get(v,i)>*best)) best=gsl_vector_ptr(v,i); if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjNum (&OUTPUT,0,*best,0); ppl_unitsDimCpy(&OUTPUT, &in[0]); } else if ((nArgs==1)&&(in[0].objType==PPLOBJ_MAT)) { int i,j; double *best=NULL; gsl_matrix *m=((pplMatrix *)(in[0].auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) if ((best==NULL)||(gsl_matrix_get(m,i,j)>*best)) best=gsl_matrix_ptr(m,i,j); if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjNum (&OUTPUT,0,*best,0); ppl_unitsDimCpy(&OUTPUT, &in[0]); } else { int i; pplObj *best = in; for (i=1; iv; for (i=0; isize; i++) if ((best==NULL)||(gsl_vector_get(v,i)<*best)) best=gsl_vector_ptr(v,i); if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjNum (&OUTPUT,0,*best,0); ppl_unitsDimCpy(&OUTPUT, &in[0]); } else if ((nArgs==1)&&(in[0].objType==PPLOBJ_MAT)) { int i,j; double *best=NULL; gsl_matrix *m=((pplMatrix *)(in[0].auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) if ((best==NULL)||(gsl_matrix_get(m,i,j)<*best)) best=gsl_matrix_ptr(m,i,j); if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjNum (&OUTPUT,0,*best,0); ppl_unitsDimCpy(&OUTPUT, &in[0]); } else { int i; pplObj *best = in; for (i=1; i in[1].real) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_NUMERICAL; sprintf(errText, "Loss of accuracy in the function %s; the remainder of this division is lost in floating-point rounding.", FunctionDescription); return; } else { NULL_OUTPUT; } } OUTPUT.real = fmod(in[0].real , in[1].real); CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, &in[0]); } void pplfunc_open (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { FILE *f; char *mode; if ((nArgs<1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The open() function requires string arguments."); return; } if ((nArgs>1)&&(in[1].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The open() function requires string arguments."); return; } if (nArgs>1) mode=(char*)in[1].auxil; else mode="r"; f = fopen((char*)in[0].auxil,mode); if (f==NULL) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } pplObjFile(&OUTPUT,0,1,f,0); } void pplfunc_ord (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ord(s)"; int t=in[0].objType; if (t!=PPLOBJ_STR) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Argument to %s must be a string. Supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[t]); return; } OUTPUT.real = (double)((char*)in[0].auxil)[0]; } void pplfunc_ordinal (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "ordinal(n)"; char *out; int n = (int)ceil(fabs(log10(in[0].real))); int i = (int)in[0].real; if (in[0].real<0) in[0].real=GSL_NAN; if (n<2) n=2; if (n>64) in[0].real=GSL_NAN; CHECK_NEEDINT(in[0], "n", "function's input must be an integer"); out = (char *)malloc(n + 8); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } if (((i%100)<21) && ((i%100)>3)) sprintf(out, "%dth", i); else if ((i% 10)==1) sprintf(out, "%dst", i); else if ((i% 10)==2) sprintf(out, "%dnd", i); else if ((i% 10)==3) sprintf(out, "%drd", i); else sprintf(out, "%dth", i); pplObjStr(&OUTPUT,0,1,out); } void pplfunc_pow (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { ppl_uaPow(c, &in[0], &in[1], &OUTPUT, status, errType, errText); } void pplfunc_prime (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "prime(x)"; CHECK_NEEDINT(in[0], "x", "function's argument must be an integer in the range"); pplObjBool(&OUTPUT,0,0); { long x = floor(in[0].real), m, n; if (x<53) // Hardcode primes less than 53 { if ((x==2)||(x==3)||(x==5)||(x==7)||(x==11)||(x==13)||(x==17)||(x==19)||(x==23)||(x==29)||(x==31)||(x==37)||(x==41)||(x==43)||(x==47)) { OUTPUT.real = 1; return; } else return; } if (((x%2)==0)||((x%3)==0)||((x%5)==0)||((x%7)==0)) return; m = sqrt(x); for (n=11; n<=m; n+=6) { if ((x% n )==0) return; if ((x%(n+2))==0) return; } OUTPUT.real = 1; } CHECK_OUTPUT_OKAY; } void pplfunc_primefactors(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj v; list *l; int i,n=(int)in[0].real; char *FunctionDescription = "primeFactors(x)"; CHECK_NEEDINT(in[0], "x", "function's argument must be"); if (in[0].real < 1) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; *errType=ERR_RANGE; sprintf(errText, "The %s function's argument must be in the range 1 <= x < %d.",FunctionDescription,INT_MAX); return; } else { NULL_OUTPUT; } } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; for (i=2; i<=sqrt(n); i++) { int prime=1; if (i<53) prime=(i==2)||(i==3)||(i==5)||(i==7)||(i==11)||(i==13)||(i==17)||(i==19)||(i==23)||(i==29)||(i==31)||(i==37)||(i==41)||(i==43)||(i==47); else if (((i%2)==0)||((i%3)==0)||((i%5)==0)||((i%7)==0)) prime=0; else { int t, tm = sqrt(i); for (t=11; ((t<=tm)&&prime); t+=6) { if ((i% t )==0) prime=0; if ((i%(t+2))==0) prime=0; } prime=1; } if (!prime) continue; while (n%i==0) { pplObjNum(&v,0,i,0); ppl_listAppendCpy(l, &v, sizeof(v)); if ((n/=i)==1) break; } } if (n!=1) { pplObjNum(&v,0,n,0); ppl_listAppendCpy(l, &v, sizeof(v)); } return; } void pplfunc_radians (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "radians(x)"; int i; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); if (in[0].dimensionless) { OUTPUT.real = ppl_rads(in[0].real); } else { OUTPUT.real = in[0].real; } CHECK_OUTPUT_OKAY; } void pplfunc_raise (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "raise(e,s)"; if (nArgs!=2) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The %s function expects two input arguments.", FunctionDescription); return; } if (in[0].objType!=PPLOBJ_EXC) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The first argument to the %s function should be an exception object; supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if (in[1].objType!=PPLOBJ_STR) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The second argument to the %s function should be a string object; supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[1].objType]); return; } *status=1; *errType=(int)round(in[0].real); strncpy(errText, in[1].auxil, FNAME_LENGTH); errText[FNAME_LENGTH-1]='\0'; return; } void pplfunc_range (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "range([f],l,[s])"; double start, end, step, n; int i; if (nArgs>1) { CHECK_2INPUT_DIMMATCH; } if (nArgs>2) { in++; CHECK_2INPUT_DIMMATCH; in--; } if (nArgs==1) { start=0; end=in[0].real; step=1; } else if (nArgs==2) { start=in[0].real; end=in[1].real; step=1; } else { start=in[0].real; end=in[1].real; step=in[2].real; } n = ceil((end-start) / step); if ((!gsl_finite(n))||(n>INT_MAX)) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText,"Invalid step size."); return; } if (n<0) n=0; if (pplObjVector(&OUTPUT,0,1,n)==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText,"Out of memory."); return; } for (i=0; iv, i, start+i*step); ppl_unitsDimCpy(&OUTPUT, &in[0]); } void pplfunc_real (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "Re(z)"; OUTPUT.real = in[0].real; CHECK_OUTPUT_OKAY; ppl_unitsDimCpy(&OUTPUT, &in[0]); } void pplfunc_rgb (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,in[0].real,in[1].real,in[2].real,0); } void pplfunc_romanNum (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "romanNumeral(n)"; char *h[] = {"", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"}; char *t[] = {"", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"}; char *o[] = {"", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"}; char *out; int n, p=0; CHECK_NEEDINT(in[0], "n", "function's input must be an integer"); if ((in[0].real<1) || (in[0].real>10000)) { *status=1; *errType=ERR_RANGE; sprintf(errText, "Argument to %s must be in the range 0= 1000) { out[p++]='M'; n-=1000; } strcpy(out+p, h[n/100]); p += strlen(out+p); n = n % 100; strcpy(out+p, t[n/10] ); p += strlen(out+p); n = n % 10; strcpy(out+p, o[n] ); p += strlen(out+p); out[p] = '\0'; pplObjStr(&OUTPUT,0,1,out); } void pplfunc_root (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj x1,x2; double tmpdbl; char *FunctionDescription = "root(z,n)"; unsigned char negated = 0; in++; CHECK_1INPUT_DIMLESS; // THIS IS CORRECT. Only check in[1] in--; if ((in[1].flagComplex) || (in[1].real < 2) || (in[1].real >= INT_MAX)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status = 1; sprintf(errText, "The %s %s in the range 2 <= n < %d.",FunctionDescription,"function's second argument must be an integer in the range",INT_MAX); return; } else { NULL_OUTPUT; } } x1=in[0]; if (x1.real < 0.0) { negated=1; x1.real=-x1.real; if (x1.imag!=0.0) x1.imag=-x1.imag; } pplObjNum(&x2, 0, 1.0 / floor(in[1].real), 0); ppl_uaPow(c, &x1, &x2, &OUTPUT, status, errType, errText); if (*status) return; if (negated) { if (fmod(floor(in[1].real) , 2) == 1) { OUTPUT.real=-OUTPUT.real; if (OUTPUT.imag!=0.0) OUTPUT.imag=-OUTPUT.imag; } else { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { QUERY_OUT_OF_RANGE; } else { tmpdbl = OUTPUT.imag; OUTPUT.imag = OUTPUT.real; OUTPUT.real = -tmpdbl; OUTPUT.flagComplex = !ppl_dblEqual(OUTPUT.imag, 0); if (!OUTPUT.flagComplex) OUTPUT.imag=0.0; // Enforce that real numbers have positive zero imaginary components } } } CHECK_OUTPUT_OKAY; } void pplfunc_round (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "round(x)"; OUTPUT.real = round(in[0].real); CHECK_OUTPUT_OKAY; } void pplfunc_sec (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sec(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_sec(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_sech (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sech(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_sech(z); CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; } void pplfunc_sgn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { OUTPUT.real = ppl_sgn(in[0].real); } void pplfunc_sin (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sin(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_sin(z); CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = sin(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } void pplfunc_sinc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sinc(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); if ((in[0].real==0) && (in[0].imag==0)) { OUTPUT.real = 1.0; } else { IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real, in[0].imag); z=gsl_complex_sin(z); CLEANUP_GSLCOMPLEX; ppl_uaDiv(c, &OUTPUT, &in[0], &OUTPUT, status, errType, errText); } ELSE_REAL { OUTPUT.real = sin(in[0].real)/in[0].real; } ENDIF } CHECK_OUTPUT_OKAY; } void pplfunc_sinh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sinh(z)"; int i; gsl_complex z; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "an angle", UNIT_ANGLE, 1); IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_sinh(z); CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = sinh(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } void pplfunc_sqrt (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sqrt(z)"; int i; gsl_complex z; IF_1COMPLEX { GSL_SET_COMPLEX(&z,in[0].real,in[0].imag); z=gsl_complex_sqrt(z); } ELSE_REAL { z=gsl_complex_sqrt_real(in[0].real); } ENDIF CLEANUP_GSLCOMPLEX; CHECK_OUTPUT_OKAY; OUTPUT.dimensionless = in[0].dimensionless; OUTPUT.tempType = in[0].tempType; for (i=0; iv; for (i=0; isize; i++) acc += gsl_vector_get(v,i); pplObjNum(&OUTPUT,0,acc,0); } else if ((nArgs==1)&&(in[0].objType==PPLOBJ_MAT)) { int i,j; double acc=0; gsl_matrix *m=((pplMatrix *)(in[0].auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) acc += gsl_matrix_get(m,i,j); pplObjNum(&OUTPUT,0,acc,0); } else { int i; pplObj acc, acc2; pplObjCpy(&acc2, &in[0], 0, 0, 1); memcpy(&acc, &acc2, sizeof(pplObj)); for (i=1; i.",FunctionDescription,pplObjTypeNames[in[0].objType]); *errType=ERR_TYPE; *status=1; return; } outstr = (char *)malloc(LSTR_LENGTH); if (outstr==NULL) { sprintf(errText,"Out of memory."); *errType=ERR_MEMORY; *status=1; return; } ppl_texify_generic(c, instr, -1, &inlen, outstr, LSTR_LENGTH, NULL, NULL); pplObjStr(&OUTPUT,0,1,outstr); if (inlen < strlen(instr)) { sprintf(errText,"Unexpected trailing matter at the end of texified expression (character position %d).",inlen); *errType=ERR_SYNTAX; *status=1; return; } return; } void pplfunc_texifyText (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "texifyText(s)"; char *instr = (char*)in[0].auxil; char *outstr; if (nArgs != 1) { sprintf(errText,"The %s function takes exactly one argument; %d supplied.",FunctionDescription,nArgs); *errType=ERR_TYPE; *status=1; return; } if (in[0].objType!=PPLOBJ_STR) { sprintf(errText,"The %s requires a single string argument; supplied argument had type <%s>.",FunctionDescription,pplObjTypeNames[in[0].objType]); *errType=ERR_TYPE; *status=1; return; } outstr = (char *)malloc(LSTR_LENGTH); if (outstr==NULL) { sprintf(errText,"Out of memory."); *errType=ERR_MEMORY; *status=1; return; } ppl_texify_string(instr, outstr, -1, LSTR_LENGTH); pplObjStr(&OUTPUT,0,1,outstr); return; } void pplfunc_tophat (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "tophat(x,sigma)"; CHECK_2INPUT_DIMMATCH; if ( fabs(in[0].real) <= fabs(in[1].real) ) OUTPUT.real = 1.0; } void pplfunc_typeOf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObjCpy(&OUTPUT,&pplObjPrototypes[in[0].objType],0,0,1); OUTPUT.self_lval = NULL; } void pplfunc_zernike (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i; char *FunctionDescription = "zernike(n,m,r,phi)"; CHECK_3INPUT_DIMLESS; CHECK_NEEDINT (in[0], "n", "function can only evaluate Zernike polynomials"); CHECK_NEEDSINT(in[1], "m", "function can only evaluate Zernike polynomials"); CHECK_DIMLESS_OR_HAS_UNIT(in[3], "fourth", "an angle", UNIT_ANGLE, 1); { int n,m,ms , sgn=1; double r; n = in[0].real; ms = in[1].real; m = abs(ms); r = in[2].real; if (m>n) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The function %s is only defined for -n<=m<=n.", FunctionDescription); return; } else { NULL_OUTPUT; } } if ((r<0)||(r>1)) { OUTPUT.real = GSL_NAN; // Defined only within the unit disk } else { if ((n%2)!=(m%2)) return; // Defined to be zero for (i=0; i<(1+(n-m)/2); i++) { OUTPUT.real += sgn * gsl_sf_fact(n-i) / ( gsl_sf_fact(i) * gsl_sf_fact((n+m)/2-i) * gsl_sf_fact((n-m)/2-i) ) * pow(r , n-2*i); sgn*=-1; } if (ms>0) OUTPUT.real *= cos(m*in[3].real); else if (ms<0) OUTPUT.real *= sin(m*in[3].real); } } CHECK_OUTPUT_OKAY; } void pplfunc_zernikeR (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i; char *FunctionDescription = "zernikeR(n,m,r)"; CHECK_NEEDINT (in[0], "n", "function can only evaluate Zernike polynomials"); CHECK_NEEDSINT(in[1], "m", "function can only evaluate Zernike polynomials"); { int n,m,ms , sgn=1; double r; n = in[0].real; ms = in[1].real; m = abs(ms); r = in[2].real; if (m>n) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The function %s is only defined for -n<=m<=n.", FunctionDescription); return; } else { NULL_OUTPUT; } } if ((r<0)||(r>1)) { OUTPUT.real = GSL_NAN; // Defined only within the unit disk } else { if ((n%2)!=(m%2)) return; // Defined to be zero for (i=0; i<(1+(n-m)/2); i++) { OUTPUT.real += sgn * gsl_sf_fact(n-i) / ( gsl_sf_fact(i) * gsl_sf_fact((n+m)/2-i) * gsl_sf_fact((n-m)/2-i) ) * pow(r , n-2*i); sgn*=-1; } } } CHECK_OUTPUT_OKAY; } void pplfunc_zeta (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "zeta(z)"; gsl_complex zi,z; IF_1COMPLEX { GSL_SET_COMPLEX(&zi,in[0].real,in[0].imag); riemann_zeta_complex(zi,&z,status,errText); if (*status) return; CLEANUP_GSLCOMPLEX; } ELSE_REAL { OUTPUT.real = gsl_sf_zeta(in[0].real); } ENDIF CHECK_OUTPUT_OKAY; } pyxplot-0.9.2/src/defaultObjs/moduleOs.h0000664000175000017500000000716012026340554016621 0ustar dcf21dcf21// moduleOs.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleOs.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_OS_H #define _PPL_MODULE_OS_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_osChdir (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetCwd (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetEgid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetEuid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetGid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetPid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetPgrp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetPpid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetUid (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetHome (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetHost (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetLogin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGetRealName(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osGlob (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPopen (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osStat (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osSystem (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osTmpfile (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osUname (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathExists(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathFilesize(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathATime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathCTime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathMTime(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathExpandUser(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_osPathJoin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/moduleAst.h0000664000175000017500000000356312026340554016772 0ustar dcf21dcf21// moduleAst.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleAst.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_MODULE_AST_H #define _PPL_MODULE_AST_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplfunc_Lcdm_age (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_angscale(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_DA (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_DL (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_DM (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_t (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_Lcdm_z (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_moonphase (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sidereal_time(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/defaultVars.h0000664000175000017500000000176012026340554017312 0ustar dcf21dcf21// defaultVars.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultVars.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _DEFAULTVARS_H #define _DEFAULTVARS_H 1 #define NASA_MG_SUN 1.32712440018e20 #define NASA_G 6.67259e-11 #include "userspace/context.h" void ppl_makeDefaultVars(ppl_context *out); #endif pyxplot-0.9.2/src/defaultObjs/moduleFractals.c0000664000175000017500000000500712026340554017770 0ustar dcf21dcf21// moduleFractals.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: moduleFractals.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include "coreUtils/dict.h" #include "settings/settings.h" #include "stringTools/asciidouble.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "defaultObjs/moduleFractals.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" void pplfunc_julia (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "julia(z,cz,MaxIter)"; CHECK_NEEDLONG(in[2], "MaxIter", "function's third argument must be"); { double y = in[0].imag , x = in[0].real, x2; double cy = in[1].imag , cx = in[1].real; long MaxIter=(long)(in[2].real), iter; for (iter=0; ((iter // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultFuncs.h 1299 2012-08-31 23:32:22Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_DEFAULT_FUNCTIONS_H #define _PPL_DEFAULT_FUNCTIONS_H 1 #include "coreUtils/dict.h" #include "settings/settings.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" void ppl_addMagicFunction(dict *n, char *name, int id, char *shortdesc, char *latex, char *desc); pplFunc *ppl_addSystemFunc (dict *n, char *name, int minArgs, int maxArgs, int numOnly, int notNan, int realOnly, int dimlessOnly, void *fn, char *shortdesc, char *latex, char *desc); void ppl_addSystemMethod (dict *n, char *name, int minArgs, int maxArgs, int numOnly, int notNan, int realOnly, int dimlessOnly, void *fn, char *shortdesc, char *latex, char *desc); void pplfunc_abs (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acos (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acosh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acoth (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acsc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_acsch (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_airy_ai (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_airy_ai_diff(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_airy_bi (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_airy_bi_diff(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_arg (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_asec (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_asech (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_asin (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_asinh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_atan (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_atanh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_atan2 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besseli (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselI (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselj (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselJ (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselk (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselK (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_bessely (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_besselY (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_beta (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_call (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ceil (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_chr (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_classOf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cmp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cmyk (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_conjugate (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_copy (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cos (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cosh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_coth (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_cross (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_csc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_csch (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_degrees (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_deepcopy (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ellK (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ellE (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ellP (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_erf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_erfc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_eval (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_exp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_expm1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_expint (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_factors (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_finite (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_floor (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gamma (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gcd (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_globals (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_gray (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_heaviside (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hsb (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hyperg_0F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hyperg_1F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hyperg_2F0 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hyperg_2F1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hyperg_U (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_hypot (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_imag (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_jacobi_cn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_jacobi_dn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_jacobi_sn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lambert_W0 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lambert_W1 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lcm (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ldexp (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_legendreP (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_legendreQ (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_len (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_locals (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_log (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_log10 (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_logn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_lrange (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_max (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_min (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_mod (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_open (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ord (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_ordinal (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_pow (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_prime (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_primefactors(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_radians (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_raise (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_range (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_rgb (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_real (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_romanNum (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_root (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_round (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sec (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sech (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sgn (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sin (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sinc (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sinh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sqrt (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_sum (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tan (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tanh (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_texify (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_texifyText (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_tophat (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_typeOf (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_zernike (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_zernikeR (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); void pplfunc_zeta (ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/defaultObjs/defaultUnits.c0000664000175000017500000033654512026340554017510 0ustar dcf21dcf21// defaultUnits.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: defaultUnits.c 1273 2012-07-20 00:18:37Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "userspace/context.h" #include "defaultObjs/defaultUnits.h" #include "defaultObjs/defaultVars.h" void ppl_makeDefaultUnits(ppl_context *context) { int i=0,j=0; int unit_pos = 0; unit *unit_database; context->unit_database = (unit *)malloc(UNITS_MAX*sizeof(unit)); if (context->unit_database == NULL) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Out of memory error whilst trying to malloc units database."); exit(1); } unit_database = context->unit_database; context->unit_PreferredUnits = ppl_listInit(1); if (context->unit_PreferredUnits == NULL) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Out of memory error whilst trying to malloc units database."); exit(1); } context->unit_PreferredUnits_default = ppl_listInit(1); if (context->unit_PreferredUnits_default == NULL) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Out of memory error whilst trying to malloc units database."); exit(1); } context->unit_pos = 0; context->baseunit_pos = UNIT_FIRSTUSER; // Set up database of known units for (i=0;itempTypeMultiplier[unit_database[unit_pos].tempType] = unit_database[unit_pos].multiplier; context->tempTypeOffset [unit_database[unit_pos].tempType] = unit_database[unit_pos].offset; unit_pos++; unit_database[unit_pos].nameAs = "R"; // Rankin unit_database[unit_pos].nameAp = "R"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "rankin"; unit_database[unit_pos].nameFp = "rankin"; unit_database[unit_pos].quantity = "temperature"; unit_database[unit_pos].tempType = 2; unit_database[unit_pos].multiplier = 5.0/9.0; unit_database[unit_pos].exponent[UNIT_TEMPERATURE]=1; context->tempTypeMultiplier[unit_database[unit_pos].tempType] = unit_database[unit_pos].multiplier; context->tempTypeOffset [unit_database[unit_pos].tempType] = unit_database[unit_pos].offset; unit_pos++; unit_database[unit_pos].nameAs = "oC"; // oC unit_database[unit_pos].nameAp = "oC"; unit_database[unit_pos].nameLs = "^\\circ C"; unit_database[unit_pos].nameLp = "^\\circ C"; unit_database[unit_pos].nameFs = "degree_celsius"; unit_database[unit_pos].nameFp = "degrees_celsius"; unit_database[unit_pos].alt1 = "degree_centigrade"; unit_database[unit_pos].alt2 = "degrees_centigrade"; unit_database[unit_pos].alt3 = "centigrade"; unit_database[unit_pos].alt4 = "celsius"; unit_database[unit_pos].quantity = "temperature"; unit_database[unit_pos].tempType = 3; unit_database[unit_pos].offset = 273.15; unit_database[unit_pos].exponent[UNIT_TEMPERATURE]=1; context->tempTypeMultiplier[unit_database[unit_pos].tempType] = unit_database[unit_pos].multiplier; context->tempTypeOffset [unit_database[unit_pos].tempType] = unit_database[unit_pos].offset; unit_pos++; unit_database[unit_pos].nameAs = "oF"; // oF unit_database[unit_pos].nameAp = "oF"; unit_database[unit_pos].nameLs = "^\\circ F"; unit_database[unit_pos].nameLp = "^\\circ F"; unit_database[unit_pos].nameFs = "degree_fahrenheit"; unit_database[unit_pos].nameFp = "degrees_fahrenheit"; unit_database[unit_pos].alt1 = "fahrenheit"; unit_database[unit_pos].quantity = "temperature"; unit_database[unit_pos].tempType = 4; unit_database[unit_pos].multiplier = 5.0/9.0; unit_database[unit_pos].offset = 459.67 * 5.0/9.0; unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_TEMPERATURE]=1; context->tempTypeMultiplier[unit_database[unit_pos].tempType] = unit_database[unit_pos].multiplier; context->tempTypeOffset [unit_database[unit_pos].tempType] = unit_database[unit_pos].offset; unit_pos++; unit_database[unit_pos].nameAs = "mol"; // mole unit_database[unit_pos].nameAp = "mol"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "mole"; unit_database[unit_pos].nameFp = "moles"; unit_database[unit_pos].quantity = "moles"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MOLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "cd"; // candela unit_database[unit_pos].nameAp = "cd"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "candela"; unit_database[unit_pos].nameFp = "candelas"; unit_database[unit_pos].quantity = "light_intensity"; unit_database[unit_pos].multiplier = 1.0/683; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1.0/683; // 1 candela = 1/683 watt per steradian unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_ANGLE] =-2; unit_pos++; unit_database[unit_pos].nameAs = "candlepower"; // candlepower unit_database[unit_pos].nameAp = "candlepower"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "candlepower"; unit_database[unit_pos].nameFp = "candlepower"; unit_database[unit_pos].quantity = "light_intensity"; unit_database[unit_pos].multiplier = 1.0/683 * 0.981; unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_ANGLE] =-2; unit_pos++; unit_database[unit_pos].nameAs = "lm"; // lumen unit_database[unit_pos].nameAp = "lm"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "lumen"; unit_database[unit_pos].nameFp = "lumens"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].multiplier = 1.0/683; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "lx"; // lux unit_database[unit_pos].nameAp = "lx"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "lux"; unit_database[unit_pos].nameFp = "luxs"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].multiplier = 1.0/683; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "Jy"; // jansky unit_database[unit_pos].nameAp = "Jy"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "jansky"; unit_database[unit_pos].nameFp = "janskys"; unit_database[unit_pos].quantity = "flux_density"; unit_database[unit_pos].multiplier = 1e-26; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_MASS] = 1; // Watt per square meter per Hz (NOT per steradian!) unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "rad"; // radians unit_database[unit_pos].nameAp = "rad"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "radian"; unit_database[unit_pos].nameFp = "radians"; unit_database[unit_pos].quantity = "angle"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].si = unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_ANGLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "deg"; // degrees unit_database[unit_pos].nameAp = "deg"; unit_database[unit_pos].nameLs = "^\\circ"; unit_database[unit_pos].nameLp = "^\\circ"; unit_database[unit_pos].nameFs = "degree"; unit_database[unit_pos].nameFp = "degrees"; unit_database[unit_pos].quantity = "angle"; unit_database[unit_pos].multiplier = M_PI / 180; unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_ANGLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "rev"; // revolution unit_database[unit_pos].nameAp = "rev"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "revolution"; unit_database[unit_pos].nameFp = "revolutions"; unit_database[unit_pos].quantity = "angle"; unit_database[unit_pos].multiplier = 2 * M_PI; unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_ANGLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "arcmin"; // arcminute unit_database[unit_pos].nameAp = "arcmins"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "arcminute"; unit_database[unit_pos].nameFp = "arcminutes"; unit_database[unit_pos].quantity = "angle"; unit_database[unit_pos].multiplier = M_PI / 180 / 60; unit_database[unit_pos].exponent[UNIT_ANGLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "arcsec"; // arcsecond unit_database[unit_pos].nameAp = "arcsecs"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "arcsecond"; unit_database[unit_pos].nameFp = "arcseconds"; unit_database[unit_pos].quantity = "angle"; unit_database[unit_pos].multiplier = M_PI / 180 / 3600; unit_database[unit_pos].exponent[UNIT_ANGLE]=1; unit_pos++; unit_database[unit_pos].nameAs = "bit"; // bit unit_database[unit_pos].nameAp = "bits"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "bit"; unit_database[unit_pos].nameFp = "bits"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "euro"; // cost unit_database[unit_pos].nameAp = "euros"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "euro"; unit_database[unit_pos].nameFp = "euros"; unit_database[unit_pos].quantity = "cost"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_COST]=1; unit_pos++; // ------------- // Derived units // ------------- unit_database[unit_pos].nameAs = "dioptre"; // dioptre unit_database[unit_pos].nameAp = "dioptres"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "dioptre"; unit_database[unit_pos].nameFp = "dioptres"; unit_database[unit_pos].quantity = "lens_power"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].exponent[UNIT_LENGTH]=-1; unit_pos++; unit_database[unit_pos].nameAs = "mph"; // mile_per_hour unit_database[unit_pos].nameAp = "mph"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "mile_per_hour"; unit_database[unit_pos].nameFp = "miles_per_hour"; unit_database[unit_pos].quantity = "velocity"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_MILE / 3600; unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]= 1; unit_database[unit_pos].exponent[UNIT_TIME] =-1; unit_pos++; unit_database[unit_pos].nameAs = "kn"; // knot unit_database[unit_pos].nameAp = "kn"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "knot"; unit_database[unit_pos].nameFp = "knots"; unit_database[unit_pos].quantity = "velocity"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_KNOT; unit_database[unit_pos].exponent[UNIT_LENGTH]= 1; unit_database[unit_pos].exponent[UNIT_TIME] =-1; unit_pos++; unit_database[unit_pos].nameAs = "acre"; // acre unit_database[unit_pos].nameAp = "acres"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "acre"; unit_database[unit_pos].nameFp = "acres"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_ACRE; //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "rood"; // rood unit_database[unit_pos].nameAp = "roods"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "rood"; unit_database[unit_pos].nameFp = "roods"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_ACRE*0.25; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "are"; // are unit_database[unit_pos].nameAp = "ares"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "are"; unit_database[unit_pos].nameFp = "ares"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 100; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "barn"; // barn unit_database[unit_pos].nameAp = "barns"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "barn"; unit_database[unit_pos].nameFp = "barns"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 1e-28; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "hectare"; // hectare unit_database[unit_pos].nameAp = "hectares"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "hectare"; unit_database[unit_pos].nameFp = "hectares"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 1e4; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_mi"; // square mile unit_database[unit_pos].nameAp = "sq_mi"; unit_database[unit_pos].nameLs = "sq\\_mi"; unit_database[unit_pos].nameLp = "sq\\_mi"; unit_database[unit_pos].nameFs = "square_mile"; unit_database[unit_pos].nameFp = "square_miles"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = pow(GSL_CONST_MKSA_MILE,2); //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_km"; // square kilometer unit_database[unit_pos].nameAp = "sq_km"; unit_database[unit_pos].nameLs = "sq\\_km"; unit_database[unit_pos].nameLp = "sq\\_km"; unit_database[unit_pos].nameFs = "square_kilometer"; unit_database[unit_pos].nameFp = "square_kilometers"; unit_database[unit_pos].alt1 = "square_kilometre"; unit_database[unit_pos].alt2 = "square_kilometres"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 1e6; //unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_m"; // square meter unit_database[unit_pos].nameAp = "sq_m"; unit_database[unit_pos].nameLs = "sq\\_m"; unit_database[unit_pos].nameLp = "sq\\_m"; unit_database[unit_pos].nameFs = "square_meter"; unit_database[unit_pos].nameFp = "square_meters"; unit_database[unit_pos].alt1 = "square_metre"; unit_database[unit_pos].alt2 = "square_metres"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 1; //unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_cm"; // square centimeter unit_database[unit_pos].nameAp = "sq_cm"; unit_database[unit_pos].nameLs = "sq\\_cm"; unit_database[unit_pos].nameLp = "sq\\_cm"; unit_database[unit_pos].nameFs = "square_centimeter"; unit_database[unit_pos].nameFp = "square_centimeters"; unit_database[unit_pos].alt1 = "square_centimetre"; unit_database[unit_pos].alt2 = "square_centimetres"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = 1e-4; //unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_ft"; // square foot unit_database[unit_pos].nameAp = "sq_ft"; unit_database[unit_pos].nameLs = "sq\\_ft"; unit_database[unit_pos].nameLp = "sq\\_ft"; unit_database[unit_pos].nameFs = "square_foot"; unit_database[unit_pos].nameFp = "square_feet"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = pow(GSL_CONST_MKSA_FOOT,2); //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "sq_in"; // square inch unit_database[unit_pos].nameAp = "sq_in"; unit_database[unit_pos].nameLs = "sq\\_in"; unit_database[unit_pos].nameLp = "sq\\_in"; unit_database[unit_pos].nameFs = "square_inch"; unit_database[unit_pos].nameFp = "square_inches"; unit_database[unit_pos].quantity = "area"; unit_database[unit_pos].multiplier = pow(GSL_CONST_MKSA_INCH,2); //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=2; unit_pos++; unit_database[unit_pos].nameAs = "cubic_m"; // cubic meter unit_database[unit_pos].nameAp = "cubic_m"; unit_database[unit_pos].nameLs = "cubic\\_m"; unit_database[unit_pos].nameLp = "cubic\\_m"; unit_database[unit_pos].nameFs = "cubic_meter"; unit_database[unit_pos].nameFp = "cubic_meters"; unit_database[unit_pos].alt1 = "cubic_metre"; unit_database[unit_pos].alt2 = "cubic_metres"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 1; //unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "cubic_cm"; // cubic centimeter unit_database[unit_pos].nameAp = "cubic_cm"; unit_database[unit_pos].nameLs = "cubic\\_cm"; unit_database[unit_pos].nameLp = "cubic\\_cm"; unit_database[unit_pos].nameFs = "cubic_centimeter"; unit_database[unit_pos].nameFp = "cubic_centimeters"; unit_database[unit_pos].alt1 = "cubic_centimetre"; unit_database[unit_pos].alt2 = "cubic_centimetres"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 1e-6; //unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "cubic_ft"; // cubic foot unit_database[unit_pos].nameAp = "cubic_ft"; unit_database[unit_pos].nameLs = "cubic\\_ft"; unit_database[unit_pos].nameLp = "cubic\\_ft"; unit_database[unit_pos].nameFs = "cubic_foot"; unit_database[unit_pos].nameFp = "cubic_feet"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = pow(GSL_CONST_MKSA_FOOT,3); //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "cubic_in"; // cubic inch unit_database[unit_pos].nameAp = "cubic_in"; unit_database[unit_pos].nameLs = "cubic\\_in"; unit_database[unit_pos].nameLp = "cubic\\_in"; unit_database[unit_pos].nameFs = "cubic_inch"; unit_database[unit_pos].nameFp = "cubic_inches"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = pow(GSL_CONST_MKSA_INCH,3); //unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "l"; // litre unit_database[unit_pos].nameAp = "l"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "litre"; unit_database[unit_pos].nameFp = "litres"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].minPrefix = -3; unit_database[unit_pos].multiplier = 1e-3; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "fl_oz_UK"; // UK fluid ounce unit_database[unit_pos].nameAp = "fl_oz_UK"; unit_database[unit_pos].nameLs = "fl\\_oz\\_UK"; unit_database[unit_pos].nameLp = "fl\\_oz\\_UK"; unit_database[unit_pos].nameFs = "fluid_ounce_UK"; unit_database[unit_pos].nameFp = "fluid_ounce_UK"; unit_database[unit_pos].comment = "UK imperial"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 28.4130625e-6; //unit_database[unit_pos].imperial = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "fl_oz_US"; // US fluid ounce unit_database[unit_pos].nameAp = "fl_oz_US"; unit_database[unit_pos].nameLs = "fl\\_oz\\_US"; unit_database[unit_pos].nameLp = "fl\\_oz\\_US"; unit_database[unit_pos].nameFs = "fluid_ounce_US"; unit_database[unit_pos].nameFp = "fluid_ounce_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_FLUID_OUNCE; //unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "pint_UK"; // UK pint unit_database[unit_pos].nameAp = "pints_UK"; unit_database[unit_pos].nameLs = "pint\\_UK"; unit_database[unit_pos].nameLp = "pints\\_UK"; unit_database[unit_pos].nameFs = "pint_UK"; unit_database[unit_pos].nameFp = "pints_UK"; unit_database[unit_pos].comment = "UK imperial"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 568.26125e-6; //unit_database[unit_pos].imperial = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "pint_US"; // US pint unit_database[unit_pos].nameAp = "pints_US"; unit_database[unit_pos].nameLs = "pint\\_US"; unit_database[unit_pos].nameLp = "pints\\_US"; unit_database[unit_pos].nameFs = "pint_US"; unit_database[unit_pos].nameFp = "pints_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_PINT; //unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "quart_UK"; // UK quart unit_database[unit_pos].nameAp = "quarts_UK"; unit_database[unit_pos].nameLs = "quart\\_UK"; unit_database[unit_pos].nameLp = "quarts\\_UK"; unit_database[unit_pos].nameFs = "quart_UK"; unit_database[unit_pos].nameFp = "quarts_UK"; unit_database[unit_pos].comment = "UK imperial"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 1136.5225e-6; //unit_database[unit_pos].imperial = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "quart_US"; // US quart unit_database[unit_pos].nameAp = "quarts_US"; unit_database[unit_pos].nameLs = "quart\\_US"; unit_database[unit_pos].nameLp = "quarts\\_US"; unit_database[unit_pos].nameFs = "quart_US"; unit_database[unit_pos].nameFp = "quarts_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_QUART; //unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "gallon_UK"; // UK gallon unit_database[unit_pos].nameAp = "gallons_UK"; unit_database[unit_pos].nameLs = "gallon\\_UK"; unit_database[unit_pos].nameLp = "gallons\\_UK"; unit_database[unit_pos].nameFs = "gallon_UK"; unit_database[unit_pos].nameFp = "gallons_UK"; unit_database[unit_pos].comment = "UK imperial"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_UK_GALLON; //unit_database[unit_pos].imperial = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "gallon_US"; // US gallon unit_database[unit_pos].nameAp = "gallons_US"; unit_database[unit_pos].nameLs = "gallon\\_US"; unit_database[unit_pos].nameLp = "gallons\\_US"; unit_database[unit_pos].nameFs = "gallon_US"; unit_database[unit_pos].nameFp = "gallons_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_US_GALLON; //unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "bushel_UK"; // UK bushel unit_database[unit_pos].nameAp = "bushels_UK"; unit_database[unit_pos].nameLs = "bushel\\_UK"; unit_database[unit_pos].nameLp = "bushels\\_UK"; unit_database[unit_pos].nameFs = "bushel_UK"; unit_database[unit_pos].nameFp = "bushels_UK"; unit_database[unit_pos].comment = "UK imperial"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 36.36872e-3; //unit_database[unit_pos].imperial = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "bushel_US"; // US bushel unit_database[unit_pos].nameAp = "bushels_US"; unit_database[unit_pos].nameLs = "bushel\\_US"; unit_database[unit_pos].nameLp = "bushels\\_US"; unit_database[unit_pos].nameFs = "bushel_US"; unit_database[unit_pos].nameFp = "bushels_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 35.23907016688e-3; //unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "cup_US"; // US cup unit_database[unit_pos].nameAp = "cups_US"; unit_database[unit_pos].nameLs = "cup\\_US"; unit_database[unit_pos].nameLp = "cups\\_US"; unit_database[unit_pos].nameFs = "cup_US"; unit_database[unit_pos].nameFp = "cups_US"; unit_database[unit_pos].comment = "US customary"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_CUP; unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "bath"; // bath unit_database[unit_pos].nameAp = "baths"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "bath"; unit_database[unit_pos].nameFp = "baths"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 22e-3; unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "homer"; // homer unit_database[unit_pos].nameAp = "homers"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "homer"; unit_database[unit_pos].nameFp = "homers"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 220e-3; unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "teaspoon"; // teaspoon unit_database[unit_pos].nameAp = "teaspoons"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "teaspoon"; unit_database[unit_pos].nameFp = "teaspoons"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 5e-6; // 5 mL unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "tablespoon"; // tablespoon unit_database[unit_pos].nameAp = "tablespoons"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "tablespoon"; unit_database[unit_pos].nameFp = "tablespoons"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 15e-6; // 15 mL unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "firkin_UK_ale"; // firkin of ale unit_database[unit_pos].nameAp = "firkins_UK_ale"; unit_database[unit_pos].nameLs = "firkin\\_UK\\_ale"; unit_database[unit_pos].nameLp = "firkins\\_UK\\_ale"; unit_database[unit_pos].nameFs = "firkin_UK_ale"; unit_database[unit_pos].nameFp = "firkins_UK_ale"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 40.91481e-3; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "firkin_UK_wine"; // firkin of wine unit_database[unit_pos].nameAp = "firkins_UK_wine"; unit_database[unit_pos].nameLs = "firkin\\_UK\\_wine"; unit_database[unit_pos].nameLp = "firkins\\_UK\\_wine"; unit_database[unit_pos].nameFs = "firkin_wine"; unit_database[unit_pos].nameFp = "firkins_wine"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 318e-3; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "kilderkin_UK_ale"; // kilderkin of ale unit_database[unit_pos].nameAp = "kilderkins_UK_ale"; unit_database[unit_pos].nameLs = "kilderkin\\_UK\\_ale"; unit_database[unit_pos].nameLp = "kilderkins\\_UK\\_ale"; unit_database[unit_pos].nameFs = "kilderkin_UK_ale"; unit_database[unit_pos].nameFp = "kilderkins_UK_ale"; unit_database[unit_pos].quantity = "volume"; unit_database[unit_pos].multiplier = 81.82962e-3; unit_database[unit_pos].exponent[UNIT_LENGTH]=3; unit_pos++; unit_database[unit_pos].nameAs = "sterad"; // steradians unit_database[unit_pos].nameAp = "sterad"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "steradian"; unit_database[unit_pos].nameFp = "steradians"; unit_database[unit_pos].quantity = "solidangle"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].si = unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_ANGLE]=2; unit_pos++; unit_database[unit_pos].nameAs = "sqdeg"; // square degrees unit_database[unit_pos].nameAp = "sqdeg"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "square_degree"; unit_database[unit_pos].nameFp = "square_degrees"; unit_database[unit_pos].quantity = "solidangle"; unit_database[unit_pos].multiplier = pow(M_PI/180, 2); unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_ANGLE]=2; unit_pos++; unit_database[unit_pos].nameAs = "Hz"; // hertz unit_database[unit_pos].nameAp = "Hz"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "hertz"; unit_database[unit_pos].nameFp = "hertz"; unit_database[unit_pos].quantity = "frequency"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].notToBeCompounded = 1; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_TIME]=-1; unit_pos++; unit_database[unit_pos].nameAs = "Bq"; // becquerel unit_database[unit_pos].nameAp = "Bq"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "becquerel"; unit_database[unit_pos].nameFp = "becquerel"; unit_database[unit_pos].quantity = "frequency"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_TIME]=-1; unit_pos++; unit_database[unit_pos].nameAs = "B"; // bytes unit_database[unit_pos].nameAp = "B"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "byte"; unit_database[unit_pos].nameFp = "bytes"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 8.0; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "Kib"; // kibibits unit_database[unit_pos].nameAp = "Kib"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "kibibit"; unit_database[unit_pos].nameFp = "kibibits"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "KiB"; // kibibytes unit_database[unit_pos].nameAp = "KiB"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "kibibyte"; unit_database[unit_pos].nameFp = "kibibytes"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0 * 8.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "Mib"; // mebibits unit_database[unit_pos].nameAp = "Mib"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "mebibit"; unit_database[unit_pos].nameFp = "mebibits"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0 * 1024.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "MiB"; // mebibytes unit_database[unit_pos].nameAp = "MiB"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "mebibyte"; unit_database[unit_pos].nameFp = "mebibytes"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0 * 1024.0 * 8.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "Gib"; // gibibits unit_database[unit_pos].nameAp = "Gib"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "gibibit"; unit_database[unit_pos].nameFp = "gibibits"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0 * 1024.0 * 1024.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "GiB"; // gibibytes unit_database[unit_pos].nameAp = "GiB"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "gibibyte"; unit_database[unit_pos].nameFp = "gibibytes"; unit_database[unit_pos].quantity = "information_content"; unit_database[unit_pos].multiplier = 1024.0 * 1024.0 * 1024.0 * 8.0; unit_database[unit_pos].exponent[UNIT_BIT]=1; unit_pos++; unit_database[unit_pos].nameAs = "N"; // newton unit_database[unit_pos].nameAp = "N"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "newton"; unit_database[unit_pos].nameFp = "newtons"; unit_database[unit_pos].quantity = "force"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "dyn"; // dyne unit_database[unit_pos].nameAp = "dyn"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "dyne"; unit_database[unit_pos].nameFp = "dynes"; unit_database[unit_pos].quantity = "force"; unit_database[unit_pos].multiplier = 1e-5; unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "lbf"; // pound force unit_database[unit_pos].nameAp = "lbf"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "pound_force"; unit_database[unit_pos].nameFp = "pounds_force"; unit_database[unit_pos].quantity = "force"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_POUND_FORCE; unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "Pa"; // pascal unit_database[unit_pos].nameAp = "Pa"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "pascal"; unit_database[unit_pos].nameFp = "pascals"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "Ba"; // barye unit_database[unit_pos].nameAp = "Ba"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "barye"; unit_database[unit_pos].nameFp = "baryes"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = 0.1; unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "atm"; // atmosphere unit_database[unit_pos].nameAp = "atms"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "atmosphere"; unit_database[unit_pos].nameFp = "atmospheres"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_STD_ATMOSPHERE; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "bar"; // bar unit_database[unit_pos].nameAp = "bars"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "bar"; unit_database[unit_pos].nameFp = "bars"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = 1e5; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "psi"; // psi unit_database[unit_pos].nameAp = "psi"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "pound_per_square_inch"; unit_database[unit_pos].nameFp = "pounds_per_square_inch"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_PSI; unit_database[unit_pos].imperial = unit_database[unit_pos].us = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "inHg"; // inch of mercury unit_database[unit_pos].nameAp = "inHg"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "inch_of_mercury"; unit_database[unit_pos].nameFp = "inches_of_mercury"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_INCH_OF_MERCURY; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "inAq"; // inch of water unit_database[unit_pos].nameAp = "inAq"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "inch_of_water"; unit_database[unit_pos].nameFp = "inches_of_water"; unit_database[unit_pos].quantity = "pressure"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_INCH_OF_WATER; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "J"; // joule unit_database[unit_pos].nameAp = "J"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "joule"; unit_database[unit_pos].nameFp = "joules"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "eV"; // electronvolt unit_database[unit_pos].nameAp = "eV"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "electronvolt"; unit_database[unit_pos].nameFp = "electronvolts"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_ELECTRON_VOLT; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "BeV"; // billion electronvolts unit_database[unit_pos].nameAp = "BeV"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "billion_electronvolts"; unit_database[unit_pos].nameFp = "billion_electronvolts"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = 1e9 * GSL_CONST_MKSA_ELECTRON_VOLT; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "erg"; // erg unit_database[unit_pos].nameAp = "erg"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "erg"; unit_database[unit_pos].nameFp = "ergs"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = 1e-7; unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "cal"; // calorie unit_database[unit_pos].nameAp = "cal"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "calorie"; unit_database[unit_pos].nameFp = "calories"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_CALORIE; unit_database[unit_pos].maxPrefix = 3; unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "kWh"; // Kilowatt hour unit_database[unit_pos].nameAp = "kWh"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "kilowatt_hour"; unit_database[unit_pos].nameFp = "kilowatt_hours"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = 3.6e6; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "BTU"; // British Thermal Unit unit_database[unit_pos].nameAp = "BTU"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "British Thermal Unit"; unit_database[unit_pos].nameFp = "British Thermal Units"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_BTU; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "therm"; // Therm unit_database[unit_pos].nameAp = "therms"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "therm"; unit_database[unit_pos].nameFp = "therms"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_THERM; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "W"; // watt unit_database[unit_pos].nameAp = "W"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "watt"; unit_database[unit_pos].nameFp = "watts"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].multiplier = 1; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "horsepower"; // horsepower unit_database[unit_pos].nameAp = "horsepower"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "horsepower"; unit_database[unit_pos].nameFp = "horsepower"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_HORSEPOWER; unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "Lsun"; // Solar luminosity unit_database[unit_pos].nameAp = "Lsun"; unit_database[unit_pos].nameLs = "L_\\odot"; unit_database[unit_pos].nameLp = "L_\\odot"; unit_database[unit_pos].nameFs = "solar_luminosity"; unit_database[unit_pos].nameFp = "solar_luminosities"; unit_database[unit_pos].alt1 = "Lsolar"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].multiplier = 3.839e26; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "clo"; // clo unit_database[unit_pos].nameAp = "clos"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "clo"; unit_database[unit_pos].nameFp = "clos"; unit_database[unit_pos].quantity = "thermal_insulation"; unit_database[unit_pos].multiplier = 0.154; unit_database[unit_pos].tempType = 1; unit_database[unit_pos].exponent[UNIT_MASS] =-1; unit_database[unit_pos].exponent[UNIT_TEMPERATURE] = 1; unit_database[unit_pos].exponent[UNIT_TIME] = 3; unit_pos++; unit_database[unit_pos].nameAs = "tog"; // tog unit_database[unit_pos].nameAp = "togs"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "tog"; unit_database[unit_pos].nameFp = "togs"; unit_database[unit_pos].quantity = "thermal_insulation"; unit_database[unit_pos].multiplier = 0.1; unit_database[unit_pos].tempType = 1; unit_database[unit_pos].exponent[UNIT_MASS] =-1; unit_database[unit_pos].exponent[UNIT_TEMPERATURE] = 1; unit_database[unit_pos].exponent[UNIT_TIME] = 3; unit_pos++; unit_database[unit_pos].nameAs = "Gy"; // gray unit_database[unit_pos].nameAp = "Gy"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "gray"; unit_database[unit_pos].nameFp = "gray"; unit_database[unit_pos].quantity = "radiation_dose"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "Sv"; // sievert unit_database[unit_pos].nameAp = "Sv"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "sievert"; unit_database[unit_pos].nameFp = "sieverts"; unit_database[unit_pos].quantity = "radiation_dose"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "kat"; // katal unit_database[unit_pos].nameAp = "kat"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "katal"; unit_database[unit_pos].nameFp = "katals"; unit_database[unit_pos].quantity = "catalytic_activity"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MOLE] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-1; unit_pos++; unit_database[unit_pos].nameAs = "P"; // poise unit_database[unit_pos].nameAp = "P"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "poise"; unit_database[unit_pos].nameFp = "poises"; unit_database[unit_pos].quantity = "viscosity"; unit_database[unit_pos].multiplier = GSL_CONST_MKSA_POISE; unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_database[unit_pos].exponent[UNIT_TIME] =-1; unit_pos++; unit_database[unit_pos].nameAs = "kayser"; // kayser unit_database[unit_pos].nameAp = "kaysers"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "kayser"; unit_database[unit_pos].nameFp = "kaysers"; unit_database[unit_pos].quantity = "wavenumber"; unit_database[unit_pos].multiplier = 100; unit_database[unit_pos].cgs = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-1; unit_pos++; unit_database[unit_pos].nameAs = "C"; // coulomb unit_database[unit_pos].nameAp = "C"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "coulomb"; unit_database[unit_pos].nameFp = "coulombs"; unit_database[unit_pos].quantity = "charge"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_TIME] = 1; unit_database[unit_pos].exponent[UNIT_CURRENT] = 1; unit_pos++; unit_database[unit_pos].nameAs = "V"; // volt unit_database[unit_pos].nameAp = "V"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "volt"; unit_database[unit_pos].nameFp = "volts"; unit_database[unit_pos].quantity = "potential"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; unit_database[unit_pos].nameAs = "ohm"; // ohm unit_database[unit_pos].nameAp = "ohms"; unit_database[unit_pos].nameLs = "\\Omega"; unit_database[unit_pos].nameLp = "\\Omega"; unit_database[unit_pos].nameFs = "ohm"; unit_database[unit_pos].nameFp = "ohms"; unit_database[unit_pos].quantity = "resistance"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_CURRENT] =-2; unit_pos++; unit_database[unit_pos].nameAs = "S"; // siemens unit_database[unit_pos].nameAp = "S"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "siemens"; unit_database[unit_pos].nameFp = "siemens"; unit_database[unit_pos].quantity = "conductance"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] =-1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-2; unit_database[unit_pos].exponent[UNIT_TIME] = 3; unit_database[unit_pos].exponent[UNIT_CURRENT] = 2; unit_pos++; unit_database[unit_pos].nameAs = "mho"; // mho unit_database[unit_pos].nameAp = "mhos"; unit_database[unit_pos].nameLs = "\\mho"; unit_database[unit_pos].nameLp = "\\mho"; unit_database[unit_pos].nameFs = "mho"; unit_database[unit_pos].nameFp = "mhos"; unit_database[unit_pos].quantity = "conductance"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].exponent[UNIT_MASS] =-1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-2; unit_database[unit_pos].exponent[UNIT_TIME] = 3; unit_database[unit_pos].exponent[UNIT_CURRENT] = 2; unit_pos++; unit_database[unit_pos].nameAs = "F"; // farad unit_database[unit_pos].nameAp = "F"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "farad"; unit_database[unit_pos].nameFp = "farad"; unit_database[unit_pos].quantity = "capacitance"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] =-2; unit_database[unit_pos].exponent[UNIT_MASS] =-1; unit_database[unit_pos].exponent[UNIT_TIME] = 4; unit_database[unit_pos].exponent[UNIT_CURRENT] = 2; unit_pos++; unit_database[unit_pos].nameAs = "H"; // henry unit_database[unit_pos].nameAp = "H"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "henry"; unit_database[unit_pos].nameFp = "henry"; unit_database[unit_pos].quantity = "inductance"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_database[unit_pos].exponent[UNIT_CURRENT] =-2; unit_pos++; unit_database[unit_pos].nameAs = "T"; // tesla unit_database[unit_pos].nameAp = "T"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "tesla"; unit_database[unit_pos].nameFp = "tesla"; unit_database[unit_pos].quantity = "magnetic_field"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; unit_database[unit_pos].nameAs = "G"; // gauss unit_database[unit_pos].nameAp = "G"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "gauss"; unit_database[unit_pos].nameFp = "gauss"; unit_database[unit_pos].quantity = "magnetic_field"; unit_database[unit_pos].multiplier = 1e-4; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; unit_database[unit_pos].nameAs = "Wb"; // weber unit_database[unit_pos].nameAp = "Wb"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "weber"; unit_database[unit_pos].nameFp = "weber"; unit_database[unit_pos].quantity = "magnetic_flux"; unit_database[unit_pos].multiplier = 1.0; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].si = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; unit_database[unit_pos].nameAs = "Mx"; // maxwell unit_database[unit_pos].nameAp = "Mx"; unit_database[unit_pos].nameLs = unit_database[unit_pos].nameAs; unit_database[unit_pos].nameLp = unit_database[unit_pos].nameAp; unit_database[unit_pos].nameFs = "maxwell"; unit_database[unit_pos].nameFp = "maxwell"; unit_database[unit_pos].quantity = "magnetic_flux"; unit_database[unit_pos].multiplier = 1e-8; unit_database[unit_pos].minPrefix = -24; unit_database[unit_pos].maxPrefix = 24; unit_database[unit_pos].cgs = unit_database[unit_pos].imperial = unit_database[unit_pos].us = unit_database[unit_pos].ancient = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; // Planck Units unit_database[unit_pos].nameAs = "L_planck"; // Planck Length unit_database[unit_pos].nameAp = "L_planck"; unit_database[unit_pos].nameLs = "L_P"; unit_database[unit_pos].nameLp = "L_P"; unit_database[unit_pos].nameFs = "planck_length"; unit_database[unit_pos].nameFp = "planck_lengths"; unit_database[unit_pos].quantity = "length"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1.61625281e-35; unit_database[unit_pos].exponent[UNIT_LENGTH]=1; unit_pos++; unit_database[unit_pos].nameAs = "M_planck"; // Planck Mass unit_database[unit_pos].nameAp = "M_planck"; unit_database[unit_pos].nameLs = "M_P"; unit_database[unit_pos].nameLp = "M_P"; unit_database[unit_pos].nameFs = "planck_mass"; unit_database[unit_pos].nameFp = "planck_masses"; unit_database[unit_pos].quantity = "mass"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 2.1764411e-8; unit_database[unit_pos].exponent[UNIT_MASS]=1; unit_pos++; unit_database[unit_pos].nameAs = "T_planck"; // Planck Time unit_database[unit_pos].nameAp = "T_planck"; unit_database[unit_pos].nameLs = "T_P"; unit_database[unit_pos].nameLp = "T_P"; unit_database[unit_pos].nameFs = "planck_time"; unit_database[unit_pos].nameFp = "planck_times"; unit_database[unit_pos].quantity = "time"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 5.3912427e-44; unit_database[unit_pos].exponent[UNIT_TIME]=1; unit_pos++; unit_database[unit_pos].nameAs = "Q_planck"; // Planck Charge unit_database[unit_pos].nameAp = "Q_planck"; unit_database[unit_pos].nameLs = "Q_P"; unit_database[unit_pos].nameLp = "Q_P"; unit_database[unit_pos].nameFs = "planck_charge"; unit_database[unit_pos].nameFp = "planck_charges"; unit_database[unit_pos].quantity = "charge"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1.87554587047e-18; unit_database[unit_pos].exponent[UNIT_CURRENT]=1; unit_database[unit_pos].exponent[UNIT_TIME] =1; unit_pos++; unit_database[unit_pos].nameAs = "Theta_planck"; // Planck Temperature unit_database[unit_pos].nameAp = "Theta_planck"; unit_database[unit_pos].nameLs = "\\Theta_P"; unit_database[unit_pos].nameLp = "\\Theta_P"; unit_database[unit_pos].nameFs = "planck_temperature"; unit_database[unit_pos].nameFp = "planck_temperature"; unit_database[unit_pos].quantity = "temperature"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1.41678571e32; unit_database[unit_pos].exponent[UNIT_TEMPERATURE]=1; unit_pos++; unit_database[unit_pos].nameAs = "p_planck"; // Planck Momentum unit_database[unit_pos].nameAp = "p_planck"; unit_database[unit_pos].nameLs = "p_P"; unit_database[unit_pos].nameLp = "p_P"; unit_database[unit_pos].nameFs = "planck_momentum"; unit_database[unit_pos].nameFp = "planck_momentum"; unit_database[unit_pos].quantity = "momentum"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 6.5248018674330712229902929; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]= 1; unit_database[unit_pos].exponent[UNIT_TIME] =-1; unit_pos++; unit_database[unit_pos].nameAs = "E_planck"; // Planck Energy unit_database[unit_pos].nameAp = "E_planck"; unit_database[unit_pos].nameLs = "E_P"; unit_database[unit_pos].nameLp = "E_P"; unit_database[unit_pos].nameFs = "planck_energy"; unit_database[unit_pos].nameFp = "planck_energy"; unit_database[unit_pos].quantity = "energy"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1956085069.7617356777191162109375; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]= 2; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "F_planck"; // Planck Force unit_database[unit_pos].nameAp = "F_planck"; unit_database[unit_pos].nameLs = "F_P"; unit_database[unit_pos].nameLp = "F_P"; unit_database[unit_pos].nameFs = "planck_force"; unit_database[unit_pos].nameFp = "planck_force"; unit_database[unit_pos].quantity = "force"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1.2102593465942594902618273e+44; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]= 1; unit_database[unit_pos].exponent[UNIT_TIME] =-2; unit_pos++; unit_database[unit_pos].nameAs = "P_planck"; // Planck Power unit_database[unit_pos].nameAp = "P_planck"; unit_database[unit_pos].nameLs = "P_P"; unit_database[unit_pos].nameLp = "P_P"; unit_database[unit_pos].nameFs = "planck_power"; unit_database[unit_pos].nameFp = "planck_power"; unit_database[unit_pos].quantity = "power"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 3.6282637948422090509290910e+52; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH]= 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_pos++; unit_database[unit_pos].nameAs = "I_planck"; // Planck Current unit_database[unit_pos].nameAp = "I_planck"; unit_database[unit_pos].nameLs = "I_P"; unit_database[unit_pos].nameLp = "I_P"; unit_database[unit_pos].nameFs = "planck_current"; unit_database[unit_pos].nameFp = "planck_current"; unit_database[unit_pos].quantity = "current"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 3.4788748621352181073707008e+25; unit_database[unit_pos].exponent[UNIT_CURRENT]= 1; unit_pos++; unit_database[unit_pos].nameAs = "V_planck"; // Planck Voltage unit_database[unit_pos].nameAp = "V_planck"; unit_database[unit_pos].nameLs = "V_P"; unit_database[unit_pos].nameLp = "V_P"; unit_database[unit_pos].nameFs = "planck_voltage"; unit_database[unit_pos].nameFp = "planck_voltage"; unit_database[unit_pos].quantity = "potential"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 1.0429417379546963190438953e+27; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_CURRENT] =-1; unit_pos++; unit_database[unit_pos].nameAs = "Z_planck"; // Planck Impedence unit_database[unit_pos].nameAp = "Z_planck"; unit_database[unit_pos].nameLs = "Z_P"; unit_database[unit_pos].nameLp = "Z_P"; unit_database[unit_pos].nameFs = "planck_impedence"; unit_database[unit_pos].nameFp = "planck_impedence"; unit_database[unit_pos].quantity = "resistance"; unit_database[unit_pos].planck = 1; unit_database[unit_pos].multiplier = 2.9979282937316497736901511e+01; unit_database[unit_pos].exponent[UNIT_MASS] = 1; unit_database[unit_pos].exponent[UNIT_LENGTH] = 2; unit_database[unit_pos].exponent[UNIT_TIME] =-3; unit_database[unit_pos].exponent[UNIT_CURRENT] =-2; unit_pos++; context->unit_pos = unit_pos; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "%d system default units loaded.", unit_pos); ppl_log(&context->errcontext,NULL); } return; } pyxplot-0.9.2/src/mathsTools/0000775000175000017500000000000012026340554014550 5ustar dcf21dcf21pyxplot-0.9.2/src/mathsTools/dcfmath.c0000664000175000017500000000517412026340554016331 0ustar dcf21dcf21// dcfmath.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dcfmath.c 1287 2012-08-10 17:57:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // A selection of useful mathematical functions which are not included in the standard C math library #define _PPL_DCFMATH_C 1 #include #include #include #include #include "dcfmath.h" double ppl_machineEpsilon; void ppl_makeMachineEpsilon() { ppl_machineEpsilon = 1.0; do { ppl_machineEpsilon /= 2.0; } while ((1.0 + (ppl_machineEpsilon/2.0)) != 1.0); return; } double ppl_max(double x, double y) { if (x>y) return x; return y; } double ppl_min(double x, double y) { if (xy?x:y; if (o>z) return o; return z; } double ppl_min3(double x, double y, double z) { double o = x*db) return 1; return 0; } int ppl_gcd(int a, int b) { while (b>0) { int tmp = a%b; a=b; b=tmp; } return a; } pyxplot-0.9.2/src/mathsTools/dcfmath.h0000664000175000017500000000266612026340554016341 0ustar dcf21dcf21// dcfmath.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dcfmath.h 1287 2012-08-10 17:57:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _DCFMATH_H #define _DCFMATH_H 1 #ifndef _DCFMATH_C extern double ppl_machineEpsilon; #endif void ppl_makeMachineEpsilon(); double ppl_max (double x, double y); double ppl_min (double x, double y); double ppl_max3 (double x, double y, double z); double ppl_min3 (double x, double y, double z); int ppl_sgn (double x); void ppl_linRaster(double *out, double min, double max, int Nsteps); void ppl_logRaster(double *out, double min, double max, int Nsteps); double ppl_degs (double rad); double ppl_rads (double degrees); int ppl_dblSort (const void *a, const void *b); int ppl_gcd (int a, int b); #endif pyxplot-0.9.2/src/coreUtils/0000775000175000017500000000000012026340554014364 5ustar dcf21dcf21pyxplot-0.9.2/src/coreUtils/stringList.h0000664000175000017500000000166612026340554016710 0ustar dcf21dcf21// stringList.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: stringList.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // List-based string processing functions #ifndef _STRINGLIST_H #define _STRINGLIST_H 1 #include "list.h" list *ppl_strSplit(char *in); #endif pyxplot-0.9.2/src/coreUtils/dict.c0000664000175000017500000002725312026340554015464 0ustar dcf21dcf21// lt_dict.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dict.c 1305 2012-09-14 17:48:04Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating linked lists #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "stringTools/asciidouble.h" void _ppl_dictRemoveEngine(dict *in, dictItem *ptr); dict *ppl_dictInit(int useMalloc) { dict *out; if (useMalloc) out = (dict *)malloc(sizeof(dict)); else out = (dict *)ppl_memAlloc(sizeof(dict)); if (out==NULL) return NULL; out->first = NULL; out->last = NULL; out->length = 0; out->refCount = 1; out->immutable = 0; out->hashTree = NULL; out->useMalloc = useMalloc; out->memory_context = ppl_memAlloc_GetMemContext(); return out; } void ppl_dictFreeTree(dictHash *i) { if (i==NULL) return; ppl_dictFreeTree(i->next); ppl_dictFreeTree(i->prev); free(i); return; } int ppl_dictFree(dict *in) { dictItem *ptr, *ptrnext; if ((in==NULL)||(!in->useMalloc)) return 0; ptr = in->first; while (ptr != NULL) { ptrnext = ptr->next; free(ptr->key); free(ptr->data); free(ptr); ptr = ptrnext; } ppl_dictFreeTree(in->hashTree); free(in); return 0; } int ppl_dictHash(const char *str, const int strLen) { unsigned int hash = 5381; int c, i=0; if (strLen<0) while ( (c = *str++) ) hash = ((hash << 5) + hash) + c; else while ((i++useMalloc ? malloc(X) : ppl_memAlloc_incontext(X, in->memory_context) ) static void ppl_dictHashAdd(dict *in, const char *str, const int hash, dictItem *item) { dictHash **ptr = &in->hashTree; while ((*ptr)!=NULL) { if ((*ptr)->hash < hash) ptr = &((*ptr)->prev); else if ((*ptr)->hash > hash) ptr = &((*ptr)->next); else { if (strcmp((*ptr)->item->key , str)==0) { (*ptr)->item=item; return; } // Overwriting a pre-existing item else return; // Genuine clash. Nothing we can do. } } *ptr = alloc(sizeof(dictHash)); if (*ptr==NULL) return; (*ptr)->hash = hash; (*ptr)->item = item; (*ptr)->prev = NULL; (*ptr)->next = NULL; } static dictItem *ppl_dictHashLookup(dict *in, const char *str, int slen, const int hash, int *clash) { dictHash **ptr = &in->hashTree; if (str==NULL) return NULL; if (slen<=0) slen=strlen(str); *clash=0; while ((*ptr)!=NULL) { if ((*ptr)->hash < hash) ptr = &((*ptr)->prev); else if ((*ptr)->hash > hash) ptr = &((*ptr)->next); else { if (strncmp((*ptr)->item->key , str , slen)==0) return (*ptr)->item; // Found it *clash=1; return NULL; } } return NULL; } static dictItem *ppl_dictHashRemove(dict *in, const char *str, const int hash, int *clash) { dictHash **ptr = &in->hashTree; if (str==NULL) return NULL; *clash=0; while ((*ptr)!=NULL) { if ((*ptr)->hash < hash) ptr = &((*ptr)->prev); else if ((*ptr)->hash > hash) ptr = &((*ptr)->next); else { if (strcmp((*ptr)->item->key , str)==0) // Found it { dictHash *old = *ptr; dictHash **near= ptr, *nearEntry; dictItem *out = (*ptr)->item; if (old->prev==NULL) { *ptr=old->next; if (in->useMalloc) free(old); return out; } if (old->next==NULL) { *ptr=old->prev; if (in->useMalloc) free(old); return out; } if (hash & 1) { while ((*near)->prev!=NULL) near=&((*near)->prev); nearEntry=*near; *near=(*near)->next; } else { while ((*near)->next!=NULL) near=&((*near)->next); nearEntry=*near; *near=(*near)->prev; } *ptr=nearEntry; if (in->useMalloc) free(old); return out; } else { *clash=1; return NULL; // Genuine clash. Nothing we can do. } } } return NULL; } int ppl_dictLen(dict *in) { if (in==NULL) return 0; return in->length; } int ppl_dictAppend(dict *in, const char *key, void *item) { dictItem *ptr=NULL, *ptrnew=NULL, *prev=NULL; int cmp = -1, hash; if (key==NULL) return 1; ptr = in->first; while (ptr != NULL) { if ( ((cmp = ppl_strCmpNoCase(ptr->key, key)) > 0) || ((cmp = strcmp(ptr->key, key)) == 0) ) break; prev = ptr; ptr = ptr->next; } if (cmp == 0) // Overwrite an existing entry in dictionary { if (in->useMalloc) free(ptr->data); ptr->data = item; } else { ptrnew = (dictItem *)alloc(sizeof(dictItem)); if (ptrnew==NULL) return 1; ptrnew->prev = prev; ptrnew->next = ptr; ptrnew->key = (char *)alloc((strlen(key)+1)); if (ptrnew->key==NULL) { if (in->useMalloc) free(ptrnew); return 1; } strcpy(ptrnew->key, key); ptrnew->data = item; if (prev == NULL) in->first = ptrnew; else prev->next = ptrnew; if (ptr == NULL) in->last = ptrnew; else ptr ->prev = ptrnew; in->length++; hash = ppl_dictHash(key, -1); ppl_dictHashAdd(in, key, hash, ptrnew); } return 0; } int ppl_dictAppendCpy(dict *in, const char *key, void *item, int size) { dictItem *ptr=NULL, *ptrnew=NULL, *prev=NULL; void *cpy; int cmp = -1, hash; if (key==NULL) return 1; cpy = alloc(size); if (cpy==NULL) return 1; memcpy(cpy, item, size); ptr = in->first; while (ptr != NULL) { if ( ((cmp = ppl_strCmpNoCase(ptr->key, key)) > 0) || ((cmp = strcmp(ptr->key, key)) == 0) ) break; prev = ptr; ptr = ptr->next; } if (cmp == 0) // Overwrite an existing entry in dictionary { if (in->useMalloc) free(ptr->data); ptr->data = cpy; ptrnew = ptr; } else { ptrnew = (dictItem *)alloc(sizeof(dictItem)); if (ptrnew==NULL) { if (in->useMalloc) free(cpy); return 1; } ptrnew->prev = prev; ptrnew->next = ptr; ptrnew->key = (char *)alloc((strlen(key)+1)); if (ptrnew->key==NULL) { if (in->useMalloc) { free(cpy); free(ptrnew); } return 1; } strcpy(ptrnew->key, key); ptrnew->data = cpy; memcpy(ptrnew->data, item, size); if (prev == NULL) in->first = ptrnew; else prev->next = ptrnew; if (ptr == NULL) in->last = ptrnew; else ptr ->prev = ptrnew; in->length++; hash = ppl_dictHash(key, -1); ppl_dictHashAdd(in, key, hash, ptrnew); } return 0; } void *ppl_dictLookup(dict *in, const char *key) { int hash; if (key==NULL) return NULL; hash = ppl_dictHash(key, -1); return ppl_dictLookupHash(in, key, hash); } void *ppl_dictLookupHash(dict *in, const char *key, int hash) { int clash; dictItem *ptr; if (key==NULL) return NULL; if (in==NULL) { return NULL; } // Check hash table ptr = ppl_dictHashLookup(in, key, -1, hash, &clash); if (!clash) { if (ptr==NULL) return NULL; return ptr->data; } // Hash table clash; need to exhaustively search dictionary ptr = in->first; while (ptr != NULL) { if (strcmp(ptr->key, key) == 0) return ptr->data; else if (ppl_strCmpNoCase(ptr->key, key) > 0) break; ptr = ptr->next; } return NULL; } void ppl_dictLookupWithWildcard(dict *in, char *key, char *SubsString, int SubsMaxLen, dictItem **ptrout) { int hash, clash, i, k, keylen; char *magicFns[] = { "diff_d", "int_d" , NULL }; dictItem *ptr; if (key==NULL) { *ptrout=NULL; return; } SubsString[0]='\0'; if (in==NULL) { *ptrout=NULL; return; } // Check hash table for (k=0; (isalnum(key[k]) || (key[k]=='_')); k++); keylen=k; hash = ppl_dictHash(key, keylen); ptr = ppl_dictHashLookup(in, key, keylen, hash, &clash); if (ptr!=NULL) { *ptrout=ptr; return; } if (clash) { ptr = in->first; while (ptr != NULL) { for (k=0; ((ptr->key[k]>' ')&&(ptr->key[k]==key[k])); k++); if ((ptr->key[k]=='\0')&&(!(isalnum(key[k])||(key[k]=='_')))) { *ptrout=ptr; return; } ptr = ptr->next; } } // Need to search "int_d?"-like wildcards for (i=0; magicFns[i]!=NULL; i++) { for (k=0; ((magicFns[i][k]>' ')&&(magicFns[i][k]==key[k])); k++); if (magicFns[i][k]=='\0') // each magic function name can be followed by a variable name { int l=0; if (isalpha(key[k+l])) // first character of dummy variable name must be a letter { for (l=0; ((isalnum(key[k+l]) || (key[k+l]=='_')) && (lfirst; while (ptr != NULL) { for (k=0; ((ptr->key[k]>' ')&&(ptr->key[k]==magicFns[i][k])); k++); if ((magicFns[i][k]=='\0')&&(ptr->key[k]=='\0')) { *ptrout=ptr; return; } ptr = ptr->next; } } } SubsString[0]='\0'; *ptrout = NULL; return; } int ppl_dictContains(dict *in, const char *key) { int hash, clash; dictItem *ptr; if (key==NULL) return 0; if (in==NULL) return 0; // Check hash table hash = ppl_dictHash(key, -1); ptr = ppl_dictHashLookup(in, key, -1, hash, &clash); if (!clash) return (ptr!=NULL); // Hash table clash; need to exhaustively search dictionary ptr = in->first; while (ptr != NULL) { if (strcmp(ptr->key, key)==0) return 1; ptr = ptr->next; } return 0; } int ppl_dictRemoveKey(dict *in, const char *key) { int hash, clash; dictItem *ptr; if (key==NULL) return 1; if (in==NULL) return 1; // Check hash table hash = ppl_dictHash(key, -1); ptr = ppl_dictHashRemove(in, key, hash, &clash); if (ptr==NULL) return 1; if (!clash) { _ppl_dictRemoveEngine(in, ptr); return 0; } // Hash table clash; need to exhaustively search dictionary ptr = in->first; while (ptr != NULL) { if (strcmp(ptr->key, key)==0) { _ppl_dictRemoveEngine(in, ptr); return 0; } else if (ppl_strCmpNoCase(ptr->key, key) > 0) break; ptr = ptr->next; } return 1; } int ppl_dictRemove(dict *in, void *item) { dictItem *ptr; if (in==NULL) return 1; ptr = in->first; while (ptr != NULL) { if (ptr->data == item) { return ppl_dictRemoveKey(in,ptr->key); } ptr = ptr->next; } return 1; } void _ppl_dictRemoveEngine(dict *in, dictItem *ptr) { if (in ==NULL) return; if (ptr==NULL) return; if (in->useMalloc) { free(ptr->data); free(ptr->key); } if (ptr->next != NULL) ptr->next->prev = ptr->prev; // We are not the last item in the list if (ptr->prev != NULL) ptr->prev->next = ptr->next; // We are the last item in the list, but not the first item if (in->last == ptr) in->last = ptr->prev; if (in->first == ptr) in->first = ptr->next; if (in->useMalloc) free(ptr); in->length--; return; } int ppl_dictRemoveAll(dict *in, void *item) { while ( !ppl_dictRemove(in,item) ); return 0; } dictIterator *ppl_dictIterateInit(dict *in) { if (in==NULL) return NULL; return in->first; } void *ppl_dictIterate(dictIterator **in, char **key) { void *out; if ((in==NULL) || (*in==NULL)) return NULL; *key = (*in)->key; out = (*in)->data; *in = (*in)->next; return out; } pyxplot-0.9.2/src/coreUtils/stringList.c0000664000175000017500000000321112026340554016667 0ustar dcf21dcf21// stringList.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: stringList.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // List-based string processing functions #include #include #include #include "stringTools/asciidouble.h" #include "list.h" /* ppl_strSplit(): Split up a string into bits separated by whitespace */ list *ppl_strSplit(char *in) { int pos, start, end; char *word; char *text_buffer; list *out; out = ppl_listInit(0); pos = 0; text_buffer = (char *)malloc(strlen(in)+1); while (in[pos] != '\0') { // Scan along to find the next word while ((in[pos] <= ' ') && (in[pos] > '\0')) pos++; start = pos; // Scan along to find the end of this word while ((in[pos] > ' ') && (in[pos] > '\0')) pos++; end = pos; if (end>start) { word = ppl_strSlice(in, text_buffer, start, end); ppl_listAppendCpy(out, word, strlen(word)+1); } } free(text_buffer); return out; } pyxplot-0.9.2/src/coreUtils/errorReport.c0000664000175000017500000002511512026340554017061 0ustar dcf21dcf21// errorReport.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: errorReport.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/errorReport.h" #include "settings/settingTypes.h" #define BLEN LSTR_LENGTH-1 static char temp_stringA[BLEN+1], temp_stringB[BLEN+1], temp_stringC[BLEN+1], temp_stringD[BLEN+1], temp_stringE[BLEN+1]; void ppl_error_setstreaminfo(pplerr_context *context, int linenumber,char *filename) { static long sourceId=0; context->error_input_sourceId = sourceId++; context->error_input_linenumber = linenumber; if (filename != NULL) { strncpy(context->error_input_filename, filename, FNAME_LENGTH); context->error_input_filename[FNAME_LENGTH-1]='\0'; } return; } void ppl_error(pplerr_context *context, int ErrType, int HighlightPos1, int HighlightPos2, char *msg) { unsigned char ApplyHighlighting, reverse=0; int i=0, j; if (msg==NULL) msg=context->tempErrStr; ApplyHighlighting = ((context->session_default.color == SW_ONOFF_ON) && (isatty(STDERR_FILENO) == 1)); if (msg!=temp_stringA) { snprintf(temp_stringA, BLEN, "%s", msg); temp_stringA[BLEN]='\0'; msg = temp_stringA; } temp_stringB[i] = temp_stringB[BLEN] = '\0'; if (ErrType != ERR_PREFORMED) // Do not prepend anything to pre-formed errors { // When processing scripts, print error location if ((context->error_input_linenumber != -1) && (strcmp(context->error_input_filename, "") != 0)) { snprintf(temp_stringB+i, BLEN-i, "%s:%d:", context->error_input_filename, context->error_input_linenumber); i += strlen(temp_stringB+i); if ((ErrType != ERR_STACKED)&&(i 1) reverse--; } if (i0)) { temp_stringB[i++] = ' '; j--; } // If newline is highlighted, add spaces to end of line so that we can highlight them else temp_stringB[i++] = msg[j]; } } if (ApplyHighlighting && (reverse!=0)) { snprintf(temp_stringB+i, BLEN-i, "\x1b[27m"); i+=strlen(temp_stringB+i); reverse=0; } if (isession_default.color_err , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)), temp_stringB, *(char **)ppl_fetchSettingName( context , SW_TERMCOL_NOR , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)) ); else snprintf(temp_stringC, BLEN, "%s\n", temp_stringB); temp_stringC[BLEN]='\0'; fputs(temp_stringC, stderr); return; } void ppl_fatal(pplerr_context *context, char *file, int line, char *msg) { char introline[FNAME_LENGTH]; if (msg==NULL) msg=context->tempErrStr; if (msg!=temp_stringE) { snprintf(temp_stringE, BLEN, "%s", msg); temp_stringE[BLEN-1]='\0'; msg = temp_stringE; } snprintf(introline, FNAME_LENGTH, "Fatal Error encountered in %s at line %d: %s", file, line, temp_stringE); introline[FNAME_LENGTH-1]='\0'; ppl_error(context, ERR_PREFORMED, -1, -1, introline); if (DEBUG) ppl_log(context, "Terminating with error condition 1."); exit(1); } void ppl_warning(pplerr_context *context, int ErrType, char *msg) { int i=0; if (msg==NULL) msg=context->tempErrStr; if (msg!=temp_stringA) { snprintf(temp_stringA, BLEN, "%s", msg); temp_stringA[BLEN-1]='\0'; msg = temp_stringA; } temp_stringB[i] = temp_stringB[BLEN] = '\0'; if (ErrType != ERR_PREFORMED) // Do not prepend anything to pre-formed errors { // When processing scripts, print error location if ((context->error_input_linenumber != -1) && (strcmp(context->error_input_filename, "") != 0)) { snprintf(temp_stringB+i, BLEN+i, "%s:%d:", context->error_input_filename, context->error_input_linenumber); i += strlen(temp_stringB+i); if ((ErrType != ERR_STACKED)&&(isession_default.color == SW_ONOFF_ON) && (isatty(STDERR_FILENO) == 1)) snprintf(temp_stringC, BLEN, "%s%s%s\n", *(char **)ppl_fetchSettingName( context , context->session_default.color_wrn , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)), temp_stringB, *(char **)ppl_fetchSettingName( context , SW_TERMCOL_NOR , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)) ); else snprintf(temp_stringC, BLEN, "%s\n", temp_stringB); temp_stringC[BLEN]='\0'; fputs(temp_stringC, stderr); return; } void ppl_report(pplerr_context *context, char *msg) { if (msg==NULL) msg=context->tempErrStr; if (msg!=temp_stringA) { snprintf(temp_stringA, BLEN, "%s", msg); temp_stringA[BLEN-1]='\0'; } if (DEBUG) { snprintf(temp_stringC, BLEN, "%s%s", "Reporting:\n", temp_stringA); temp_stringC[BLEN]='\0'; ppl_log(context, temp_stringC); } if ((context->session_default.color == SW_ONOFF_ON) && (isatty(STDOUT_FILENO) == 1)) snprintf(temp_stringC, BLEN, "%s%s%s\n", *(char **)ppl_fetchSettingName( context , context->session_default.color_rep , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)), temp_stringA, *(char **)ppl_fetchSettingName( context , SW_TERMCOL_NOR , SW_TERMCOL_INT , (void *)SW_TERMCOL_TXT, sizeof(char *)) ); else snprintf(temp_stringC, BLEN, "%s\n", temp_stringA); temp_stringC[BLEN]='\0'; fputs(temp_stringC, stdout); return; } void ppl_log(pplerr_context *context, char *msg) { static FILE *logfile = NULL; static int latch = 0; char linebuffer[LSTR_LENGTH]; if (latch) return; // Do not allow recursive calls, which might be generated by the call to ppl_fatal below latch = 1; if (logfile==NULL) { char LogFName[128]; snprintf(LogFName,127,"pyxplot.%d.log",getpid()); LogFName[127]='\0'; if ((logfile=fopen(LogFName,"w")) == NULL) { ppl_fatal(context,__FILE__,__LINE__,"Could not open log file to write."); exit(1); } setvbuf(logfile, NULL, _IOLBF, 0); // Set log file to be line-buffered, so that log file is always up-to-date } if (msg==NULL) msg=context->tempErrStr; if (msg!=temp_stringD) { snprintf(temp_stringD, BLEN, "%s", msg); temp_stringD[BLEN-1]='\0'; } fprintf(logfile, "[%s] [%s] %s\n", ppl_strStrip(ppl_friendlyTimestring(), linebuffer), context->error_source, temp_stringD); latch = 0; return; } pyxplot-0.9.2/src/coreUtils/backup.c0000664000175000017500000000313612026340554016000 0ustar dcf21dcf21// ppl_passwd.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: backup.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for getting information out of /etc/passwd #include #include #include #include #include "coreUtils/errorReport.h" #include "pplConstants.h" #include "settings/settingTypes.h" #include "userspace/context.h" void ppl_createBackupIfRequired(ppl_context *c, const char *filename) { char newname[FNAME_LENGTH]; int i,j; if (c->set->term_current.backup == SW_ONOFF_OFF) return; // Backup is switched off if (access(filename, F_OK) != 0) return; // File we're about to write to does not already exist strcpy(newname, filename); i = strlen(filename); for (j=0 ; j<65536 ; j++) { sprintf(newname+i, "~%d",j); if (access(newname, F_OK) != 0) break; // We've found a backup file which does not already exist } rename(filename, newname); return; } pyxplot-0.9.2/src/coreUtils/memAlloc.c0000664000175000017500000003222112026340554016261 0ustar dcf21dcf21// ppl_memAlloc.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: memAlloc.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for memory management #include #include #include #include "stringTools/strConstants.h" #include "coreUtils/memAlloc.h" #define PPL_MAX_CONTEXTS 250 // ppl_memAlloc_memory functions // These provide simple wrapper for fastmalloc which keep track of the current memory allocation context int ppl_memAlloc_mem_context = -1; static char temp_merr_string[LSTR_LENGTH]; // Storage buffer for error messages static void (*mem_error)(pplerr_context *, int, int, int, char *); // Handler for errors static void (*mem_log) (pplerr_context *, char *); // Handler for logging events static pplerr_context *errcontext; // Implementation of FASTMALLOC // For each allocation context, a pointer to the first chunk of memory which we have malloced void **_fastmalloc_firstblocklist; // For each allocation context, a pointer to the chunk of memory which we are currently allocating from void **_fastmalloc_currentblocklist; // For each allocation context, integers recording how many bytes have been allocated from the current block long *_fastmalloc_currentblock_alloc_ptr; // Keep statistics on numbers of malloc calls long long _fastmalloc_callcount; long long _fastmalloc_bytecount; long long _fastmalloc_malloccount; static int _fastmalloc_initialised = 0; void fastmalloc_init() { int i; if (_fastmalloc_initialised == 1) return; _fastmalloc_firstblocklist = (void **)malloc(PPL_MAX_CONTEXTS * sizeof(void *)); _fastmalloc_currentblocklist = (void **)malloc(PPL_MAX_CONTEXTS * sizeof(void *)); _fastmalloc_currentblock_alloc_ptr = (long *)malloc(PPL_MAX_CONTEXTS * sizeof(long )); for (i=0; i=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "FastMalloc asked to malloc memory in an unrecognised context %d.", context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return NULL; } if ((_fastmalloc_currentblocklist[context] == NULL) || (size > (FM_BLOCKSIZE - 2 - _fastmalloc_currentblock_alloc_ptr[context]))) // We need to malloc a new block { _fastmalloc_malloccount++; if (size > FM_BLOCKSIZE - sizeof(void **)) { if (MEMDEBUG1) { sprintf(temp_merr_string, "Fastmalloc creating block of size %d bytes at memory level %d.", size, context); (*mem_log)(errcontext, temp_merr_string); } if ((ptr = malloc(size + SYNCSTEP + sizeof(void **))) == NULL) { (*mem_error)(errcontext, 100, -1, -1, "Out of memory."); return NULL; } // This is a big malloc which needs to new block to itself } else { if (MEMDEBUG1) { sprintf(temp_merr_string, "Fastmalloc creating block of size %d bytes at memory level %d.", FM_BLOCKSIZE, context); (*mem_log)(errcontext, temp_merr_string); } if ((ptr = malloc(FM_BLOCKSIZE )) == NULL) { (*mem_error)(errcontext, 100, -1, -1, "Out of memory."); return NULL; } // Malloc a new standard sized block } *((void **)ptr) = NULL; // Link to next block in chain if (_fastmalloc_currentblocklist[context] == NULL) _fastmalloc_firstblocklist[context] = ptr; // Insert link into previous block in chain else *((void **)_fastmalloc_currentblocklist[context]) = ptr; _fastmalloc_currentblocklist[context] = ptr; _fastmalloc_currentblock_alloc_ptr[context] = (sizeof(void **) + (SYNCSTEP-1)); // Fastforward over link to next block _fastmalloc_currentblock_alloc_ptr[context] -= (_fastmalloc_currentblock_alloc_ptr[context] % SYNCSTEP); out = ptr + _fastmalloc_currentblock_alloc_ptr[context]; _fastmalloc_currentblock_alloc_ptr[context] += (size + (SYNCSTEP-1)); // Fastfoward over block we have just allocated _fastmalloc_currentblock_alloc_ptr[context] -= (_fastmalloc_currentblock_alloc_ptr[context] % SYNCSTEP); } else { // There is room for this malloc in the old block out = _fastmalloc_currentblocklist[context] + _fastmalloc_currentblock_alloc_ptr[context]; _fastmalloc_currentblock_alloc_ptr[context] += (size + (SYNCSTEP-1)); // Fastfoward over block we have just allocated _fastmalloc_currentblock_alloc_ptr[context] -= (_fastmalloc_currentblock_alloc_ptr[context] % SYNCSTEP); } return out; } // --------------------------------------------------------- // ppl_memAlloc_memory functions // These provide simple wrapper for fastmalloc which keep track of the current memory allocation context // -------------------------------------------------------- // ppl_memAlloc_MemoryInit() -- Call this before using any ppl_memAlloc_memory functions. void ppl_memAlloc_MemoryInit( pplerr_context *ec, void(*mem_error_handler)(pplerr_context *,int, int, int, char *) , void(*mem_log_handler)(pplerr_context *,char *) ) { mem_error = mem_error_handler; mem_log = mem_log_handler; errcontext = ec; if (MEMDEBUG1) (*mem_log)(errcontext, "Initialising memory management system."); ppl_memAlloc_mem_context = 0; fastmalloc_init(); ppl_memAlloc_FreeAll(0); _ppl_memAlloc_SetMemContext(0); return; } // ppl_memAlloc_MemoryStop() -- Call this when ppl_memAlloc_memory is finished with and should be cleaned up void ppl_memAlloc_MemoryStop() { if (MEMDEBUG1) (*mem_log)(errcontext, "Shutting down memory management system."); fastmalloc_close(); ppl_memAlloc_mem_context = -1; return; } // ppl_memAlloc_DescendIntoNewContext() -- Create a new memory allocation context for future calls to ppl_memAlloc() // [returns the context number of the allocation context which has been assigned to future ppl_memAlloc calls] int ppl_memAlloc_DescendIntoNewContext() { if (ppl_memAlloc_mem_context < 0 ) { (*mem_error)(errcontext, 100, -1, -1, "Call to ppl_memAlloc_DescendIntoNewContext() before call to ppl_memAlloc_MemoryInit()."); return -1; } if (ppl_memAlloc_mem_context >= (PPL_MAX_CONTEXTS+1)) { (*mem_error)(errcontext, 100, -1, -1, "Too many memory contexts."); return -1; } _ppl_memAlloc_SetMemContext(ppl_memAlloc_mem_context+1); if (MEMDEBUG1) { sprintf(temp_merr_string, "Descended into memory context %d.", ppl_memAlloc_mem_context); (*mem_log)(errcontext, temp_merr_string); } return ppl_memAlloc_mem_context; } // ppl_memAlloc_AscendOutOfContext() -- Call when the current memory allocation context is finished with and can be freed. // [call with the number of the allocation context which is to be freed. Returns the number of the current allocation context after the freeing operation.] int ppl_memAlloc_AscendOutOfContext(int context) { if (ppl_memAlloc_mem_context < 0 ) { (*mem_error)(errcontext, 100, -1, -1, "Call to ppl_memAlloc_AscendOutOfContext() before call to ppl_memAlloc_MemoryInit()."); return -1; } if (context > ppl_memAlloc_mem_context ) return ppl_memAlloc_mem_context; if (context <= 0 ) { (*mem_error)(errcontext, 100, -1, -1, "Call to ppl_memAlloc_AscendOutOfContext() attempting to ascend out of lowest possible memory context."); return -1; } if (MEMDEBUG1) { sprintf(temp_merr_string, "Ascending out of memory context %d.", ppl_memAlloc_mem_context); (*mem_log)(errcontext, temp_merr_string); } ppl_memAlloc_FreeAll(context); _ppl_memAlloc_SetMemContext(context-1); return ppl_memAlloc_mem_context; } // _ppl_memAlloc_SetMemContext() -- PRIVATE FUNCTION. void _ppl_memAlloc_SetMemContext(int context) { if ((context<0) || (context>=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "ppl_memAlloc_SetMemContext passed unrecognised context number %d.", context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return; } ppl_memAlloc_mem_context = context; return; } // ppl_memAlloc_GetMemContext() -- Returns the number of the current memory allocation context. int ppl_memAlloc_GetMemContext() { return ppl_memAlloc_mem_context; } // ppl_memAlloc_FreeAll() -- Free all memory which has been allocated in the specified allocation context, and in deeper levels. void ppl_memAlloc_FreeAll(int context) { static int latch=0; if (latch==1) return; // Prevent recursive calls if (ppl_memAlloc_mem_context<0) return; // Memory management not initialised latch=1; if ((context<0) || (context>=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "ppl_memAlloc_FreeAll() passed unrecognised context %d.", context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return; } if (MEMDEBUG1) { sprintf(temp_merr_string, "Freeing all memory down to level %d.", context); (*mem_log)(errcontext, temp_merr_string); } fastmalloc_freeall(context); latch=0; return; } // ppl_memAlloc_Free() -- Free all memory which has been allocated in the specified allocation context, but not in deeper levels. void ppl_memAlloc_Free(int context) { static int latch=0; if (latch==1) return; // Prevent recursive calls latch=1; if ((context<0) || (context>=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "ppl_memAlloc_Free() passed unrecognised context %d.", context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return; } if (MEMDEBUG1) { sprintf(temp_merr_string, "Freeing all memory down in level %d.", context); (*mem_log)(errcontext, temp_merr_string); } fastmalloc_free(context); latch=0; return; } // memAalloc() -- Malloc some memory in the present allocation context. void *ppl_memAlloc(int size) { void *out; if ((ppl_memAlloc_mem_context<0) || (ppl_memAlloc_mem_context>=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "ppl_memAlloc_malloc() using unrecognised context %d.", ppl_memAlloc_mem_context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return NULL; } if (MEMDEBUG2) { sprintf(temp_merr_string, "Request to malloc %d bytes at memory level %d.", size, ppl_memAlloc_mem_context); (*mem_log)(errcontext, temp_merr_string); } out = fastmalloc(ppl_memAlloc_mem_context, size); if (out == NULL) { (*mem_error)(errcontext, 100, -1, -1, "Out of memory."); return NULL; } return out; } // ppl_memAlloc_incontext() -- Malloc some memory in the specified context. Use sparingly. void *ppl_memAlloc_incontext(int size, int context) { void *out; if ((context<0) || (context>=PPL_MAX_CONTEXTS)) { sprintf(temp_merr_string, "ppl_memAlloc_incontext() passed unrecognised context %d.", context); (*mem_error)(errcontext, 100, -1, -1, temp_merr_string); return NULL; } if (MEMDEBUG2) { sprintf(temp_merr_string, "Request to malloc %d bytes at memory level %d.", size, context); (*mem_log)(errcontext, temp_merr_string); } out = fastmalloc(context, size); if (out == NULL) { (*mem_error)(errcontext, 100, -1, -1, "Out of memory."); return NULL; } return out; } pyxplot-0.9.2/src/coreUtils/errorReport.h0000664000175000017500000000441012026340554017061 0ustar dcf21dcf21// ppl_error.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: errorReport.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for returning messages to the user #ifndef _PPL_ERROR_H #define _PPL_ERROR_H 1 #define ERR_INTERNAL 100 #define ERR_GENERIC 101 #define ERR_SYNTAX 102 #define ERR_NUMERICAL 103 #define ERR_FILE 104 #define ERR_MEMORY 105 #define ERR_STACKED 106 #define ERR_PREFORMED 107 #define ERR_RANGE 108 #define ERR_UNIT 109 #define ERR_OVERFLOW 110 #define ERR_NAMESPACE 111 #define ERR_TYPE 112 #define ERR_INTERRUPT 113 #define ERR_DICTKEY 114 #define ERR_ASSERT 115 #include "stringTools/strConstants.h" typedef struct pplset_session { int splash, color, color_rep, color_wrn, color_err; char cwd[FNAME_LENGTH]; char tempdir[FNAME_LENGTH]; char homedir[FNAME_LENGTH]; } pplset_session; typedef struct pplerr_context_s { int error_input_linenumber; long error_input_sourceId; char error_input_filename[FNAME_LENGTH]; char error_source[16]; // Identifier of the process producing log messages char tempErrStr[LSTR_LENGTH]; pplset_session session_default; } pplerr_context; void ppl_error_setstreaminfo(pplerr_context *context, int linenumber,char *filename); void ppl_error(pplerr_context *context, int ErrType, int HighlightPos1, int HighlightPos2, char *msg); void ppl_fatal(pplerr_context *context, char *file, int line, char *msg); void ppl_warning(pplerr_context *context, int ErrType, char *msg); void ppl_report(pplerr_context *context, char *msg); void ppl_log(pplerr_context *context, char *msg); #endif pyxplot-0.9.2/src/coreUtils/dict.h0000664000175000017500000000466712026340554015475 0ustar dcf21dcf21// dict.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dict.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Data structures for dictionaries #ifndef _LT_DICT_H #define _LT_DICT_H 1 typedef struct dictHashS { int hash; struct dictItemS *item; struct dictHashS *prev, *next; } dictHash; typedef struct dictItemS { char *key; void *data; struct dictItemS *next; struct dictItemS *prev; } dictItem; typedef struct dictS { struct dictItemS *first; struct dictItemS *last; int length, refCount; unsigned char immutable; struct dictHashS *hashTree; int useMalloc; int memory_context; } dict; typedef dictItem dictIterator; dict *ppl_dictInit (int useMalloc); int ppl_dictHash (const char *str, const int strLen); void ppl_dictFreeTree (dictHash *i); int ppl_dictFree (dict *in); int ppl_dictLen (dict *in); int ppl_dictAppend (dict *in, const char *key, void *item); int ppl_dictAppendCpy (dict *in, const char *key, void *item, int size); void *ppl_dictLookup (dict *in, const char *key); void *ppl_dictLookupHash (dict *in, const char *key, int hash); void ppl_dictLookupWithWildcard(dict *in, char *key, char *SubsString, int SubsMaxLen, dictItem **ptrout); int ppl_dictContains (dict *in, const char *key); int ppl_dictRemoveKey (dict *in, const char *key); int ppl_dictRemove (dict *in, void *item); int ppl_dictRemoveAll (dict *in, void *item); dictIterator *ppl_dictIterateInit (dict *in); void *ppl_dictIterate (dictIterator **in, char **key); #endif pyxplot-0.9.2/src/coreUtils/memAlloc.h0000664000175000017500000000342012026340554016265 0ustar dcf21dcf21// ppl_memAlloc.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: memAlloc.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for memory management #ifndef _MEMALLOC_H #define _MEMALLOC_H 1 #include "coreUtils/errorReport.h" void ppl_memAlloc_MemoryInit ( pplerr_context *ec, void(*mem_error_handler)(pplerr_context *,int, int, int, char *) , void(*mem_log_handler)(pplerr_context *,char *) ); void ppl_memAlloc_MemoryStop (); int ppl_memAlloc_DescendIntoNewContext (); int ppl_memAlloc_AscendOutOfContext (int context); void _ppl_memAlloc_SetMemContext (int context); int ppl_memAlloc_GetMemContext (); void ppl_memAlloc_FreeAll (int context); void ppl_memAlloc_Free (int context); void *ppl_memAlloc (int size); void *ppl_memAlloc_incontext (int size, int context); // Allocate memory in 128kb blocks (131072 bytes) #define FM_BLOCKSIZE 131072 // Always align mallocs to 8-byte boundaries; 64-bit processors do double arithmetic twice as fast when word-aligned #define SYNCSTEP 8 #endif pyxplot-0.9.2/src/coreUtils/backup.h0000664000175000017500000000166012026340554016005 0ustar dcf21dcf21// backup.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: backup.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _BACKUP_H #define _BACKUP_H 1 #include "userspace/context.h" void ppl_createBackupIfRequired(ppl_context *c, const char *filename); #endif pyxplot-0.9.2/src/coreUtils/list.h0000664000175000017500000000400212026340554015504 0ustar dcf21dcf21// list.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: list.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Data structures for linked lists #ifndef _LIST_H #define _LIST_H 1 typedef struct listItemS { void *data; struct listItemS *next; struct listItemS *prev; } listItem; typedef struct listS { struct listItemS *first; struct listItemS *last; int length, refCount, immutable; int useMalloc; int memory_context; } list; typedef listItem listIterator; list *ppl_listInit (int useMalloc); int ppl_listFree (list *in); int ppl_listLen (list *in); list *ppl_listCpy (list *in, int useMalloc, int itemSize); int ppl_listAppend (list *in, void *item); int ppl_listAppendCpy (list *in, void *item, int size); int ppl_listInsertCpy (list *in, int N, void *item, int size); int ppl_listRemove (list *in, void *item); int ppl_listRemoveAll (list *in, void *item); void *ppl_listGetItem (list *in, int N); void *ppl_listPop (list *in); void *ppl_listPopItem (list *in, int N); void *ppl_listLast (list *in); listIterator *ppl_listIterateInit(list *in); void *ppl_listIterate (listIterator **in); #endif pyxplot-0.9.2/src/coreUtils/list.c0000664000175000017500000001364612026340554015515 0ustar dcf21dcf21// list.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: list.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for manupulating linked lists #include #include #include #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" list *ppl_listInit(int useMalloc) { list *out; if (useMalloc) out = (list *)malloc(sizeof(list)); else out = (list *)ppl_memAlloc(sizeof(list)); if (out==NULL) return NULL; out->first = NULL; out->last = NULL; out->length = 0; out->refCount = 1; out->immutable = 0; out->useMalloc = useMalloc; out->memory_context = ppl_memAlloc_GetMemContext(); return out; } int ppl_listFree(list *in) { listItem *ptr, *ptrnext; if ((in==NULL)||(!in->useMalloc)) return 0; ptr = in->first; while (ptr != NULL) { ptrnext = ptr->next; free(ptr->data); free(ptr); ptr = ptrnext; } free(in); return 0; } int ppl_listLen(list *in) { if (in==NULL) return 0; return in->length; } #define alloc(X) ( in->useMalloc ? malloc(X) : ppl_memAlloc_incontext(X, in->memory_context) ) list *ppl_listCpy(list *in, int useMalloc, int itemSize) { listItem *i; list *out; if (in==NULL) return NULL; out = ppl_listInit(useMalloc); if (out==NULL) return NULL; i = in->first; while (i!=NULL) { ppl_listAppendCpy(in, i->data, itemSize); i=i->next; } return out; } int ppl_listAppend(list *in, void *item) { listItem *ptrnew; if (in==NULL) return 1; ptrnew = (listItem *)alloc(sizeof(listItem)); if (ptrnew==NULL) return 1; ptrnew->prev = in->last; ptrnew->next = NULL; ptrnew->data = item; if (in->first == NULL) in->first = ptrnew; if (in->last != NULL) in->last->next = ptrnew; in->last = ptrnew; in->length++; return 0; } int ppl_listAppendCpy(list *in, void *item, int size) { listItem *ptrnew; if (in==NULL) return 1; ptrnew = (listItem *)alloc(sizeof(listItem)); if (ptrnew==NULL) return 1; ptrnew->prev = in->last; ptrnew->next = NULL; ptrnew->data = alloc(size); if (ptrnew->data==NULL) { if (in->useMalloc) free(ptrnew); return 1; } memcpy(ptrnew->data, item, size); if (in->first == NULL) in->first = ptrnew; if (in->last != NULL) in->last->next = ptrnew; in->last = ptrnew; in->length++; return 0; } int ppl_listInsertCpy(list *in, int N, void *item, int size) { int i; listItem **ptr, *ptrnew; if (in==NULL) return 1; ptrnew = (listItem *)alloc(sizeof(listItem)); if (ptrnew==NULL) return 1; ptrnew->data = alloc(size); if (ptrnew->data==NULL) { if (in->useMalloc) free(ptrnew); return 1; } memcpy(ptrnew->data, item, size); ptr = &in->first; for (i=0; ((inext); ptrnew->prev = (*ptr==NULL) ? in->last : (*ptr)->prev; ptrnew->next = *ptr; if (*ptr!=NULL) (*ptr)->prev = ptrnew; *ptr = ptrnew; in->length++; return 0; } static void ppl_listRemoveEngine(list *in, listItem *ptr) { listItem *ptrnext; if (ptr->next != NULL) // We are not the last item in the list { ptrnext = ptr->next; ptr->data = ptrnext->data; ptr->next = ptrnext->next; if (in->last == ptrnext) in->last = ptr; else ptr->next->prev = ptr; if (in->useMalloc) free(ptrnext); } else if (ptr->prev != NULL) // We are the last item in the list, but not the first item { ptrnext = ptr->prev; ptr->data = ptrnext->data; ptr->prev = ptrnext->prev; if (in->first == ptrnext) in->first = ptr; else ptrnext->prev->next = ptr; if (in->useMalloc) free(ptrnext); } else // We are the only item in the list { in->first = NULL; in->last = NULL; if (in->useMalloc) free(ptr); } in->length--; return; } int ppl_listRemove(list *in, void *item) { listItem *ptr; if (in==NULL) return 1; ptr = in->first; while (ptr != NULL) { if (ptr->data == item) { ppl_listRemoveEngine(in, ptr); return 0; } ptr = ptr->next; } return 1; } int ppl_listRemoveAll(list *in, void *item) { while ( !ppl_listRemove(in,item) ); return 0; } void *ppl_listGetItem(list *in, int N) { listItem *ptr; int i; if (in==NULL) return NULL; ptr = in->first; for (i=0; ((inext); if (ptr==NULL) return NULL; return ptr->data; } void *ppl_listPop(list *in) { void *out; if (in->last == NULL) return NULL; out = in->last->data; if (in->first == in->last) { in->first = in->last = NULL; } else { in->last = in->last->prev; in->last->next = NULL; } in->length--; return out; } void *ppl_listPopItem(list *in, int N) { listItem *ptr; void *out=NULL; int i; if (in==NULL) return NULL; ptr = in->first; for (i=0; ((inext); if (ptr==NULL) return NULL; else { out=ptr->data; ppl_listRemoveEngine(in, ptr); } return out; } void *ppl_listLast(list *in) { if (in->last == NULL) return NULL; return in->last->data; } listIterator *ppl_listIterateInit(list *in) { if (in==NULL) return NULL; return in->first; } void *ppl_listIterate(listIterator **in) { void *out; if ((in==NULL) || (*in==NULL)) return NULL; out = (*in)->data; *in = (*in)->next; return out; } pyxplot-0.9.2/src/coreUtils/getPasswd.c0000664000175000017500000000657212026340554016503 0ustar dcf21dcf21// ppl_passwd.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: getPasswd.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- // Functions for getting information out of /etc/passwd #include #include #include #include #include #include "coreUtils/errorReport.h" #include "pplConstants.h" struct passwd *UnixGetPwEntry(pplerr_context *context) { int uid; struct passwd *ptr; uid = getuid(); setpwent(); // Memory leak which valgrind reveals here is probably okay; getpwent sets up a static variable with malloc while ((ptr = getpwent()) != NULL) if (ptr->pw_uid == uid) break; endpwent(); return(ptr); } char *ppl_unixGetHomeDir(pplerr_context *context) { struct passwd *ptr; static char *failover=NULL; ptr = UnixGetPwEntry(context); if (ptr==NULL) { if (failover != NULL) return failover; failover = malloc(FNAME_LENGTH); if (failover==NULL) ppl_fatal(context,__FILE__,__LINE__,"Could not find user's entry in output of getpwent()"); sprintf(failover,"/home/%s", getlogin()); sprintf(context->tempErrStr, "Could not find user's entry in output of getpwent(). Guessing that home directory is <%s>.", failover); ppl_warning(context, ERR_GENERIC, NULL); return failover; } return ptr->pw_dir; } char *ppl_unixGetUserHomeDir(pplerr_context *context,char *username) { struct passwd *ptr; setpwent(); // Ditto memory leak comment above while ((ptr = getpwent()) != NULL) if (strcmp(ptr->pw_name , username) == 0) break; endpwent(); if (ptr==NULL) return NULL; return ptr->pw_dir; } char *ppl_unixGetIRLName(pplerr_context *context) { struct passwd *ptr; int i; ptr = UnixGetPwEntry(context); if (ptr==NULL) return getlogin(); // In case of failure, return user's login. strcpy(context->tempErrStr, ptr->pw_gecos); for (i=0; context->tempErrStr[i]!='\0'; i++) if (context->tempErrStr[i]==',') context->tempErrStr[i]='\0'; // Remove commas from in-real-life name return context->tempErrStr; } // Expand out filenames line ~dcf21/script.ppl char *ppl_unixExpandUserHomeDir(pplerr_context *context,char *in, char *cwd, char *out) { char UserName[1024]; char *scan_in, *scan_out; if (in[0] == '/') strcpy (out, in); else if (in[0] != '~') sprintf(out, "%s%s%s", cwd, PATHLINK, in); else if (in[1] == '/') sprintf(out, "%s%s%s", ppl_unixGetHomeDir(context), PATHLINK, in+2); else { for ( scan_in=in+1,scan_out=UserName ; ((*scan_in!='/') && (*scan_in!='\0')) ; *(scan_out++)=*(scan_in++) ); *scan_out='\0'; scan_out = ppl_unixGetUserHomeDir(context,UserName); if (scan_out != NULL) sprintf(out, "%s%s", scan_out, scan_in); else strcpy (out, in); } return out; } pyxplot-0.9.2/src/coreUtils/getPasswd.h0000664000175000017500000000226712026340554016505 0ustar dcf21dcf21// getPasswd.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: getPasswd.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _GETPASSWD_H #define _GETPASSWD_H 1 #include "coreUtils/errorReport.h" /* Functions defined in ppl_passwd.c */ char *ppl_unixGetHomeDir (pplerr_context *context); char *ppl_unixGetUserHomeDir (pplerr_context *context,char *username); char *ppl_unixGetIRLName (pplerr_context *context); char *ppl_unixExpandUserHomeDir(pplerr_context *context,char *in, char *cwd, char *out); #endif pyxplot-0.9.2/src/pplConstants.h0000664000175000017500000000364512026340554015264 0ustar dcf21dcf21// pplConstants.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplConstants.h 1296 2012-08-29 22:13:31Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLCONSTANTS_H #define _PPLCONSTANTS_H 1 // Context buffer lengths #define ALGEBRA_MAXLEN 2048 /* Size of buffer for tokenising input expressions */ #define STACK_DEFAULT 4096 /* Stack size */ #define CONTEXT_DEPTH 256 /* Maximum number of stacked local namespaces */ #define DUMMYVAR_MAXLEN 16 /* Maximum number of characters in a dummy variable name for integration / differentiation */ #define MAX_RECURSION_DEPTH 128 /* The maximum recursion depth */ // Plot related structure sizes #define MULTIPLOT_MAXINDEX 32768 #define PALETTE_LENGTH 512 #define MAX_PLOTSTYLES 128 // The maximum number of plot styles (e.g. plot sin(x) with style 23) which are be defined. Similar to 'with linestyle 23' in gnuplot #define MAX_AXES 128 #define MAX_CONTOURS 128 // Maximum number of contours in 'set contour' #define USING_ITEMS_MAX 32 #define FUNC_MAXARGS 1024 // Axis linear interpolations #define AXISLINEARINTERPOLATION_NPOINTS 2045 // Command-specific options #define EQNSOLVE_MAXDIMS 16 // Maximum number of via variables when equation solving / fitting #endif pyxplot-0.9.2/src/expressions/0000775000175000017500000000000012026340554014775 5ustar dcf21dcf21pyxplot-0.9.2/src/expressions/dollarOp.h0000664000175000017500000000302312026340554016720 0ustar dcf21dcf21// dollarOp.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dollarOp.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _DOLLAROP_H #define _DOLLAROP_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_dollarOp_config (ppl_context *c, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char *usingExpr, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits); void ppl_dollarOp_deconfig(ppl_context *c); void ppl_dollarOp_fetchColByNum(ppl_context *c, pplExpr *inExpr, int inExprCharPos, int colNum); void ppl_dollarOp_fetchColByName(ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *colName); #endif pyxplot-0.9.2/src/expressions/expEval.c0000664000175000017500000010317212026340554016551 0ustar dcf21dcf21// expEval.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEval.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _EXPEVAL_C 1 #include #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "expressions/dollarOp.h" #include "expressions/expEval.h" #include "expressions/expEvalCalculus.h" #include "expressions/expEvalOps.h" #include "expressions/expEvalSlice.h" #include "expressions/fnCall.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjCmp.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjMethods.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" #include "pplConstants.h" #define TBADD(et) ppl_tbAdd(context,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,et,charpos,inExpr->ascii,"") static void expEval_stringSubs(ppl_context *context, pplExpr *inExpr, int charpos, int Nsubs) { const char allowedFormats[] = "cdieEfgGosSxX%"; // These tokens are allowed after a % format specifier char formatToken[512]; pplObj *obj = &context->stack[context->stackPtr]; int argP = -Nsubs; char *format = (char *)((obj+argP-1)->auxil); int outlen = 65536; int inP = 0; int outP = 0; int inP2, requiredArgs, l, arg1i=0, arg2i=0; char *out = (char *)malloc(outlen); if (out==NULL) { strcpy(context->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY); return; } // Loop over format string looking for tokens for ( ; format[inP]!='\0' ; inP++) { // If output buffer is nearly full, malloc some more if (outP>outlen-16384) { char *outnew=(char *)realloc((void*)out , outlen+=65536); if (outnew==NULL) { free(out); strcpy(context->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY); return; } out = outnew; } if (format[inP]!='%') { out[outP++] = format[inP]; continue; } // Characters other than % tokens are copied straight to output inP2=inP+1; // inP2 looks ahead to see experimentally if syntax is right requiredArgs = 1; // Normal %f like tokens require 1 argument if ((format[inP2]=='+')||(format[inP2]=='-')||(format[inP2]==' ')||(format[inP2]=='#')) inP2++; // optional flag can be <+- #> if (format[inP2]=='*') { inP2++; requiredArgs++; } else while ((format[inP2]>='0') && (format[inP2]<='9')) inP2++; // length can be * or some digits if (format[inP2]=='.') // precision starts with a . and is followed by * or by digits { inP2++; if (format[inP2]=='*') { inP2++; requiredArgs++; } else while ((format[inP2]>='0') && (format[inP2]<='9')) inP2++; // length can be * or some digits } // We do not allow user to specify optional length flag, which could potentially be for (l=0; allowedFormats[l]!='\0'; l++) if (format[inP2]==allowedFormats[l]) break; if (allowedFormats[l]=='%') requiredArgs=0; if ((allowedFormats[l]=='\0') || ((allowedFormats[l]=='%')&&(format[inP2-1]!='%')) ) { out[outP++] = format[inP]; continue; } // Have not got correct syntax for a format specifier if (requiredArgs > -argP) { free(out); strcpy(context->errStat.errBuff, "Too few arguments supplied to string substitution operator"); TBADD(ERR_RANGE); return; } // Have run out of substitution arguments // %% token simply produces a literal % if (allowedFormats[l]=='%') { strcpy(out+outP, "%"); // %% just produces a % character } else { ppl_strSlice(format, formatToken, inP, inP2+1); // If token required extra integer arguments, read these now if (requiredArgs > 1) { CAST_TO_INT(obj+argP,"%"); arg1i = (int)((obj+argP)->real); argP++; } if (requiredArgs > 2) { CAST_TO_INT(obj+argP,"%"); arg2i = (int)((obj+argP)->real); argP++; } // Print a string if ((allowedFormats[l]=='c') || (allowedFormats[l]=='s') || (allowedFormats[l]=='S')) { const int tmpbufflen = 65536; char *tmpbuff = (char *)malloc(tmpbufflen); if (tmpbuff==NULL) { free(out); strcpy(context->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY); return; } pplObjPrint(context, obj+argP, NULL, tmpbuff, tmpbufflen, 0, 0); formatToken[inP2-inP] = 's'; if (requiredArgs==1) snprintf(out+outP, outlen-outP, formatToken, tmpbuff); // Print a string variable if (requiredArgs==2) snprintf(out+outP, outlen-outP, formatToken, arg1i, tmpbuff); if (requiredArgs==3) snprintf(out+outP, outlen-outP, formatToken, arg1i, arg2i, tmpbuff); out[outlen-1]='\0'; free(tmpbuff); } else { pplObj *o = obj+argP; CAST_TO_NUM(obj+argP); // Make object into a number if ((!gsl_finite(o->real)) || ((context->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (o->flagComplex!=0))) { strcpy(out+outP, "nan"); } else { strcpy(out+outP, ppl_unitsNumericDisplayWithFormat(context, o, 0, formatToken, allowedFormats[l], outlen-outP, requiredArgs, arg1i, arg2i)); } } argP++; } outP += strlen(out+outP); inP = inP2; } out[outP]='\0'; // Throw an error if too many arguments were supplied if (argP<0) { free(out); sprintf(context->errStat.errBuff, "Too many arguments supplied to string substitution operator; %d supplied when %d were needed.", Nsubs, Nsubs+argP); TBADD(ERR_RANGE); return; } // Return output string pplObjStr(obj, 0, 1, out); context->stackPtr++; return; cast_fail: if (out!=NULL) free(out); return; } #define STACK_POP \ { \ context->stackPtr--; \ ppl_garbageObject(&context->stack[context->stackPtr]); \ if (context->stack[context->stackPtr].refCount != 0) { strcpy(context->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } \ } pplObj *ppl_expEval(ppl_context *context, pplExpr *inExpr, int *lastOpAssign, int dollarAllowed, int iterDepth) { int j=0; int initialStackPtr=0; int charpos=0; pplExprBytecode *in = inExpr->bytecode; if (iterDepth > MAX_RECURSION_DEPTH) { strcpy(context->errStat.errBuff,"Maximum recursion depth exceeded."); TBADD(ERR_OVERFLOW); return NULL; } // If at bottom iteration depth, clean up stack now if there is any left-over junk if (iterDepth==0) { STACK_REINIT(context); } initialStackPtr = context->stackPtr; *lastOpAssign=0; while (1) { pplObj *stk; int pos = j; // Position of start of instruction int len = in[j].len; // length of bytecode instruction with data int o = in[j].opcode; // Opcode number char *charaux = (char *)&(in[j+1]); charpos = in[j].charpos; // character position of token (for error reporting) if (cancellationFlag) { strcpy(context->errStat.errBuff,"Operation cancelled."); charpos=0; TBADD(ERR_INTERRUPT); goto cleanup_on_error; } if (initialStackPtr==0) { STACK_REQUEST (context,4); } // allowed to realloc stack else { STACK_MUSTHAVE(context,4); } // not allowed to realloc stack; will change pointers in calling layers if (context->stackFull) { strcpy(context->errStat.errBuff,"Stack overflow."); charpos=0; TBADD(ERR_MEMORY); goto cleanup_on_error; } stk = &context->stack[context->stackPtr]; switch (o) { case 0: // Return break; case 1: // Numeric literal *lastOpAssign=0; pplObjNum(stk , 0 , in[j].auxil.d , 0); stk->refCount=1; context->stackPtr++; break; case 2: // String literal { int l = strlen(charaux); char *out; *lastOpAssign=0; if ((out = (char *)malloc(l+1))==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup_on_error; } strcpy(out , charaux); pplObjStr(stk , 0 , 1 , out); stk->refCount=1; context->stackPtr++; break; } case 3: // Lookup value { int i , got=0; char *key = charaux; *lastOpAssign=0; for (i=context->ns_ptr ; i>=0 ; i=(i>1)?1:i-1) { pplObj *obj = (pplObj *)ppl_dictLookup(context->namespaces[i] , key); if (obj==NULL) continue; if ((obj->objType==PPLOBJ_GLOB)||(obj->objType==PPLOBJ_ZOM)) continue; pplObjCpy(stk , obj , 1 , 0 , 1); stk->immutable = stk->immutable || context->namespaces[i]->immutable; stk->refCount=1; context->stackPtr++; got=1; break; } if (!got) { sprintf(context->errStat.errBuff,"No such variable '%s'.",key); TBADD(ERR_NAMESPACE); goto cleanup_on_error; } break; } case 4: // Lookup value (pointer) { int i; char *key = charaux; *lastOpAssign=0; for (i=context->ns_ptr ; ; i=1) { pplObj *obj = (pplObj *)ppl_dictLookup(context->namespaces[i] , key); if ((obj==NULL)&&(!context->namespaces[i]->immutable)) { pplObjZom(stk , 1); // Create a temporary zombie for now stk->refCount=1; ppl_dictAppendCpy(context->namespaces[i] , key , stk , sizeof(pplObj)); stk->amMalloced=0; obj = (pplObj *)ppl_dictLookup(context->namespaces[i] , key); if (obj==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup_on_error; } } if ((obj==NULL)||((context->namespaces[i]->immutable)&&(obj->objType!=PPLOBJ_GLOB))) { sprintf(context->errStat.errBuff,"Cannot modify variable in immutable namespace."); TBADD(ERR_NAMESPACE); goto cleanup_on_error; } if (obj->objType==PPLOBJ_GLOB) { if (i<2) { sprintf(context->errStat.errBuff,"Variable declared global in global namespace."); TBADD(ERR_NAMESPACE); goto cleanup_on_error; } continue; } pplObjCpy(stk , obj , 1 , 0 , 1); stk->refCount=1; context->stackPtr++; break; } break; } case 5: // Dereference value { char *key = charaux; pplObj *in = stk-1; pplObj *in_cpy = NULL; pplObj *iter = in; int t = iter->objType; int imm = iter->immutable; int found = 0; *lastOpAssign = 0; // Make copy of object that will be self_this (in, which we therefore don't garbage below) in_cpy = (pplObj *)malloc(sizeof(pplObj)); if (in_cpy == NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup_on_error; } memcpy(in_cpy, in, sizeof(pplObj)); in_cpy->refCount=1; in_cpy->amMalloced=1; // Loop through module / class instance and its prototypes looking for named method for ( ; (t==PPLOBJ_MOD)||(t==PPLOBJ_USER) ; iter=iter->objPrototype , t=iter->objType ) { dict *d = (dict *)(iter->auxil); pplObj *obj = (pplObj *)ppl_dictLookup(d , key); imm = imm || iter->immutable || d->immutable; if ((obj==NULL) || (obj->objType==PPLOBJ_ZOM) || (obj->objType==PPLOBJ_GLOB)) { imm=1; continue; } // Named methods of prototypes are immutable pplObjCpy(stk-1 , obj , 1 , 0 , 1); (stk-1)->immutable = (stk-1)->immutable || imm; (stk-1)->refCount=1; found = 1; break; } if (!found) // If module or class instance doesn't have named method, see if type has named method { dict *d = pplObjMethods[in->objType]; pplObj *obj = (pplObj *)ppl_dictLookup(d , key); if (obj==NULL) { sprintf(context->errStat.errBuff,"No such method '%s'.",key); TBADD(ERR_NAMESPACE); free(in_cpy); goto cleanup_on_error; } pplObjCpy(stk-1 , obj , 1 , 0 , 1); (stk-1)->immutable = 1; (stk-1)->refCount=1; } in->self_this = in_cpy; break; } case 6: // Dereference value (pointer) { char *key = charaux; int t = (stk-1)->objType; dict *d = (dict *)((stk-1)->auxil); *lastOpAssign=0; if ((stk-1)->immutable) { sprintf(context->errStat.errBuff,"Cannot modify variable in immutable namespace."); TBADD(ERR_TYPE); goto cleanup_on_error; } if ((t==PPLOBJ_MOD)||(t==PPLOBJ_USER)) { pplObj *obj = (pplObj *)ppl_dictLookup(d , key); if (d->immutable) { sprintf(context->errStat.errBuff,"Cannot modify variable in immutable namespace."); TBADD(ERR_TYPE); goto cleanup_on_error; } if (obj==NULL) { pplObjZom(stk , 0); // Create a temporary zombie for now stk->refCount=1; ppl_dictAppendCpy(d , key , stk , sizeof(pplObj)); obj = (pplObj *)ppl_dictLookup(d , key); if (obj==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup_on_error; } } STACK_POP; pplObjCpy(stk-1 , obj , 1 , 0 , 1); (stk-1)->refCount=1; context->stackPtr++; break; } else { sprintf(context->errStat.errBuff,"Cannot assign methods or variables to this object."); TBADD(ERR_TYPE); goto cleanup_on_error; } break; } case 7: // slice case 16: // slice pointer { int status=0, errType=-1; const int getPtr = (o==16); const int mode = in[j].auxil.i; const int range = (mode & 1) == 0; const int maxset = (mode & 2) != 0; const int minset = (mode & 4) != 0; int Nrange = 1 , i , min=0 , max=0; *lastOpAssign=0; if (range) { Nrange = minset + maxset; for (i=1; i<=Nrange; i++) { int *out = ((i==1)&&maxset) ? &max : &min; if ((stk-i)->objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Range limits when slicing must be numerical values; supplied limit has type <%s>.",pplObjTypeNames[(stk-1)->objType]); TBADD(ERR_TYPE); goto cleanup_on_error; } if (!(stk-i)->dimensionless) { sprintf(context->errStat.errBuff,"Range limits when slicing must be dimensionless numbers; supplied limit has units of <%s>.", ppl_printUnit(context, stk-i, NULL, NULL, 0, 1, 0) ); TBADD(ERR_NUMERICAL); goto cleanup_on_error; } if ((stk-i)->flagComplex) { sprintf(context->errStat.errBuff,"Range limits when slicing must be real numbers; supplied limit is complex."); TBADD(ERR_NUMERICAL); goto cleanup_on_error; } if ( (!gsl_finite((stk-i)->real)) || ((stk-i)->realreal>INT_MAX) ) { sprintf(context->errStat.errBuff,"Range limits when slicing must be in the range %d to %d.", INT_MIN, INT_MAX); TBADD(ERR_RANGE); goto cleanup_on_error; } *out = (int)(stk-i)->real; } } if (!range) ppl_sliceItem (context, getPtr, &status, &errType, context->errStat.errBuff); else ppl_sliceRange(context, minset, min, maxset, max, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } break; } case 8: // Make dict { int k; int len = in[j].auxil.i; dict *d = ppl_dictInit(1); *lastOpAssign=0; if (d==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (context->stackPtr<2*len) { sprintf(context->errStat.errBuff,"Attempt to make dictionary with too few items on the stack."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } for (k=0; kobjType!=PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Dictionary keys must be strings; supplied key has type <%s>.",pplObjTypeNames[(stk-2*(len-k))->objType]); TBADD(ERR_TYPE); goto cleanup_on_error; } for (k=0; kauxil) , (void *)&v , sizeof(pplObj) ); } for (k=0; k<2*len; k++) { STACK_POP; } pplObjDict(&context->stack[context->stackPtr] , 0 , 1 , d); context->stack[context->stackPtr].refCount=1; context->stackPtr++; break; } case 9: // Make list { int k; int len = in[j].auxil.i; list *l = ppl_listInit(1); *lastOpAssign=0; if (l==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (context->stackPtrerrStat.errBuff,"Attempt to make list with too few items on the stack."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } for (k=0; kstack[context->stackPtr] , 0 , 1 , l); context->stack[context->stackPtr].refCount=1; context->stackPtr++; break; } case 10: // Execute function call { int nArgs = in[j].auxil.i; *lastOpAssign=0; ppl_fnCall(context, inExpr, charpos, nArgs, dollarAllowed, iterDepth); if (context->errStat.status) goto cleanup_on_error; break; } case 11: // Operator { int t = in[j].auxil.i; *lastOpAssign=0; pplObjNum(stk, 0, 0, 0); stk->refCount=1; switch (t) { case 0x25: // - { CAST_TO_NUM(stk-1); (stk-1)->real *= -1; if ((stk-1)->flagComplex) (stk-1)->imag *=-1; break; } case 0x26: // + { CAST_TO_NUM(stk-1); break; } case 0xA7: // ~ { CAST_TO_INT(stk-1,"~"); (stk-1)->real = ~(int)((stk-1)->real); break; } case 0xA8: // ! { CAST_TO_BOOL(stk-1); (stk-1)->real = !(stk-1)->real; break; } case 0xC9: // ** { int status=0, errType=-1; CAST_TO_NUM(stk-1); CAST_TO_NUM(stk-2); ppl_uaPow(context, stk-2, stk-1, stk, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4A: // * { int status=0, errType=-1; ppl_opMul(context, stk-2, stk-1, stk, 1, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4B: // div { int status=0, errType=-1; ppl_opDiv(context, stk-2, stk-1, stk, 1, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4C: // mod { int status=0, errType=-1; CAST_TO_NUM(stk-1); CAST_TO_NUM(stk-2); ppl_uaMod(context, stk-2, stk-1, stk, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4D: // add { int status=0, errType=-1; ppl_opAdd(context, stk-2, stk-1, stk, 1, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4E: // sub { int status=0, errType=-1; ppl_opSub(context, stk-2, stk-1, stk, 1, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } STACK_POP; STACK_POP; memcpy(stk-2, stk, sizeof(pplObj)); context->stackPtr++; break; } case 0x4F: // << { CAST_TO_INT(stk-1,"<<"); CAST_TO_INT(stk-2,"<<"); (stk-2)->real = ((int)(stk-2)->real) << ((int)(stk-1)->real); STACK_POP; break; } case 0x50: // >> { CAST_TO_INT(stk-1,">>"); CAST_TO_INT(stk-2,">>"); (stk-2)->real = ((int)(stk-2)->real) >> ((int)(stk-1)->real); STACK_POP; break; } case 0x57: // & { CAST_TO_INT(stk-1,"&"); CAST_TO_INT(stk-2,"&"); (stk-2)->real = ((int)(stk-2)->real) & ((int)(stk-1)->real); STACK_POP; break; } case 0x58: // ^ { CAST_TO_INT(stk-1,"^"); CAST_TO_INT(stk-2,"^"); (stk-2)->real = ((int)(stk-2)->real) ^ ((int)(stk-1)->real); STACK_POP; break; } case 0x59: // | { CAST_TO_INT(stk-1,"|"); CAST_TO_INT(stk-2,"|"); (stk-2)->real = ((int)(stk-2)->real) | ((int)(stk-1)->real); STACK_POP; break; } case 0x5C: // swap-pop { ppl_garbageObject(stk-2); memcpy(stk-2, stk-1, sizeof(pplObj)); context->stackPtr--; break; } case 0x51: // < case 0x52: // <= case 0x53: // >= case 0x54: // > case 0x55: // == case 0x56: // != { int stat=0 , errType=-1 , cmp = pplObjCmp(context, stk-2, stk-1, &stat, &errType, context->errStat.errBuff, 0); if (stat) { TBADD(errType); goto cleanup_on_error; } if (t==0x51) stat = (cmp == -1); else if (t==0x52) stat = (cmp == -1) || (cmp==0); else if (t==0x53) stat = (cmp == 1) || (cmp==0); else if (t==0x54) stat = (cmp == 1); else if (t==0x55) stat = (cmp == 0); else stat = (cmp != 0); STACK_POP; STACK_POP; pplObjBool(stk-2,0,stat); (stk-2)->refCount=1; context->stackPtr++; break; } default: sprintf(context->errStat.errBuff,"Unknown operator with id=%d.",t); TBADD(ERR_INTERNAL); goto cleanup_on_error; } break; } case 12: // assignment operator { int t = in[j].auxil.i; pplObj *o = stk-2; pplObj *in = stk-1; pplObj *tmp= stk; int t2 = in->objType; int status = 0, errType=-1; *lastOpAssign=1; if (context->stackPtr < 2) { sprintf(context->errStat.errBuff,"Too few items on stack for assignment operator."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (o->self_lval == NULL) { sprintf(context->errStat.errBuff,"Assignment operators can only be applied to variables."); TBADD(ERR_TYPE); goto cleanup_on_error; } if (o->immutable) { sprintf(context->errStat.errBuff,"Cannot assign to an immutable object."); TBADD(ERR_TYPE); goto cleanup_on_error; } #define ASSIGN \ { \ tmp->refCount=1; \ if (o->self_dval==NULL) \ { \ int om = o->self_lval->amMalloced; \ int rc = o->self_lval->refCount; \ o->self_lval->amMalloced = 0; \ o->self_lval->refCount = 1; \ ppl_garbageObject(o->self_lval); \ pplObjCpy(o->self_lval, tmp, 0, om, 1); \ o->self_lval->refCount = rc; \ } \ else /* Assign vector or matrix element */ \ { \ if ((t2!=PPLOBJ_NUM) || (tmp->flagComplex)) { sprintf(context->errStat.errBuff,"Vectors and matrices can only contain real numbers."); TBADD(ERR_TYPE); goto cleanup_on_error; } \ if (!ppl_unitsDimEqual(o,tmp)) { sprintf(context->errStat.errBuff,"Cannot insert element with dimensions <%s> into vector with dimensions <%s>.", ppl_printUnit(context,tmp,NULL,NULL,0,1,0), ppl_printUnit(context,o,NULL,NULL,1,1,0)); TBADD(ERR_UNIT); goto cleanup_on_error; } \ *o->self_dval = tmp->real; \ } \ ppl_garbageObject(o); \ memcpy(o , tmp , sizeof(pplObj)); /* swap-pop */ \ STACK_POP; \ } if (t==0x40) // = { pplObjCpy(tmp, in, 0, 0, 1); tmp->immutable = 0; ASSIGN; } else if (t==0x41) // += { ppl_opAdd(context, o, in, tmp, 0, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } ASSIGN; } else if (t==0x42) // -= { ppl_opSub(context, o, in, tmp, 0, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } ASSIGN; } else if (t==0x43) // *= { ppl_opMul(context, o, in, tmp, 0, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } ASSIGN; } else if (t==0x44) // /= { ppl_opDiv(context, o, in, tmp, 0, &status, &errType, context->errStat.errBuff); if (status) { TBADD(errType); goto cleanup_on_error; } ASSIGN; } else { if (o->objType != PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"The fused operator-assignment operators can only be applied to numeric variables."); TBADD(ERR_TYPE); goto cleanup_on_error; } CAST_TO_NUM(in); pplObjNum(tmp, 0, 0, 0); switch (t) { case 0x45: // %= ppl_uaMod(context, o, in, tmp, &status, &errType, context->errStat.errBuff); break; case 0x46: // &= CAST_TO_INT(in,"&="); CAST_TO_INT(o,"&="); tmp->real = ((int)o->real) & ((int)in->real); break; case 0x47: // ^= CAST_TO_INT(in,"^="); CAST_TO_INT(o,"^="); tmp->real = ((int)o->real) ^ ((int)in->real); break; case 0x48: // |= CAST_TO_INT(in,"|="); CAST_TO_INT(o,"|="); tmp->real = ((int)o->real) | ((int)in->real); break; case 0x49: // <<= CAST_TO_INT(in,"<<="); CAST_TO_INT(o,"<<="); tmp->real = ((int)o->real) << ((int)in->real); break; case 0x4A: // >>= CAST_TO_INT(in,">>="); CAST_TO_INT(o,">>="); tmp->real = ((int)o->real) >> ((int)in->real); break; case 0x4B: // **= ppl_uaPow(context, o, in, tmp, &status, &errType, context->errStat.errBuff); break; default: sprintf(context->errStat.errBuff,"Unknown fused operator-assignment operator with id=%d.",t); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (status) { TBADD(errType); goto cleanup_on_error; } ASSIGN; break; } break; } case 13: // increment and decrement operators { int t = in[j].auxil.i; pplObj *o = stk-1; *lastOpAssign=1; if (context->stackPtr < 1) { sprintf(context->errStat.errBuff,"Too few items on stack for -- or ++ operator."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (o->self_lval == NULL) { sprintf(context->errStat.errBuff,"The -- and ++ operators can only be applied to variables."); TBADD(ERR_TYPE); goto cleanup_on_error; } if (o->objType != PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"The -- and ++ operators can only be applied to numeric variables."); TBADD(ERR_TYPE); goto cleanup_on_error; } if (o->immutable) { sprintf(context->errStat.errBuff,"Cannot modify an immutable object."); TBADD(ERR_TYPE); goto cleanup_on_error; } switch (t) { case 0x21: // -- (post-eval) case 0x23: // -- (pre-eval) if (o->self_dval != NULL) (*o->self_dval)--; else o->self_lval->real--; if (t==0x23) o->real = (o->self_dval != NULL) ? *o->self_dval : o->self_lval->real; break; case 0x22: // ++ (post-eval) case 0x24: // ++ (pre-eval) if (o->self_dval != NULL) (*o->self_dval)++; else o->self_lval->real++; if (t==0x24) o->real = (o->self_dval != NULL) ? *o->self_dval : o->self_lval->real; break; default: sprintf(context->errStat.errBuff,"Unknown increment/decrement operator with id=%d.",t); TBADD(ERR_INTERNAL); goto cleanup_on_error; } break; } case 14: // string substitution { int Nsubs = in[j].auxil.i; int i; if (context->stackPtr < Nsubs+1) { sprintf(context->errStat.errBuff,"Too few items on stack for string substitution operator."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } if ((stk-Nsubs-1)->objType != PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Attempt to apply string substitution operator to a non-string."); TBADD(ERR_TYPE); goto cleanup_on_error; } expEval_stringSubs(context, inExpr, charpos, Nsubs); if (context->errStat.status) { goto cast_fail; } stk->refCount = 1; context->stackPtr--; for (i=0; istack[context->stackPtr] , stk , sizeof(pplObj)); context->stackPtr++; break; } case 15: // dollar operator { int t; if (context->stackPtr < 1) { sprintf(context->errStat.errBuff,"Too few items on stack for dollar operator."); TBADD(ERR_INTERNAL); goto cleanup_on_error; } t = context->stack[context->stackPtr-1].objType; if (t==PPLOBJ_NUM) { double num = context->stack[context->stackPtr-1].real; int n; if ((num<-4)||(num>MAX_DATACOLS)||(!gsl_finite(num))) { sprintf(context->errStat.errBuff,"The $ column reference operator was passed an illegal column number; must be in range -3 to %d.",MAX_DATACOLS); TBADD(ERR_RANGE); goto cleanup_on_error; } n = (int)round(num); ppl_dollarOp_fetchColByNum(context, inExpr, charpos, n); if (context->errStat.status) goto cast_fail; } else if (t==PPLOBJ_STR) { char *name = (char *)context->stack[context->stackPtr-1].auxil; int malloced = context->stack[context->stackPtr-1].auxilMalloced; ppl_dollarOp_fetchColByName(context, inExpr, charpos, name); if (malloced) free(name); } else { sprintf(context->errStat.errBuff,"The $ column reference operator can only act on column numbers and (string) names. Object supplied was of type <%s>,",pplObjTypeNames[t]); TBADD(ERR_TYPE); goto cleanup_on_error; } break; } case 17: // branch if false { int branch; *lastOpAssign=0; CAST_TO_BOOL(stk-1); branch = (stk-1)->real == 0; if (branch) { len = in[j].auxil.i-pos; if (in[j].flag) { STACK_POP; } } else { STACK_POP; } break; } case 18: // branch if true { int branch; *lastOpAssign=0; CAST_TO_BOOL(stk-1); branch = (stk-1)->real != 0; if (branch) { len = in[j].auxil.i-pos; if (in[j].flag) { STACK_POP; } } else { STACK_POP; } break; } case 19: // goto { *lastOpAssign=0; len = in[j].auxil.i-pos; break; } case 20: // make boolean { *lastOpAssign=0; CAST_TO_BOOL(stk-1); break; } default: sprintf(context->errStat.errBuff,"Illegal bytecode opcode passed to expEval."); charpos=0; TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (o==0) break; j = pos+len; } if (context->stackPtr <= 0) { sprintf(context->errStat.errBuff,"Unexpected empty stack at end of evaluation."); charpos=0; TBADD(ERR_INTERNAL); goto cleanup_on_error; } if (context->stackPtr != initialStackPtr+1) { ppl_warning(&context->errcontext, ERR_INTERNAL, "Unexpected junk on stack in expEval."); } return &context->stack[context->stackPtr-1]; cast_fail: cleanup_on_error: for ( ; context->stackPtr>initialStackPtr ; ) { STACK_POP; } return NULL; } pyxplot-0.9.2/src/expressions/traceback.h0000664000175000017500000000260112026340554017064 0ustar dcf21dcf21// traceback.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: traceback.h 1285 2012-08-10 01:07:03Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _TRACEBACK_H #define _TRACEBACK_H 1 #define TB_MAXLEVEL 8 #include "stringTools/strConstants.h" typedef struct traceback { int errPos, errLine, amErrMsgExpr, amErrMsgCmd; long sourceId; char source[FNAME_LENGTH]; char context[FNAME_LENGTH]; char *linetext; } traceback; typedef struct errStatus { int errType, status, tracebackDepth; char errMsgExpr[LSTR_LENGTH]; long sourceIdExpr; int errPosExpr, oldErrPosExpr; char errMsgCmd [LSTR_LENGTH]; long sourceIdCmd; int errPosCmd , oldErrPosCmd; char errBuff[LSTR_LENGTH]; traceback tbLevel[TB_MAXLEVEL]; } errStatus; #endif pyxplot-0.9.2/src/expressions/expEvalOps.c0000664000175000017500000006337112026340554017241 0ustar dcf21dcf21// expEvalOps.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalOps.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #define GSL_RANGE_CHECK_OFF 1 #include "expressions/expEval.h" #include "expressions/expEvalOps.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjCmp.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "pplConstants.h" #define CAST_TO_NUM2(X) \ { \ double d=0; \ int t=(X)->objType; \ int rc=(X)->refCount; \ if (t!=PPLOBJ_NUM) \ { \ switch (t) \ { \ case PPLOBJ_BOOL: d = ((X)->real!=0); break; \ case PPLOBJ_STR : \ { \ int len; char *c=(char *)(X)->auxil; \ d = ppl_getFloat(c, &len); \ if (len>0) { while ((c[len]>'\0')&&(c[len]<=' ')) len++; } \ if ((len<0)||(c[len]!='\0')) { *status=1; *errType=ERR_TYPE; sprintf(errText,"Attempt to implicitly cast string to number failed: string is not a valid number."); goto cast_fail; } \ break; \ } \ default: \ { *status=1; *errType=ERR_TYPE; sprintf(errText,"Cannot implicitly cast an object of type <%s> to a number.",pplObjTypeNames[t]); goto cast_fail; } \ } \ ppl_garbageObject(X); \ pplObjNum(X,0,d,0); \ (X)->refCount=rc; \ } \ } void ppl_opAdd(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText) { int t1 = a->objType; int t2 = b->objType; if ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_NUM)) { goto am_numeric; } else if ((t1==PPLOBJ_STR)&&(t2==PPLOBJ_STR)) // adding strings: concatenate { char *tmp; int l1 = strlen((char *)a->auxil); int l2 = strlen((char *)b->auxil); int l = l1+l2+1; tmp = (char *)malloc(l); if (tmp==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } strcpy(tmp , (char *)a->auxil); strcpy(tmp+l1 , (char *)b->auxil); pplObjStr(o,0,1,tmp); } else if ((t1==PPLOBJ_COL)&&(t2==PPLOBJ_COL)) // adding colors { double r1,g1,b1,r2,g2,b2; if (round(a->exponent[0])==SW_COLSPACE_RGB ) { r1=a->exponent[8]; g1=a->exponent[9]; b1=a->exponent[10]; } else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&r1,&g1,&b1); else pplcol_HSBtoRGB (a->exponent[8],a->exponent[9],a->exponent[10],&r1,&g1,&b1); if (round(b->exponent[0])==SW_COLSPACE_RGB ) { r2=b->exponent[8]; g2=b->exponent[9]; b2=b->exponent[10]; } else if (round(b->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(b->exponent[8],b->exponent[9],b->exponent[10],b->exponent[11],&r2,&g2,&b2); else pplcol_HSBtoRGB (b->exponent[8],b->exponent[9],b->exponent[10],&r2,&g2,&b2); r1+=r2; g1+=g2; b1+=b2; pplObjColor(o,0,SW_COLSPACE_RGB,r1,g1,b1,0); } else if ( ((t1==PPLOBJ_DATE)&&(t2==PPLOBJ_NUM)) || ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_DATE)) ) // adding time interval to date { int i; pplObj *num = (t1==PPLOBJ_NUM) ? a : b; for (i=0; iexponent[i] != (i==UNIT_TIME)) { *status=1; *errType=ERR_UNIT; sprintf(errText, "Can only add quantities with units of time to dates. Attempt to add a quantity with units of <%s>.", ppl_printUnit(context,num,NULL,NULL,1,1,0)); return; } pplObjDate(o,0,a->real+b->real); } else if ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_VEC)) // adding vectors { int i; gsl_vector *v1 = ((pplVector *)(a->auxil))->v; gsl_vector *v2 = ((pplVector *)(b->auxil))->v; gsl_vector *vo; if (!ppl_unitsDimEqual(a, b)) { if (a->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0), ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if (v1->size != v2->size) { sprintf(errText, "Can only add vectors of a common size. Left operand has length of %ld, while right operand has length of %ld.", (long)v1->size, (long)v2->size); *errType=ERR_RANGE; *status = 1; return; } if (pplObjVector(o,0,1,v1->size)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(o->auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo , i , gsl_vector_get(v1,i) + gsl_vector_get(v2,i)); ppl_unitsDimCpy(o,a); } else if ((t1==PPLOBJ_LIST)&&(t2==PPLOBJ_LIST)) // adding lists { listIterator *li; pplObj *item, buff; list *l; if (pplObjList(o,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l = (list *)o->auxil; li = ppl_listIterateInit((list *)a->auxil); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } li = ppl_listIterateInit((list *)b->auxil); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } } else if ((t1==PPLOBJ_LIST)&&(t2==PPLOBJ_VEC)) // adding vector to list { int i; listIterator *li; pplObj *item, buff; gsl_vector *bv = ((pplVector *)(b->auxil))->v; list *l; if (pplObjList(o,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l = (list *)o->auxil; li = ppl_listIterateInit((list *)a->auxil); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } pplObjNum(&buff,1,0,0); ppl_unitsDimCpy(&buff,b); for (i=0; isize; i++) { buff.real=gsl_vector_get(bv,i); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } } else if ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_LIST)) // adding list to vector { int i; listIterator *li; pplObj *item, buff; gsl_vector *av = ((pplVector *)(a->auxil))->v; list *l; if (pplObjList(o,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l = (list *)o->auxil; pplObjNum(&buff,1,0,0); ppl_unitsDimCpy(&buff,a); for (i=0; isize; i++) { buff.real=gsl_vector_get(av,i); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } li = ppl_listIterateInit((list *)b->auxil); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_listAppendCpy(l, (void *)&buff, sizeof(pplObj) ); } } else if ( ((t1==PPLOBJ_DICT)&&(t2==PPLOBJ_DICT)) || // adding dictionaries ((t1==PPLOBJ_MOD )&&(t2==PPLOBJ_MOD )) ) // adding modules { dictIterator *di; pplObj *item, buff; dict *d; char *key; if ( ((t1==PPLOBJ_DICT)?pplObjDict(o,0,1,NULL):pplObjModule(o,0,1,0)) == NULL ) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } d = (dict *)o->auxil; di = ppl_dictIterateInit((dict *)a->auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_dictAppendCpy(d, key, (void *)&buff, sizeof(pplObj) ); } di = ppl_dictIterateInit((dict *)b->auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { pplObjCpy(&buff, item, 0, 1, 1); ppl_dictAppendCpy(d, key, (void *)&buff, sizeof(pplObj) ); } } else if ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_MAT)) // adding matrices { int i,j; gsl_matrix *m1 = ((pplMatrix *)(a->auxil))->m; gsl_matrix *m2 = ((pplMatrix *)(b->auxil))->m; gsl_matrix *mo; if (!ppl_unitsDimEqual(a, b)) { if (a->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0), ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if ( (m1->size1 != m2->size1) || (m1->size2 != m2->size2) ) { sprintf(errText, "Can only add matrices of a common size. Left operand has size of %ldx%ld, while right operand has size of %ldx%ld.", (long)m1->size1, (long)m1->size2, (long)m2->size1, (long)m2->size2); *errType=ERR_RANGE; *status = 1; return; } if (pplObjMatrix(o,0,1,m1->size1,m2->size2)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } mo = ((pplMatrix *)(o->auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) gsl_matrix_set(mo , i , j , gsl_matrix_get(m1,i,j) + gsl_matrix_get(m2,i,j)); ppl_unitsDimCpy(o,a); } else // adding numbers { CAST_TO_NUM2(a); CAST_TO_NUM2(b); am_numeric: o->objType = PPLOBJ_NUM; // Do this by hand rather than calling pplObjNum to save time (some field will be set by function call below) o->objPrototype = &pplObjPrototypes[PPLOBJ_NUM]; o->self_lval = NULL; o->self_dval = NULL; o->self_this = NULL; o->amMalloced = 0; o->immutable = 0; ppl_uaAdd(context, a, b, o, status, errType, errText); } cast_fail: return; } void ppl_opSub(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText) { int t1 = a->objType; int t2 = b->objType; if ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_NUM)) { goto am_numeric; } else if ((t1==PPLOBJ_DATE)&&(t2==PPLOBJ_DATE)) // subtracting dates: return time interval { pplObjNum(o,0,a->real-b->real,0); o->dimensionless=0; o->exponent[UNIT_TIME]=1; } else if ((t1==PPLOBJ_DATE)&&(t2==PPLOBJ_NUM)) // subtracting time interval from date { int i; for (i=0; iexponent[i] != (i==UNIT_TIME)) { *status=1; *errType=ERR_UNIT; sprintf(errText, "Can only subtract quantities with units of time from dates. Attempt to subtract a quantity with units of <%s>.", ppl_printUnit(context,b,NULL,NULL,1,1,0)); return; } pplObjDate(o,0,a->real-b->real); } else if ((t1==PPLOBJ_COL)&&(t2==PPLOBJ_COL)) // subtracting colors { double r1,g1,b1,r2,g2,b2; if (round(a->exponent[0])==SW_COLSPACE_RGB ) { r1=a->exponent[8]; g1=a->exponent[9]; b1=a->exponent[10]; } else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&r1,&g1,&b1); else pplcol_HSBtoRGB (a->exponent[8],a->exponent[9],a->exponent[10],&r1,&g1,&b1); if (round(b->exponent[0])==SW_COLSPACE_RGB ) { r2=b->exponent[8]; g2=b->exponent[9]; b2=b->exponent[10]; } else if (round(b->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(b->exponent[8],b->exponent[9],b->exponent[10],b->exponent[11],&r2,&g2,&b2); else pplcol_HSBtoRGB (b->exponent[8],b->exponent[9],b->exponent[10],&r2,&g2,&b2); r1-=r2; g1-=g2; b1-=b2; pplObjColor(o,0,SW_COLSPACE_RGB,r1,g1,b1,0); } else if ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_VEC)) // subtracting vectors { int i; gsl_vector *v1 = ((pplVector *)(a->auxil))->v; gsl_vector *v2 = ((pplVector *)(b->auxil))->v; gsl_vector *vo; if (ppl_unitsDimEqual(a, b) == 0) { if (a->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0), ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if (v1->size != v2->size) { sprintf(errText, "Can only subtract vectors of a common size. Left operand has length of %ld, while right operand has length of %ld.", (long)v1->size, (long)v2->size); *errType=ERR_RANGE; *status = 1; return; } if (pplObjVector(o,0,1,v1->size)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(o->auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo , i , gsl_vector_get(v1,i) - gsl_vector_get(v2,i)); ppl_unitsDimCpy(o,a); } else if ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_MAT)) // subtracting matrices { int i,j; gsl_matrix *m1 = ((pplMatrix *)(a->auxil))->m; gsl_matrix *m2 = ((pplMatrix *)(b->auxil))->m; gsl_matrix *mo; if (ppl_unitsDimEqual(a, b) == 0) { if (a->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(context, a, NULL, NULL, 0, 1, 0), ppl_printUnit(context, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if ( (m1->size1 != m2->size1) || (m1->size2 != m2->size2) ) { sprintf(errText, "Can only subtract matrices of a common size. Left operand has size of %ldx%ld, while right operand has size of %ldx%ld.", (long)m1->size1, (long)m1->size2, (long)m2->size1, (long)m2->size2); *errType=ERR_RANGE; *status = 1; return; } if (pplObjMatrix(o,0,1,m1->size1,m2->size2)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } mo = ((pplMatrix *)(o->auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) gsl_matrix_set(mo , i , j , gsl_matrix_get(m1,i,j) - gsl_matrix_get(m2,i,j)); ppl_unitsDimCpy(o,a); } else // subtracting numbers { CAST_TO_NUM2(a); CAST_TO_NUM2(b); am_numeric: o->objType = PPLOBJ_NUM; // Do this by hand rather than calling pplObjNum to save time (some field will be set by function call below) o->objPrototype = &pplObjPrototypes[PPLOBJ_NUM]; o->self_lval = NULL; o->self_dval = NULL; o->self_this = NULL; o->amMalloced = 0; o->immutable = 0; ppl_uaSub(context, a, b, o, status, errType, errText); } cast_fail: return; } void ppl_opMul(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText) { int t1 = a->objType; int t2 = b->objType; if ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_NUM)) { goto am_numeric; } else if ( ((t1==PPLOBJ_COL)&&(t2==PPLOBJ_NUM)) || ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_COL)) ) // multiplying colors by numbers { double r1,g1,b1; pplObj *c = (t1==PPLOBJ_COL)?a:b; pplObj *n = (t1==PPLOBJ_COL)?b:a; double m = n->real; if ((!n->dimensionless) || (n->flagComplex) || (!gsl_finite(m)) || (m<0)) { sprintf(errText, "Can only multiply colors by dimensionless, real, positive numbers."); *errType=ERR_RANGE; *status=1; return; } if (round(c->exponent[0])==SW_COLSPACE_RGB ) { r1=c->exponent[8]; g1=c->exponent[9]; b1=c->exponent[10]; } else if (round(c->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(c->exponent[8],c->exponent[9],c->exponent[10],c->exponent[11],&r1,&g1,&b1); else pplcol_HSBtoRGB (c->exponent[8],c->exponent[9],c->exponent[10],&r1,&g1,&b1); r1*=m; g1*=m; b1*=m; pplObjColor(o,0,SW_COLSPACE_RGB,r1,g1,b1,0); } else if ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_VEC)) // multiplying vectors (scalar dot product) { gsl_vector *v1 = ((pplVector *)(a->auxil))->v; gsl_vector *v2 = ((pplVector *)(b->auxil))->v; int i; double acc=0; if (v1->size != v2->size) { sprintf(errText, "Can only form dot-product of vectors of a common size. Left operand has length of %ld, while right operand has length of %ld.", (long)v1->size, (long)v2->size); *errType=ERR_RANGE; *status=1; return; } a->real=a->imag=b->real=b->imag=0 ; a->flagComplex=b->flagComplex=0; ppl_uaMul(context, a, b, o, status, errType, errText); for (i=0; isize; i++) acc += gsl_vector_get(v1,i) * gsl_vector_get(v2,i); o->real=acc; o->imag=0; o->flagComplex=0; } else if ( ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_NUM)) || // multiplying vector by number ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_VEC)) ) // multiplying number by vector { int i; pplObj *num = (t1==PPLOBJ_NUM) ? a : b; pplObj *vec = (t1==PPLOBJ_VEC) ? a : b; gsl_vector *v = ((pplVector *)(vec->auxil))->v; gsl_vector *vo = NULL; if (num->flagComplex) { sprintf(errText, "Vectors can only contain real numbers, and cannot be multiplied by complex numbers."); *errType=ERR_NUMERICAL; *status = 1; return; } vec->real=1; vec->imag=0; vec->flagComplex=0; if (pplObjVector(o,0,1,v->size)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ppl_uaMul(context, a, b, o, status, errType, errText); vo = ((pplVector *)(o->auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo, i, gsl_vector_get(v,i) * o->real); o->real=0; } else if ( ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_NUM)) || // multiplying matrix by number ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_MAT)) ) // multiplying number by matrix { int i,j; pplObj *num = (t1==PPLOBJ_NUM) ? a : b; pplObj *mat = (t1==PPLOBJ_MAT) ? a : b; gsl_matrix *m = ((pplMatrix *)(mat->auxil))->m; gsl_matrix *mo = NULL; if (num->flagComplex) { sprintf(errText, "Matrices can only contain real numbers, and cannot be multiplied by complex numbers."); *errType=ERR_NUMERICAL; *status = 1; return; } mat->real=1; mat->imag=0; mat->flagComplex=0; if (pplObjMatrix(o,0,1,m->size1,m->size2)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ppl_uaMul(context, a, b, o, status, errType, errText); mo = ((pplMatrix *)(o->auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) gsl_matrix_set(mo, i, j, gsl_matrix_get(m,i,j) * o->real); o->real=0; } else if ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_VEC)) // matrix-vector multiplication { int gslerr=0; gsl_matrix *m = ((pplMatrix *)(a->auxil))->m; gsl_vector *v = ((pplVector *)(b->auxil))->v; gsl_vector *vo = NULL; if (m->size2 != v->size) { sprintf(errText, "Matrices can only be multiplied by vectors when the number of matrix columns (%ld) equals the number of vector rows (%ld).", (long)m->size2, (long)v->size); *errType=ERR_NUMERICAL; *status = 1; return; } if (pplObjVector(o,0,1,m->size1)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } a->real=b->real=1; a->imag=b->imag=0; a->flagComplex=b->flagComplex=0; ppl_uaMul(context, a, b, o, status, errType, errText); vo = ((pplVector *)(o->auxil))->v; if ((gslerr = gsl_blas_dgemv(CblasNoTrans, 1, m, v, 0, vo))!=0) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, gsl_strerror(gslerr)); return; } } else if ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_MAT)) // matrix-matrix multiplication { int gslerr=0; gsl_matrix *m1 = ((pplMatrix *)(a->auxil))->m; gsl_matrix *m2 = ((pplMatrix *)(b->auxil))->m; gsl_matrix *mo = NULL; if (m1->size2 != m2->size1) { sprintf(errText, "Matrices can only be multiplied when the number of matrix columns (%ld) in the left matrix equals the number of rows (%ld) in the right matrix.", (long)m1->size2, (long)m2->size1); *errType=ERR_NUMERICAL; *status = 1; return; } if (pplObjMatrix(o,0,1,m1->size1,m2->size2)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } a->real=b->real=1; a->imag=b->imag=0; a->flagComplex=b->flagComplex=0; ppl_uaMul(context, a, b, o, status, errType, errText); mo = ((pplMatrix *)(o->auxil))->m; if ((gslerr = gsl_blas_dgemm(CblasNoTrans, CblasNoTrans, 1, m1, m2, 0, mo))!=0) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, gsl_strerror(gslerr)); return; } } else // multiplying numbers { CAST_TO_NUM2(a); CAST_TO_NUM2(b); am_numeric: o->objType = PPLOBJ_NUM; // Do this by hand rather than calling pplObjNum to save time (some field will be set by function call below) o->objPrototype = &pplObjPrototypes[PPLOBJ_NUM]; o->self_lval = NULL; o->self_dval = NULL; o->self_this = NULL; o->amMalloced = 0; o->immutable = 0; ppl_uaMul(context, a, b, o, status, errType, errText); } cast_fail: return; } void ppl_opDiv(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText) { int t1 = a->objType; int t2 = b->objType; if ((t1==PPLOBJ_NUM)&&(t2==PPLOBJ_NUM)) { goto am_numeric; } else if ((t1==PPLOBJ_COL)&&(t2==PPLOBJ_NUM)) // dividing colors by numbers { double r1,g1,b1; double m = b->real; if ((!b->dimensionless) || (b->flagComplex) || (!gsl_finite(m)) || (m<0)) { sprintf(errText, "Can only divide colors by dimensionless, real, positive numbers."); *errType=ERR_RANGE; *status=1; return; } if (round(a->exponent[0])==SW_COLSPACE_RGB ) { r1=a->exponent[8]; g1=a->exponent[9]; b1=a->exponent[10]; } else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&r1,&g1,&b1); else pplcol_HSBtoRGB (a->exponent[8],a->exponent[9],a->exponent[10],&r1,&g1,&b1); r1/=m; g1/=m; b1/=m; pplObjColor(o,0,SW_COLSPACE_RGB,r1,g1,b1,0); } else if ((t1==PPLOBJ_VEC)&&(t2==PPLOBJ_NUM)) // dividing vector by number { int i; gsl_vector *v = ((pplVector *)(a->auxil))->v; gsl_vector *vo = NULL; if (b->flagComplex) { sprintf(errText, "Vectors can only contain real numbers, and cannot be divided by complex numbers."); *errType=ERR_NUMERICAL; *status = 1; return; } a->real=1; a->imag=0; a->flagComplex=0; if (pplObjVector(o,0,1,v->size)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ppl_uaDiv(context, a, b, o, status, errType, errText); vo = ((pplVector *)(o->auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo, i, gsl_vector_get(v,i) * o->real); o->real=0; } else if ((t1==PPLOBJ_MAT)&&(t2==PPLOBJ_NUM)) // dividing matrix by number { int i,j; gsl_matrix *m = ((pplMatrix *)(a->auxil))->m; gsl_matrix *mo = NULL; if (b->flagComplex) { sprintf(errText, "Matrices can only contain real numbers, and cannot be divided by complex numbers."); *errType=ERR_NUMERICAL; *status = 1; return; } a->real=1; a->imag=0; a->flagComplex=0; if (pplObjMatrix(o,0,1,m->size1,m->size2)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ppl_uaDiv(context, a, b, o, status, errType, errText); mo = ((pplMatrix *)(o->auxil))->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) gsl_matrix_set(mo, i, j, gsl_matrix_get(m,i,j) * o->real); o->real=0; } else // dividing numbers { CAST_TO_NUM2(a); CAST_TO_NUM2(b); am_numeric: o->objType = PPLOBJ_NUM; // Do this by hand rather than calling pplObjNum to save time (some field will be set by function call below) o->objPrototype = &pplObjPrototypes[PPLOBJ_NUM]; o->self_lval = NULL; o->self_dval = NULL; o->self_this = NULL; o->amMalloced = 0; o->immutable = 0; ppl_uaDiv(context, a, b, o, status, errType, errText); } cast_fail: return; } pyxplot-0.9.2/src/expressions/expEvalCalculus.h0000664000175000017500000000247012026340554020251 0ustar dcf21dcf21// expEvalCalculus.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalCalculus.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPEVALCALCULUS_H #define _EXPEVALCALCULUS_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_expIntegrate (ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *expr, int exprPos, char *dummy, pplObj *min , pplObj *max , pplObj *out, int dollarAllowed, int recursionDepth); void ppl_expDifferentiate(ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *expr, int exprPos, char *dummy, pplObj *point, pplObj *step, pplObj *out, int dollarAllowed, int recursionDepth); #endif pyxplot-0.9.2/src/expressions/expEval.h0000664000175000017500000001072312026340554016555 0ustar dcf21dcf21// expEval.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEval.h 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPEVAL_H #define _EXPEVAL_H 1 #include "expressions/expCompile.h" #include "userspace/context.h" #include "userspace/pplObj.h" #define CAST_TO_NUM(X) \ { \ double d=0; \ int t=(X)->objType; \ int rc=(X)->refCount; \ if (t!=PPLOBJ_NUM) \ { \ switch (t) \ { \ case PPLOBJ_BOOL: d = ((X)->real!=0); break; \ case PPLOBJ_STR : \ { \ int len; char *c=(char *)(X)->auxil; \ d = ppl_getFloat(c, &len); \ if (len>0) { while ((c[len]>'\0')&&(c[len]<=' ')) len++; } \ if ((len<0)||(c[len]!='\0')) { sprintf(context->errStat.errBuff,"Attempt to implicitly cast string to number failed: string is not a valid number."); TBADD(ERR_TYPE); goto cast_fail; } \ break; \ } \ default: \ { sprintf(context->errStat.errBuff,"Cannot implicitly cast an object of type <%s> to a number.",pplObjTypeNames[t]); TBADD(ERR_TYPE); goto cast_fail; } \ } \ ppl_garbageObject(X); \ pplObjNum(X,0,d,0); \ (X)->refCount=rc; \ } \ } #define CAST_TO_REAL(X,OP) \ { \ CAST_TO_NUM(X); \ if ((X)->flagComplex) { sprintf(context->errStat.errBuff,"The %s operator can only act on real numbers.",OP); TBADD(ERR_RANGE); goto cast_fail; } \ } #define CAST_TO_INT(X,OP) \ { \ CAST_TO_REAL(X,OP); \ if (!(X)->dimensionless) { sprintf(context->errStat.errBuff,"The %s operator is an integer operator which can only act on dimensionless numbers: supplied operand has units of <%s>.",OP,ppl_printUnit(context,X,NULL,NULL,0,1,0)); TBADD(ERR_UNIT); goto cast_fail; } \ if (((X)->real < INT_MIN) || ((X)->real > INT_MAX)) { sprintf(context->errStat.errBuff,"The %s operator can only act on integers in the range %d to %d.",OP,INT_MIN,INT_MAX); TBADD(ERR_RANGE); goto cast_fail; } \ } #define CAST_TO_BOOL(X) \ { \ int t=(X)->objType, s; \ int rc=(X)->refCount; \ if (t!=PPLOBJ_BOOL) \ { \ switch (t) \ { \ case PPLOBJ_NUM : s = (((X)->real!=0)||((X)->imag!=0)) && gsl_finite((X)->real) && gsl_finite((X)->imag) && (((X)->imag==0)||(context->set->term_current.ComplexNumbers == SW_ONOFF_ON)); break; \ case PPLOBJ_STR : s = ((char *)(X)->auxil)[0]!='\0'; break; \ case PPLOBJ_ZOM : \ case PPLOBJ_EXC : \ case PPLOBJ_NULL: s = 0; break; \ case PPLOBJ_DICT: s = (((dict *)(X)->auxil)->length!=0); break; \ case PPLOBJ_LIST: s = (((list *)(X)->auxil)->length!=0); break; \ case PPLOBJ_VEC : s = (((pplVector *)(X)->auxil)->v->size!=0); break; \ case PPLOBJ_MAT : s = (((pplMatrix *)(X)->auxil)->m->size1!=0) || (((pplMatrix *)(X)->auxil)->m->size2!=0); break; \ case PPLOBJ_FILE: s = (((pplFile *)(X)->auxil)->open!=0); break; \ default : s = 1; break; \ } \ ppl_garbageObject(X); \ pplObjBool(X,0,s); \ (X)->refCount=rc; \ } \ } #define STACK_REQUEST(C,N) \ { \ C->stackFull=0; \ if (C->stackPtr > C->stackSize-1024-N) \ { \ int newStackSize = 2*C->stackSize; \ pplObj *newStack = (pplObj *)realloc(C->stack , newStackSize * sizeof(pplObj)); \ if (newStack != NULL) { C->stack=newStack; C->stackSize=newStackSize; } \ else C->stackFull=1; \ } \ } #define STACK_MUSTHAVE(C,N) \ { \ C->stackFull = (C->stackPtr > C->stackSize-4-N); \ } #define STACK_REINIT(C) \ { \ while (context->stackPtr>0) { STACK_POP; } \ \ if (C->stackSize > STACK_DEFAULT) \ { \ int newStackSize = 2*C->stackSize; \ pplObj *newStack = (pplObj *)malloc(newStackSize * sizeof(pplObj)); \ if (newStack != NULL) { free(C->stack); C->stack=newStack; C->stackSize=newStackSize; } \ } \ } pplObj *ppl_expEval(ppl_context *context, pplExpr *inExpr, int *lastOpAssign, int dollarAllowed, int iterDepth); #endif pyxplot-0.9.2/src/expressions/fnCall.h0000664000175000017500000000200112026340554016336 0ustar dcf21dcf21// fnCall.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fnCall.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _FNCALL_H #define _FNCALL_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_fnCall(ppl_context *context, pplExpr *inExpr, int intExprCharPos, int nArgs, int dollarAllowed, int iterDepth); #endif pyxplot-0.9.2/src/expressions/expEvalCalculus.c0000664000175000017500000003176112026340554020251 0ustar dcf21dcf21// expEvalCalculus.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalCalculus.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _EXPEVALCALCULUS_C 1 #include #include #include #include #include #include #include #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" typedef struct calculusComm { pplExpr *expr; ppl_context *context; pplObj *dummy; pplObj first; double dummyReal, dummyImag; unsigned char isFirst; unsigned char testingReal, varyingReal; int dollarAllowed; int integrate; int iterDepth; } calculusComm; double ppl_expEvalCalculusSlave(double x, void *params) { int lastOpAssign; double r,i; pplObj *output; calculusComm *data = (calculusComm *)params; if (data->context->errStat.status) return GSL_NAN; // We've previously had an error... so don't do any more work if (data->varyingReal) { data->dummy->real = x; data->dummy->imag = data->dummyImag; data->dummy->flagComplex = !ppl_dblEqual(data->dummy->imag,0); } else { data->dummy->imag = x; data->dummy->real = data->dummyReal; data->dummy->flagComplex = !ppl_dblEqual(data->dummy->imag,0); } output = ppl_expEval(data->context, data->expr, &lastOpAssign, data->dollarAllowed, data->iterDepth+1); if (data->context->errStat.status) return GSL_NAN; // Check that integrand is a number if (output->objType!=PPLOBJ_NUM) { strcpy(data->context->errStat.errBuff, "This operand is not a number across the range where calculus is being attempted."); ppl_tbAdd(data->context,data->expr->srcLineN,data->expr->srcId,data->expr->srcFname,0,ERR_TYPE,0,data->expr->ascii,data->integrate?"integrand":"differentiated expression"); ppl_garbageObject(&data->context->stack[--data->context->stackPtr]); // trash and pop output from stack return GSL_NAN; } // Check that integrand is dimensionally consistent over integration range if (data->isFirst) { memcpy(&data->first, output, sizeof(pplObj)); data->isFirst = 0; } else { if (!ppl_unitsDimEqual(&data->first,output)) { strcpy(data->context->errStat.errBuff, "This operand does not have consistent units across the range where calculus is being attempted."); ppl_tbAdd(data->context,data->expr->srcLineN,data->expr->srcId,data->expr->srcFname,0,ERR_UNIT,0,data->expr->ascii,data->integrate?"integrand":"differentiated expression"); ppl_garbageObject(&data->context->stack[--data->context->stackPtr]); // trash and pop output from stack return GSL_NAN; } } r = output->real; i = output->imag; ppl_garbageObject(&data->context->stack[--data->context->stackPtr]); // trash and pop output from stack // Integrand was complex, but complex arithmetic is turned off if ((!ppl_dblEqual(output->imag, 0)) && (data->context->set->term_current.ComplexNumbers == SW_ONOFF_OFF)) return GSL_NAN; if (data->testingReal) return r; else return i; } void ppl_expIntegrate(ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *expr, int exprPos, char *dummy, pplObj *min, pplObj *max, pplObj *out, int dollarAllowed, int iterDepth) { calculusComm commlink; pplObj *dummyVar; pplObj dummyTemp; gsl_integration_workspace *ws; gsl_function fn; pplExpr *expr2; int explen; double resultReal=0, resultImag=0, error; if (!ppl_unitsDimEqual(min,max)) { strcpy(c->errStat.errBuff, "The minimum and maximum limits of this integration operation are not dimensionally compatible."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_UNIT,inExprCharPos,inExpr->ascii,"int_d?() function"); return; } if (min->flagComplex || max->flagComplex) { strcpy(c->errStat.errBuff, "The minimum and maximum limits of this integration operation must be real numbers; supplied values are complex."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,inExprCharPos,inExpr->ascii,"int_d?() function"); return; } { int errPos=-1, errType=-1; ppl_expCompile(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,expr,&explen,dollarAllowed,1,1,&expr2,&errPos,&errType,c->errStat.errBuff); if (errPos>=0) { pplExpr_free(expr2); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,errType,errPos+exprPos,inExpr->ascii,"int_d?() function"); return; } if (explenerrStat.errBuff, "Unexpected trailing matter at the end of integrand."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_SYNTAX,explen+exprPos,inExpr->ascii,"int_d?() function"); pplExpr_free(expr2); return; } } commlink.context = c; commlink.integrate = 1; commlink.expr = expr2; commlink.isFirst = 1; commlink.testingReal = 1; commlink.varyingReal = 1; commlink.dollarAllowed = dollarAllowed; commlink.iterDepth = iterDepth; pplObjNum(&commlink.first,0,0,0); ppl_contextGetVarPointer(c, dummy, &dummyVar, &dummyTemp); dummyVar->objType = min->objType; dummyVar->real = min->real; dummyVar->imag = min->imag; dummyVar->flagComplex = min->flagComplex; ppl_unitsDimCpy(dummyVar, min); // Get units of dummyVar right commlink.dummy = dummyVar; commlink.dummyReal = dummyVar->real; commlink.dummyImag = dummyVar->imag; ws = gsl_integration_workspace_alloc(1000); fn.function = &ppl_expEvalCalculusSlave; fn.params = &commlink; gsl_integration_qags (&fn, min->real, max->real, 0, 1e-7, 1000, ws, &resultReal, &error); if ((!c->errStat.status) && (c->set->term_current.ComplexNumbers == SW_ONOFF_ON)) { commlink.testingReal = 0; gsl_integration_qags (&fn, min->real, max->real, 0, 1e-7, 1000, ws, &resultImag, &error); } gsl_integration_workspace_free(ws); pplExpr_free(expr2); ppl_contextRestoreVarPointer(c, dummy, &dummyTemp); // Restore old value of the dummy variable we've been using if (!c->errStat.status) { int status=0, errType=-1; ppl_uaMul( c, &commlink.first , min , out , &status, &errType, c->errStat.errBuff ); // Get units of output right if (status) { ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,errType,inExprCharPos,inExpr->ascii,"int_d?() function"); return; } out->real = resultReal; out->imag = resultImag; out->flagComplex = !ppl_dblEqual(resultImag, 0); if (!out->flagComplex) out->imag=0.0; // Enforce that real numbers have positive zero imaginary components if ((!gsl_finite(out->real)) || (!gsl_finite(out->imag)) || ((out->flagComplex) && (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(c->errStat.errBuff, "Integral does not evaluate to a finite value."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,exprPos,inExpr->ascii,"int_d?() function"); return; } else { out->real = GSL_NAN; out->imag = 0; out->flagComplex=0; } } } else { strcpy(c->errStat.errBuff, ""); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_GENERIC,inExprCharPos,inExpr->ascii,"int_d?() function"); } return; } void ppl_expDifferentiate(ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *expr, int exprPos, char *dummy, pplObj *point, pplObj *step, pplObj *out, int dollarAllowed, int iterDepth) { calculusComm commlink; pplObj *dummyVar; pplObj dummyTemp; gsl_function fn; pplExpr *expr2; int explen; double resultReal=0, resultImag=0, dIdI, dRdI; double resultReal_error, resultImag_error, dIdI_error, dRdI_error; if (!ppl_unitsDimEqual(point, step)) { strcpy(c->errStat.errBuff, "The arguments x and step to this differentiation operation are not dimensionally compatible."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,inExprCharPos,inExpr->ascii,"diff_d?() function"); return; } if (step->flagComplex) { strcpy(c->errStat.errBuff, "The argument 'step' to this differentiation operation must be a real number; supplied value is complex."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,inExprCharPos,inExpr->ascii,"diff_d?() function"); return; } { int errPos=-1, errType=-1; ppl_expCompile(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,expr,&explen,dollarAllowed,1,1,&expr2,&errPos,&errType,c->errStat.errBuff); if (errPos>=0) { pplExpr_free(expr2); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,errType,errPos+exprPos,inExpr->ascii,"diff_d?() function"); return; } if (explenerrStat.errBuff, "Unexpected trailing matter at the end of differentiated expression."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_SYNTAX,explen,inExpr->ascii,"diff_d?() function"); pplExpr_free(expr2); return; } } commlink.context = c; commlink.integrate = 0; commlink.expr = expr2; commlink.isFirst = 1; commlink.testingReal = 1; commlink.varyingReal = 1; commlink.dollarAllowed = dollarAllowed; commlink.iterDepth = iterDepth; pplObjNum(&commlink.first,0,0,0); ppl_contextGetVarPointer(c, dummy, &dummyVar, &dummyTemp); dummyVar->objType = point->objType; dummyVar->real = point->real; dummyVar->imag = point->imag; dummyVar->flagComplex = point->flagComplex; ppl_unitsDimCpy(dummyVar, point); // Get units of dummyVar right commlink.dummy = dummyVar; commlink.dummyReal = dummyVar->real; commlink.dummyImag = dummyVar->imag; fn.function = &ppl_expEvalCalculusSlave; fn.params = &commlink; gsl_deriv_central(&fn, point->real, step->real, &resultReal, &resultReal_error); pplExpr_free(expr2); if ((!c->errStat.status) && (c->set->term_current.ComplexNumbers == SW_ONOFF_ON)) { commlink.testingReal = 0; gsl_deriv_central(&fn, point->real, step->real, &resultImag, &resultImag_error); commlink.varyingReal = 0; gsl_deriv_central(&fn, point->imag, step->real, &dIdI , &dIdI_error); commlink.testingReal = 1; gsl_deriv_central(&fn, point->imag, step->real, &dRdI , &dRdI_error); if ((!ppl_dblApprox(resultReal, dIdI, 2*(resultReal_error+dIdI_error))) || (!ppl_dblApprox(resultImag, -dRdI, 2*(resultImag_error+dRdI_error)))) { sprintf(c->errStat.errBuff, "The Cauchy-Riemann equations are not satisfied at this point in the complex plane. It does not therefore appear possible to perform complex differentiation. In the notation f(x+iy)=u+iv, the offending derivatives were: du/dx=%e, dv/dy=%e, du/dy=%e and dv/dx=%e.", resultReal, dIdI, dRdI, resultImag); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,exprPos,inExpr->ascii,"diff_d?() function"); return; } } ppl_contextRestoreVarPointer(c, dummy, &dummyTemp); // Restore old value of the dummy variable we've been using if (!c->errStat.status) { int status=0, errType=-1; point->real = 1.0; point->imag = 0.0; point->flagComplex = 0; ppl_uaDiv( c , &commlink.first , point , out , &status, &errType, c->errStat.errBuff ); // Get units of output right if (status) { ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,errType,inExprCharPos,inExpr->ascii,"diff_d?() function"); return; } out->real = resultReal; out->imag = resultImag; out->flagComplex = !ppl_dblEqual(resultImag, 0); if (!out->flagComplex) out->imag=0.0; // Enforce that real numbers have positive zero imaginary components } if ((!gsl_finite(out->real)) || (!gsl_finite(out->imag)) || ((out->flagComplex) && (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(c->errStat.errBuff, "Differentiated expression does not evaluate to a finite value."); ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,ERR_NUMERICAL,exprPos,inExpr->ascii,"diff_d?() function"); return; } else { out->real = GSL_NAN; out->imag = 0; out->flagComplex=0; } } return; } pyxplot-0.9.2/src/expressions/traceback.c0000664000175000017500000001472512026340554017071 0ustar dcf21dcf21// traceback.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: traceback.c 1303 2012-09-09 21:04:51Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include "expressions/traceback_fns.h" #include "stringTools/strConstants.h" #include "userspace/context.h" void ppl_tbClear(ppl_context *c) { int i; for (i=c->errStat.tracebackDepth-1 ; i>=0 ; i--) { traceback *t = &c->errStat.tbLevel[i]; if (t->linetext!=NULL) free(t->linetext); } c->errStat.status = c->errStat.tracebackDepth = 0; c->errStat.errType = -1; if (c->errStat.errPosCmd !=-1) c->errStat.oldErrPosCmd = c->errStat.errPosCmd; if (c->errStat.errPosExpr!=-1) c->errStat.oldErrPosExpr = c->errStat.errPosExpr; c->errStat.errPosCmd = c->errStat.errPosExpr = -1; c->errStat.errBuff[0] = '\0'; c->errStat.sourceIdExpr = c->errStat.sourceIdCmd = -1; return; } void ppl_tbAdd(ppl_context *c, int srcLineN, long srcId, char *srcFname, int cmdOrExpr, int errType, int errPos, char *linetext, char *context) { int i = c->errStat.tracebackDepth; if ((!cmdOrExpr) || (i==0)) { traceback *t = &c->errStat.tbLevel[i]; if ((i<0)||(i>=TB_MAXLEVEL)) return; c->errStat.tracebackDepth++; t->errPos = errPos; t->errLine = srcLineN; t->sourceId = srcId; strncpy(t->source, srcFname, FNAME_LENGTH); t->amErrMsgExpr = t->amErrMsgCmd = 0; t->source[FNAME_LENGTH-1]='\0'; if (context==NULL) { t->context[0]='\0'; } else { strncpy(t->context, context, FNAME_LENGTH); t->context[FNAME_LENGTH-1] = '\0'; } if (linetext==NULL) { t->linetext=NULL; } else { t->linetext = malloc(strlen(linetext)+1); if (t->linetext!=NULL) strcpy(t->linetext,linetext); } c->errStat.status = 1; if (c->errStat.errType < 0) c->errStat.errType = errType; if ((!cmdOrExpr)&&(c->errStat.sourceIdExpr<0)&&(strlen(c->errStat.errBuff)>0)) { t->amErrMsgExpr = 1; c->errStat.sourceIdExpr = srcId; c->errStat.errPosExpr = errPos; strcpy(c->errStat.errMsgExpr, c->errStat.errBuff); } if ((cmdOrExpr)&&(c->errStat.sourceIdCmd<0)) t->amErrMsgCmd = 1; } if ((cmdOrExpr)&&(c->errStat.sourceIdCmd<0)&&(strlen(c->errStat.errBuff)>0)) { c->errStat.sourceIdCmd = srcId; c->errStat.errPosCmd = errPos; strcpy(c->errStat.errMsgCmd, c->errStat.errBuff); } return; } void ppl_tbWrite(ppl_context *c) { int i=0,j,k; char *out = c->errcontext.tempErrStr; int outLen = LSTR_LENGTH; int h1=-1, h2=-1; out[i] = out[outLen-1] = '\0'; outLen--; if (!c->errStat.status) return; // No error! snprintf(out+i, outLen-i, "\n"); i+=strlen(out+i); switch (c->errStat.errType) { case ERR_INTERNAL : snprintf(out+i, outLen-i, "Internal error:"); break; case ERR_SYNTAX : snprintf(out+i, outLen-i, "Syntax error:"); break; case ERR_NUMERICAL : snprintf(out+i, outLen-i, "Numerical error:"); break; case ERR_FILE : snprintf(out+i, outLen-i, "File error:"); break; case ERR_RANGE : snprintf(out+i, outLen-i, "Range error:"); break; case ERR_UNIT : snprintf(out+i, outLen-i, "Unit error:"); break; case ERR_OVERFLOW : snprintf(out+i, outLen-i, "Overflow error:"); break; case ERR_NAMESPACE: snprintf(out+i, outLen-i, "Namespace error:"); break; case ERR_TYPE : snprintf(out+i, outLen-i, "Type error:"); break; case ERR_INTERRUPT: snprintf(out+i, outLen-i, "Interrupt error:"); break; case ERR_DICTKEY : snprintf(out+i, outLen-i, "Key error:"); break; case ERR_ASSERT : snprintf(out+i, outLen-i, "Assertion error:"); break; case ERR_MEMORY : case ERR_GENERIC : default : snprintf(out+i, outLen-i, "Error:"); break; } i+=strlen(out+i); snprintf(out+i, outLen-i, "\n"); ppl_error(&c->errcontext, ERR_PREFORMED, -1, -1, NULL); for (j=c->errStat.tracebackDepth-1 ; j>=0 ; j--) { i=0; h1=-1; traceback *t = &c->errStat.tbLevel[j]; snprintf(out+i, outLen-i, "In %s", (t->source[0]=='\0')?"keyboard entry":t->source); i+=strlen(out+i); if (t->errLine>=0) { snprintf(out+i, outLen-i, ", line %d", t->errLine); i+=strlen(out+i); } if (t->errPos >=0) { snprintf(out+i, outLen-i, ", position %d below", t->errPos); i+=strlen(out+i); } if (t->context[0]!='\0') { snprintf(out+i, outLen-i, " (%s)", t->context); i+=strlen(out+i); } if ((t->linetext!=NULL) && (j>0)) { snprintf(out+i, outLen-i, ":\n %s", t->linetext); h1 = i+3+t->errPos; } else snprintf(out+i, outLen-i, (j==0)?":":"."); ppl_error(&c->errcontext, ERR_PREFORMED, h1, -1, NULL); } i=1; strcpy(out,"\n"); if ((c->errStat.tracebackDepth>0) && (c->errStat.tbLevel[0].linetext!=NULL)) { const int lp = c->errStat.errPosCmd; const int lp2 = c->errStat.errPosExpr; traceback *t = &c->errStat.tbLevel[0]; if ((t->sourceId == c->errStat.sourceIdCmd) && (lp>=0)) { snprintf(out+i, outLen-i, "%s\n", c->errStat.errMsgCmd); i+=strlen(out+i); for (k=0;((klinetext); i+=strlen(out+i); if ((t->sourceId == c->errStat.sourceIdExpr) && (lp2>=0)) { for (k=0;((kerrStat.errMsgExpr); i+=strlen(out+i); } else { h2 = -1; } } ppl_error(&c->errcontext, ERR_PREFORMED, h1, h2, NULL); return; } pyxplot-0.9.2/src/expressions/expEvalSlice.c0000664000175000017500000003143312026340554017531 0ustar dcf21dcf21// expEvalSlice.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalSlice.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "expressions/expEvalSlice.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "pplConstants.h" #define STACK_POP \ { \ context->stackPtr--; \ ppl_garbageObject(&context->stack[context->stackPtr]); \ if (context->stack[context->stackPtr].refCount != 0) { *status=1; *errType=ERR_INTERNAL; strcpy(errText,"Stack forward reference detected."); goto fail; } \ } \ void ppl_sliceItem (ppl_context *context, int getPtr, int *status, int *errType, char *errText) { const int nArgs=1; pplObj *out = &context->stack[context->stackPtr-1-nArgs]; pplObj *args = context->stack+context->stackPtr-nArgs; pplObj called; int i; int t = out->objType; if (context->stackPtrrefCount = 1; if ((t==PPLOBJ_DICT) || (t==PPLOBJ_MOD) || (t==PPLOBJ_USER)) { dict *din = (dict *)called.auxil; char *key; pplObj *obj; if (args->objType!=PPLOBJ_STR) { *errType=ERR_TYPE; sprintf(errText,"Dictionary keys must be strings; supplied key has type <%s>.",pplObjTypeNames[args->objType]); goto fail; } key = (char *)args[0].auxil; if (!ppl_dictContains(din,key)) { if (getPtr && (!din->immutable)) { pplObj v; v.refCount=1; pplObjNull(&v,1); ppl_dictAppendCpy(din, key, &v, sizeof(pplObj)); } else { *status=1; *errType=ERR_DICTKEY; sprintf(errText,"Undefined dictionary key '%s'.", key); goto fail; } } obj = (pplObj *)ppl_dictLookup(din,key); pplObjCpy(out, obj, 1, 0, 1); out->immutable = out->immutable || din->immutable; goto cleanup; } if (args->objType!=PPLOBJ_NUM) { *errType=ERR_TYPE; sprintf(errText,"Item numbers when slicing must be numerical values; supplied index has type <%s>.",pplObjTypeNames[args->objType]); goto fail; } if (!args->dimensionless) { *errType=ERR_NUMERICAL; sprintf(errText,"Item numbers when slicing must be dimensionless numbers; supplied index has units of <%s>.", ppl_printUnit(context, args, NULL, NULL, 0, 1, 0) ); goto fail; } if (args->flagComplex) { *errType=ERR_NUMERICAL; sprintf(errText,"Item numbers when slicing must be real numbers; supplied index is complex."); goto fail; } if ( (!gsl_finite(args->real)) || (args->realreal>INT_MAX) ) { *errType=ERR_NUMERICAL; sprintf(errText,"Item numbers when slicing must be in the range %d to %d.", INT_MIN, INT_MAX); goto fail; } switch (t) { case PPLOBJ_STR: { const char *in = (char *)called.auxil; const int inl = strlen(in); char *outstr; int p = args[0].real; if (p<0) p+=inl; if ((p<0)||(p>=inl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"String index out of range."); goto fail; } if (getPtr) { *status=1; *errType=ERR_TYPE; sprintf(errText,"Cannot assign to a character in a string."); goto fail; } if ((outstr = (char *)malloc(2))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); goto fail; } outstr[0] = in[p]; outstr[1] = '\0'; pplObjStr(out, 0, 1, outstr); break; } case PPLOBJ_LIST: { list *lin = (list *)called.auxil; const int linl = lin->length; int p = args[0].real; pplObj *obj; if (p<0) p+=linl; if (getPtr && (p==linl) && (!lin->immutable)) { pplObj v; v.refCount=1; pplObjNull(&v,1); ppl_listAppendCpy(lin, &v, sizeof(pplObj)); } else { if ((p<0)||(p>=linl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"List index out of range."); goto fail; } } obj = (pplObj *)ppl_listGetItem(lin,p); pplObjCpy(out, obj, 1, 0, 1); out->immutable = out->immutable || lin->immutable; break; } case PPLOBJ_VEC: { gsl_vector *vin = ((pplVector *)called.auxil)->v; const int vinl = vin->size; int p = args[0].real; double *obj; if (p<0) p+=vinl; if ((p<0)||(p>=vinl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"Vector index out of range."); goto fail; } obj = gsl_vector_ptr(vin, p); pplObjNum(out, 0, *obj, 0); ppl_unitsDimCpy(out,&called); if ((out->self_lval = called.self_lval)!=NULL) { __sync_add_and_fetch(&out->self_lval->refCount,1); } out->self_dval = obj; out->immutable = out->immutable || called.immutable; break; } case PPLOBJ_MAT: { pplMatrix *mob = (pplMatrix *)called.auxil; gsl_matrix *min = mob->m; const int minl = mob->sliceNext ? min->size2 : min->size1; int p = args[0].real; pplVector *vo; if (p<0) p+=minl; if ((p<0)||(p>=minl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"Matrix index out of range."); goto fail; } vo = (pplVector *)malloc(sizeof(pplVector)); if (vo==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); goto fail; } vo->refCount = 1; vo->raw = NULL; vo->rawm = mob->raw; __sync_add_and_fetch(&mob->raw->refCount,1); if (!mob->sliceNext) vo->view = gsl_matrix_column(min, p); else vo->view = gsl_matrix_row (min, p); vo->v = &vo->view.vector; out->objType = PPLOBJ_ZOM; out->refCount=1; out->auxil = (void*)vo; out->auxilMalloced = 1; out->auxilLen = sizeof(pplVector); out->objPrototype = &pplObjPrototypes[PPLOBJ_VEC]; if ((out->self_lval = called.self_lval)!=NULL) { __sync_add_and_fetch(&out->self_lval->refCount,1); } out->self_dval = NULL; out->self_this = NULL; out->immutable = 0; ppl_unitsDimCpy(out,&called); out->objType = PPLOBJ_VEC; out->immutable = called.immutable; break; } default: *status=1; *errType=ERR_TYPE; sprintf(errText,"Attempt to slice an object of type <%s>, which cannot be sliced.",pplObjTypeNames[t]); goto fail; } cleanup: for (i=0; istack[context->stackPtr-1-nArgs]; pplObj called; int i; int t = out->objType; if (context->stackPtrrefCount = 1; switch (t) { case PPLOBJ_STR: { const char *in = (char *)called.auxil; const int inl = strlen(in); int outlen; char *outstr; if (!minset) min =0; else if (min<0) min+=inl; if (!maxset) max =inl; else if (max<0) max+=inl; if ((min<0)||(min>inl)||(max<0)||(max>inl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"String index out of range."); goto fail; } outlen = max-min; if (outlen<0) outlen=0; if ((outstr = (char *)malloc(outlen+1))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); goto fail; } strncpy(outstr,in+min,outlen); outstr[outlen]='\0'; pplObjStr(out, 0, 1, outstr); break; } case PPLOBJ_LIST: { list *lin = (list *)called.auxil; list *lout; const int inl = lin->length; int i; listIterator *li; pplObj obj, *objptr; if (!minset) min =0; else if (min<0) min+=inl; if (!maxset) max =inl; else if (max<0) max+=inl; if ((min<0)||(min>inl)||(max<0)||(max>inl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"List index out of range."); goto fail; } if (pplObjList(out,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); goto fail; } lout = (list *)out->auxil; obj.refCount=1; li = ppl_listIterateInit(lin); for (i=0; ((objptr=(pplObj*)ppl_listIterate(&li))!=NULL); i++) if ((i>=min)&&(iv; const int vinl = vecin->size; pplVector *vo; if (!minset) min =0; else if (min<0) min+=vinl; if (!maxset) max =vinl; else if (max<0) max+=vinl; if ((min<0)||(min>vinl)||(max<0)||(max>vinl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"Vector index out of range."); goto fail; } if (maxrefCount = 1; if ((vo->raw = vob->raw )!=NULL) { __sync_add_and_fetch(&vob->raw ->refCount,1); } if ((vo->rawm = vob->rawm)!=NULL) { __sync_add_and_fetch(&vob->rawm->refCount,1); } vo->view = gsl_vector_subvector(vecin, min, max-min); vo->v = &vo->view.vector; out->objType = PPLOBJ_ZOM; out->refCount=1; out->auxil = (void*)vo; out->auxilMalloced = 1; out->auxilLen = sizeof(pplVector); out->objPrototype = &pplObjPrototypes[PPLOBJ_VEC]; out->self_lval = NULL; out->self_dval = NULL; out->self_this = NULL; out->immutable = 0; ppl_unitsDimCpy(out,&called); out->objType = PPLOBJ_VEC; out->immutable = called.immutable; break; } case PPLOBJ_MAT: { pplMatrix *mob = (pplMatrix *)called.auxil; gsl_matrix *matin = mob->m; const int minl = mob->sliceNext ? matin->size2 : matin->size1; pplMatrix *mo; if (!minset) min =0; else if (min<0) min+=minl; if (!maxset) max =minl; else if (max<0) max+=minl; if ((min<0)||(min>minl)||(max<0)||(max>minl)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"Matrix index out of range."); goto fail; } if (maxrefCount = 1; mo->raw = mob->raw; __sync_add_and_fetch(&mob->raw->refCount,1); if (mob->sliceNext) mo->view = gsl_matrix_submatrix(matin, min, 0 , max-min , matin->size2); else mo->view = gsl_matrix_submatrix(matin, 0 , min, matin->size1 , max-min ); mo->sliceNext = !mob->sliceNext; mo->m = &mo->view.matrix; out->objType = PPLOBJ_ZOM; out->refCount=1; out->auxil = (void*)mo; out->auxilMalloced = 1; out->auxilLen = sizeof(pplMatrix); out->objPrototype = &pplObjPrototypes[PPLOBJ_MAT]; out->self_lval = NULL; out->self_dval = NULL; out->self_this = NULL; out->immutable = 0; ppl_unitsDimCpy(out,&called); out->objType = PPLOBJ_MAT; out->immutable = called.immutable; break; } default: *status=1; *errType=ERR_TYPE; sprintf(errText,"Attempt to slice an object of type <%s>, which cannot be sliced.",pplObjTypeNames[t]); goto fail; } cleanup: for (i=0; i // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fnCall.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _FNCALL_C 1 #include #include #include #include #include #include #include #include "commands/fft.h" #include "commands/histogram.h" #include "commands/interpolate.h" #include "coreUtils/dict.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "expressions/expEval.h" #include "expressions/expEvalCalculus.h" #include "expressions/fnCall.h" #include "expressions/traceback_fns.h" #include "settings/colors.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "pplConstants.h" #define TBADD(et) ppl_tbAdd(context,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,et,inExprCharPos,inExpr->ascii,"") #define TBADD2(et,place) ppl_tbAdd(context,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,et,inExprCharPos,inExpr->ascii,place) #define STACK_POP \ { \ context->stackPtr--; \ ppl_garbageObject(&context->stack[context->stackPtr]); \ if (context->stack[context->stackPtr].refCount != 0) { strcpy(context->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL); goto cleanup; } \ } void ppl_fnCall(ppl_context *context, pplExpr *inExpr, int inExprCharPos, int nArgs, int dollarAllowed, int iterDepth) { pplObj *out = &context->stack[context->stackPtr-1-nArgs]; pplObj *args = context->stack+context->stackPtr-nArgs; pplObj called; pplFunc *fn; int i; int t = out->objType; if (context->stackPtrerrStat.errBuff,"Attempt to call function with few items on the stack."); TBADD(ERR_INTERNAL); return; } memcpy(&called, out, sizeof(pplObj)); pplObjNum(out, 0, 0, 0); // Overwrite function object on stack, but don't garbage collect it yet out->refCount = 1; out->self_this = called.self_this; // Attempt to call a module to generate a class instance? if ((t == PPLOBJ_MOD) || (t == PPLOBJ_USER)) { if (nArgs!=0) { sprintf(context->errStat.errBuff,"Instantiation takes zero arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); goto cleanup; } pplObjUser(out,0,1,&called); goto cleanup; } // Attempt to call a type object as a constructor? else if (t == PPLOBJ_TYPE) { int id = ((pplType *)(out->auxil))->id; switch (id) { case PPLOBJ_NUM: if (nArgs==0) { pplObjNum(out,0,0,0); } else if (nArgs==1) { CAST_TO_NUM(&args[0]); pplObjCpy(out,&args[0],0,0,1); } else { sprintf(context->errStat.errBuff,"The numeric object constructor takes either zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_STR: if (nArgs==0) { pplObjStr(out,0,0,""); } else if (nArgs==1) { if (args[0].objType==PPLOBJ_STR) pplObjCpy(out,&args[0],0,0,1); else { char *outstr=(char*)malloc(65536); pplObjPrint(context,&args[0],NULL,outstr,65536,0,0); pplObjStr(out,0,1,outstr); } } else { sprintf(context->errStat.errBuff,"The string object constructor takes either zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_BOOL: if (nArgs==0) { pplObjBool(out,0,1); } else if (nArgs==1) { CAST_TO_BOOL(&args[0]); pplObjCpy(out,&args[0],0,0,1); } else { sprintf(context->errStat.errBuff,"The boolean object constructor takes either zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_DATE: if (nArgs==0) { pplObjDate(out,0,(double)time(NULL)); } else if (nArgs==1) { if (args[0].objType==PPLOBJ_DATE) pplObjDate(out,0,args[0].real); else { sprintf(context->errStat.errBuff,"The first argument to the date object constructor should be a date; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The date object constructor takes zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_COL: if (nArgs==0) { pplObjColor(out,0,SW_COLSPACE_RGB,0,0,0,0); } else if (nArgs==1) { if ((args[0].objType==PPLOBJ_COL)||(args[0].objType==PPLOBJ_NUM)) { unsigned char d1,d2; int i1,i2; pplObjColor(out,0,SW_COLSPACE_RGB,0,0,0,0); ppl_colorFromObj(context,&args[0],&i1,&i2,NULL,&out->exponent[8],&out->exponent[9],&out->exponent[10],&out->exponent[11],&d1,&d2); out->exponent[2]=i1; out->exponent[0]=i2; } else { sprintf(context->errStat.errBuff,"The first argument to the color object constructor should be a color; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The color object constructor takes zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_DICT: if (nArgs==0) { pplObjDict(out,0,1,NULL); } else if (nArgs==1) { if (args[0].objType==PPLOBJ_DICT) pplObjDeepCpy(out,&args[0],0,0,1); else { sprintf(context->errStat.errBuff,"The first argument to the dictionary object constructor should be a dictionary; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The dictionary object constructor takes zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_MOD: case PPLOBJ_USER: if (nArgs==0) { pplObjModule(out,0,1,0); } else if (nArgs==1) { if ((args[0].objType==PPLOBJ_MOD)||(args[0].objType==PPLOBJ_USER)||(args[0].objType==PPLOBJ_DICT)) { pplObjDeepCpy(out,&args[0],0,0,1); out->objType=PPLOBJ_MOD; } else { sprintf(context->errStat.errBuff,"The first argument to the module/instance object constructor should be a module or instance; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The module/instance object constructor takes zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_FILE: if (nArgs==0) { pplObjFile(out,0,1,tmpfile(),0); } else if (nArgs==1) { if (args[0].objType==PPLOBJ_FILE) pplObjCpy(out,&args[0],0,0,1); else { sprintf(context->errStat.errBuff,"The first argument to the file object constructor should be a file object; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The file object constructor takes zero or one arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_TYPE: sprintf(context->errStat.errBuff,"Creation of new data type objects is not permitted."); TBADD(ERR_TYPE); goto cleanup; case PPLOBJ_FUNC: sprintf(context->errStat.errBuff,"New function objects must be created with the syntax f(x)=... or subroutine f(x) { ... }."); TBADD(ERR_TYPE); goto cleanup; case PPLOBJ_EXC: if (nArgs==1) { if (args[0].objType==PPLOBJ_STR) { pplObjCpy(out,&args[0],0,0,1); pplObjException(out,0,1,(char*)out->auxil,ERR_GENERIC); } else if (args[0].objType==PPLOBJ_EXC) { pplObjCpy(out,&args[0],0,0,1); } else { sprintf(context->errStat.errBuff,"The first argument to the exception object constructor should be a string; an object of type <%s> was supplied.",pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); } } else { sprintf(context->errStat.errBuff,"The exception object constructor takes one argument; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_NULL: if (nArgs==0) { pplObjNull(out,0); } else { sprintf(context->errStat.errBuff,"The null object constructor takes zero arguments; %d supplied.",nArgs); TBADD(ERR_TYPE); } goto cleanup; case PPLOBJ_LIST: if ((nArgs==1)&&(args[0].objType==PPLOBJ_LIST)) { pplObjDeepCpy(out, &args[0], 0, 0, 1); goto cleanup; } if (pplObjList(out,0,1,NULL)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } if (nArgs<1) goto cleanup; if ((nArgs==1)&&(args[0].objType==PPLOBJ_VEC)) { int i; gsl_vector *vec = ((pplVector *)args[0].auxil)->v; const int l = vec->size; pplObj v; list *lo = (list *)out->auxil; v.refCount = 1; pplObjNum(&v,1,0,0); ppl_unitsDimCpy(&v, &args[0]); for (i=0; iauxil; v.refCount = 1; pplObjCpy(&v,&args[i],0,1,1); ppl_listAppendCpy(lo, &v, sizeof(pplObj)); } } goto cleanup; case PPLOBJ_VEC: if (nArgs<1) { pplObjVector(out,0,1,1); gsl_vector_set( ((pplVector*)out->auxil)->v,0,0); goto cleanup; } if (nArgs==1) { if (args[0].objType==PPLOBJ_VEC) { pplObjDeepCpy(out, &args[0], 0, 0, 1); goto cleanup; } else if (args[0].objType==PPLOBJ_NUM) { gsl_vector *v; long i,len; if (!args[0].dimensionless) { sprintf(context->errStat.errBuff,"Specified length of vector should be dimensionless; supplied length has units of <%s>.", ppl_printUnit(context, &args[0], NULL, NULL, 0, 1, 0)); TBADD(ERR_TYPE); goto cleanup; } if (args[0].flagComplex) { sprintf(context->errStat.errBuff,"Specified length of vector should be real; supplied length is complex number."); TBADD(ERR_NUMERICAL); goto cleanup; } if ((args[0].real<1)||(args[0].real>INT_MAX)) { sprintf(context->errStat.errBuff,"Specified length of vector should be in the range 1errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } v = ((pplVector *)out->auxil)->v; for (i=0; ilength; gsl_vector *v; if (len==0) { sprintf(context->errStat.errBuff,"Cannot create a vector of length zero."); TBADD(ERR_RANGE); goto cleanup; } if (pplObjVector(out,0,1,len)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } v = ((pplVector *)out->auxil)->v; if (len>0) { pplObj *item = (pplObj*)ppl_listIterate(&li); if (item->objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Vectors can only hold real numeric values. Attempt to add a complex number."); TBADD(ERR_TYPE); goto cleanup; } ppl_unitsDimCpy(out,item); gsl_vector_set(v,i,item->real); } for (i=1; iobjType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Vectors can only hold real numeric values. Attempt to add a complex number."); TBADD(ERR_TYPE); goto cleanup; } if (!ppl_unitsDimEqual(item, out)) { if (out->dimensionless) { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", i+1, ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); } else if (item->dimensionless) { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", i+1, ppl_printUnit(context, out, NULL, NULL, 0, 1, 0) ); } else { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", i+1, ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); } TBADD(ERR_UNIT); goto cleanup; } gsl_vector_set(v,i,item->real); } goto cleanup; } } // List is to made up from arguments supplied to constructor { long i=0; gsl_vector *v; if (pplObjVector(out,0,1,nArgs)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } v = ((pplVector *)out->auxil)->v; if (nArgs>0) { pplObj *item = &args[0]; if (item->objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Vectors can only hold real numeric values. Attempt to add a complex number."); TBADD(ERR_TYPE); goto cleanup; } ppl_unitsDimCpy(out,item); gsl_vector_set(v,i,item->real); } for (i=1; iobjType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Vectors can only hold real numeric values. Attempt to add a complex number."); TBADD(ERR_TYPE); goto cleanup; } if (!ppl_unitsDimEqual(item, out)) { if (out->dimensionless) { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", i+1, ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); } else if (item->dimensionless) { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", i+1, ppl_printUnit(context, out, NULL, NULL, 0, 1, 0) ); } else { sprintf(context->errStat.errBuff, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", i+1, ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); } TBADD(ERR_UNIT); goto cleanup; } gsl_vector_set(v,i,item->real); } goto cleanup; } case PPLOBJ_MAT: if (nArgs<1) { pplObjMatrix(out,0,1,1,1); gsl_matrix_set( ((pplMatrix*)out->auxil)->m,0,0,0); goto cleanup; } else if (args[0].objType==PPLOBJ_MAT) { if (nArgs!=1) { sprintf(context->errStat.errBuff,"When initialising a matrix from another matrix, only one argument should be supplied (the source matrix). %d have been provided.",nArgs); TBADD(ERR_TYPE); goto cleanup; } pplObjDeepCpy(out, &args[0], 0, 0, 1); goto cleanup; } else if (args[0].objType==PPLOBJ_NUM) { int s1,s2,i,j; gsl_matrix *m; if (nArgs!=2) { sprintf(context->errStat.errBuff,"When specifying the size of a matrix, two numerical arguments must be supplied. %d have been provided.",nArgs); TBADD(ERR_TYPE); goto cleanup; } if (args[1].objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"When specifying the size of a matrix, two numerical arguments must be supplied. Second argument has type <%s>.", pplObjTypeNames[args[1].objType]); TBADD(ERR_TYPE); goto cleanup; } if (!args[0].dimensionless) { sprintf(context->errStat.errBuff,"When specifying the size of a matrix, both numerical arguments must be dimensionless. First has units of <%s>.", ppl_printUnit(context, &args[0], NULL, NULL, 1, 1, 0) ); TBADD(ERR_TYPE); goto cleanup; } if (!args[1].dimensionless) { sprintf(context->errStat.errBuff,"When specifying the size of a matrix, both numerical arguments must be dimensionless. Second has units of <%s>.", ppl_printUnit(context, &args[1], NULL, NULL, 1, 1, 0) ); TBADD(ERR_TYPE); goto cleanup; } if ((args[0].flagComplex) || (args[1].flagComplex)) { sprintf(context->errStat.errBuff,"When specifying the size of a matrix, both arguments must be real numbers. Supplied arguments are complex."); TBADD(ERR_TYPE); goto cleanup; } s1 = args[0].real ; s2 = args[1].real; if ((s1<1)||(s1>INT_MAX)) { sprintf(context->errStat.errBuff,"Specified dimension of vector should be in the range 1INT_MAX)) { sprintf(context->errStat.errBuff,"Specified dimension of vector should be in the range 1errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } m = ((pplMatrix *)out->auxil)->m; for (i=0; iv->size; const long s2 = nArgs; gsl_matrix *m; if (pplObjMatrix(out,0,1,s1,s2)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } m = ((pplMatrix *)out->auxil)->m; ppl_unitsDimCpy(out,&args[0]); for (i=0; ierrStat.errBuff,"When initialising a matrix from a list of vectors, all arguments must be vectors. Supplied argument has type <%s>.", pplObjTypeNames[args[i].objType]); TBADD(ERR_TYPE); goto cleanup; } v = ((pplVector*)args[i].auxil)->v; if (v->size != s1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, the vectors must have consistent lengths. Supplied vector has length %ld whereas previous arguments have had a length %ld.",(long)v->size,s1); TBADD(ERR_RANGE); goto cleanup; } if (!ppl_unitsDimEqual(out, &args[i])) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, the vectors must all have the same dimensions. Supplied vectors have units of <%s> and <%s>.", ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, &args[i], NULL, NULL, 1, 1, 0) ); TBADD(ERR_UNIT); } for (j=0; jlength; pplObj *item; if (len==0) { sprintf(context->errStat.errBuff,"Cannot create a matrix of dimension zero."); TBADD(ERR_MEMORY); goto cleanup; } item = (pplObj*)listin->first->data; if (item->objType==PPLOBJ_NUM) { long i; const long s1 = len; const long s2 = nArgs; gsl_matrix *m; for (i=0; ierrStat.errBuff,"When initialising a matrix from a list of lists, all arguments must be lists. Supplied argument has type <%s>.", pplObjTypeNames[args[i].objType]); TBADD(ERR_TYPE); goto cleanup; } if (pplObjMatrix(out,0,1,s2,s1)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } m = ((pplMatrix *)out->auxil)->m; ppl_unitsDimCpy(out,item); for (i=0; ilength != s1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, the lists must have consistent lengths. Supplied list has length %ld whereas previous lists have had a length %ld.",(long)listin->length,s1); TBADD(ERR_RANGE); goto cleanup; } for (j=0; jobjType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, the elements must all be numerical values; supplied element has type <%s>.", pplObjTypeNames[item->objType]); TBADD(ERR_RANGE); goto cleanup; } if (!ppl_unitsDimEqual(out, item)) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, all of the elements must have the same dimensions. Supplied elements have units of <%s> and <%s>.", ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); TBADD(ERR_UNIT); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Matrices can only hold real numbers; supplied elements are complex."); TBADD(ERR_NUMERICAL); goto cleanup; } gsl_matrix_set(m, i, j, item->real ); } } goto cleanup; } else if (item->objType==PPLOBJ_VEC) { long i; const long s1 = ((pplVector*)item->auxil)->v->size; const long s2 = len; gsl_matrix *m; if (nArgs!=1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, only one argument should be supplied. %d arguments were supplied.",nArgs); TBADD(ERR_RANGE); goto cleanup; } if (pplObjMatrix(out,0,1,s1,s2)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } m = ((pplMatrix *)out->auxil)->m; ppl_unitsDimCpy(out,item); for (i=0; iobjType!=PPLOBJ_VEC) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, all arguments must be vectors. Supplied argument has type <%s>.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } v = ((pplVector*)item->auxil)->v; if (v->size != s1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, the vectors must have consistent lengths. Supplied vector has length %ld whereas previous arguments have had a length %ld.",(long)v->size,s1); TBADD(ERR_RANGE); goto cleanup; } if (!ppl_unitsDimEqual(out, item)) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of vectors, the vectors must all have the same dimensions. Supplied vectors have units of <%s> and <%s>.", ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, item, NULL, NULL, 1, 1, 0) ); TBADD(ERR_UNIT); goto cleanup; } for (j=0; jobjType==PPLOBJ_LIST) { long i; const long s1 = ((list*)item->auxil)->length; const long s2 = len; gsl_matrix *m; if (nArgs!=1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, only one argument should be supplied. %d arguments were supplied.",nArgs); TBADD(ERR_RANGE); goto cleanup; } if (s1==0) { sprintf(context->errStat.errBuff,"Cannot create a matrix of dimension zero."); TBADD(ERR_MEMORY); goto cleanup; } if (pplObjMatrix(out,0,1,s2,s1)==NULL) { sprintf(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } m = ((pplMatrix *)out->auxil)->m; ppl_unitsDimCpy(out,((pplObj*)((list*)item->auxil)->first->data)); for (i=0; iobjType!=PPLOBJ_LIST) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, all arguments must be lists. Supplied argument has type <%s>.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } list *listin2 = (list *)item->auxil; listIterator *li2 = ppl_listIterateInit(listin2); if (listin2->length != s1) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, the lists must have consistent lengths. Supplied list has length %ld whereas previous lists have had a length %ld.",(long)listin2->length,s1); TBADD(ERR_RANGE); goto cleanup; } for (j=0; jobjType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, the elements must all be numerical values; supplied element has type <%s>.", pplObjTypeNames[item2->objType]); TBADD(ERR_RANGE); goto cleanup; } if (!ppl_unitsDimEqual(out, item2)) { sprintf(context->errStat.errBuff,"When initialising a matrix from a list of lists, all of the elements must have the same dimensions. Supplied elements have units of <%s> and <%s>.", ppl_printUnit(context, out, NULL, NULL, 0, 1, 0), ppl_printUnit(context, item2, NULL, NULL, 1, 1, 0) ); TBADD(ERR_UNIT); goto cleanup; } if (item->flagComplex) { sprintf(context->errStat.errBuff,"Matrices can only hold real numbers; supplied elements are complex."); TBADD(ERR_NUMERICAL); goto cleanup; } gsl_matrix_set(m, i, j, item2->real ); } } goto cleanup; } else { sprintf(context->errStat.errBuff,"Cannot initialise a matrix from an object of type <%s>.", pplObjTypeNames[item->objType]); TBADD(ERR_TYPE); goto cleanup; } } else { sprintf(context->errStat.errBuff,"Cannot initialise a matrix from an object of type <%s>.", pplObjTypeNames[args[0].objType]); TBADD(ERR_TYPE); goto cleanup; } goto cleanup; } } // Otherwise object being called must be a function object if (t != PPLOBJ_FUNC) { sprintf(context->errStat.errBuff,"Object of type <%s> cannot be called as a function.",pplObjTypeNames[t]); TBADD(ERR_TYPE); goto cleanup; } fn = (pplFunc *)called.auxil; if (fn->functionType==PPL_FUNC_MAGIC) { if (fn->minArgs==1) // unit() { int end, errPos=-1; char *u = (char*)context->stack[context->stackPtr-1].auxil; if (nArgs != 1) { sprintf(context->errStat.errBuff,"The unit() function takes exactly one argument; %d supplied.",nArgs); TBADD(ERR_TYPE); goto cleanup; } ppl_unitsStringEvaluate(context, u, out, &end, &errPos, context->errStat.errBuff); if (errPos>=0) { TBADD(ERR_UNIT); goto cleanup; } if (end!=strlen(u)) { sprintf(context->errStat.errBuff,"Unexpected trailing matter after unit string."); TBADD(ERR_UNIT); goto cleanup; } } else if (fn->minArgs==2) // diff_d() { pplObj v, *step, *xpos; int k; for (k=inExprCharPos; ((inExpr->ascii[k]!='(')&&(inExpr->ascii[k]!='\0')); k++); if (inExpr->ascii[k]=='(') k++; for ( ; ((inExpr->ascii[k]>'\0')&&(inExpr->ascii[k]<=' ' )); k++); if (nArgs == 3) step = &v; else if (nArgs == 4) step = &args[3]; else { sprintf(context->errStat.errBuff,"The diff_d() function takes two or thee arguments; %d supplied.",nArgs-1); TBADD(ERR_TYPE); goto cleanup; } if (args[0].objType!=PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Dummy variable not passed to diff_d() as a string"); TBADD(ERR_INTERNAL); goto cleanup; } if (args[1].objType!=PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Differentiation expression not passed to diff_d() as a string"); TBADD(ERR_INTERNAL); goto cleanup; } if (args[2].objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"The diff_d() function requires a number as its second argument; supplied argument has type <%s>.",pplObjTypeNames[args[2].objType]); TBADD(ERR_TYPE); goto cleanup; } if ((nArgs==4)&&(args[3].objType!=PPLOBJ_NUM)) { sprintf(context->errStat.errBuff,"The diff_d() function requires a number as its third argument; supplied argument has type <%s>.",pplObjTypeNames[args[3].objType]); TBADD(ERR_TYPE); goto cleanup; } xpos = &args[2]; memcpy(&v,xpos,sizeof(pplObj)); v.imag=0; v.real = hypot(xpos->real,xpos->imag)*1e-6; v.flagComplex=0; if (v.realerrStat.status) { goto cleanup; } } else if (fn->minArgs==3) // int_d() { int k; for (k=inExprCharPos; ((inExpr->ascii[k]!='(')&&(inExpr->ascii[k]!='\0')); k++); if (inExpr->ascii[k]=='(') k++; for ( ; ((inExpr->ascii[k]>'\0')&&(inExpr->ascii[k]<=' ' )); k++); if (nArgs != 4) { sprintf(context->errStat.errBuff,"The int_d() function takes two or three arguments; %d supplied.",nArgs-1); TBADD(ERR_TYPE); goto cleanup; } if (args[0].objType!=PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Dummy variable not passed to int_d() as a string"); TBADD(ERR_INTERNAL); goto cleanup; } if (args[1].objType!=PPLOBJ_STR) { sprintf(context->errStat.errBuff,"Integration expression not passed to diff_d() as a string"); TBADD(ERR_INTERNAL); goto cleanup; } if (args[2].objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"The int_d() function requires a number as its second argument; supplied argument has type <%s>.",pplObjTypeNames[args[2].objType]); TBADD(ERR_TYPE); goto cleanup; } if (args[3].objType!=PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"The int_d() function requires a number as its third argument; supplied argument has type <%s>.",pplObjTypeNames[args[3].objType]); TBADD(ERR_TYPE); goto cleanup; } ppl_expIntegrate(context,inExpr,inExprCharPos,(char*)args[1].auxil,k,(char*)args[0].auxil,&args[2],&args[3],out,dollarAllowed,iterDepth); if (context->errStat.status) { goto cleanup; } } } else { if (fn->minArgs == fn->maxArgs) { if (nArgs != fn->maxArgs) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function takes exactly %d arguments; %d supplied.",fn->maxArgs,nArgs); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } } else if (nArgs < fn->minArgs) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function takes a minimum of %d arguments; %d supplied.",fn->minArgs,nArgs); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } else if (nArgs > fn->maxArgs) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function takes a maximum of %d arguments; %d supplied.",fn->maxArgs,nArgs); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } if (fn->numOnly) for (i=0; iset->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function required numeric arguments; argument %d has type <%s>.",i+1,pplObjTypeNames[args[i].objType]); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } if (fn->realOnly) for (i=0; iset->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function requires real arguments; argument %d is complex.",i+1); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } if (fn->dimlessOnly) for (i=0; iset->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function requires dimensionless arguments; argument %d has dimensions of <%s>.",i+1,ppl_printUnit(context, &args[i], NULL, NULL, 1, 1, 0)); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } if (fn->notNan) for (i=0; iset->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function requires finite arguments; argument %d is not finite.",i+1); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } if ((fn->functionType==PPL_FUNC_SYSTEM) && (fn->needSelfThis) && (called.self_this==NULL)) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"Function is a method which has been detached from the object that owns it."); TBADD(ERR_TYPE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } switch (fn->functionType) { case PPL_FUNC_SYSTEM: { int stat=0, errType=-1; ((void(*)(ppl_context *, pplObj *, int, int *, int *, char *))fn->functionPtr)(context, args, nArgs, &stat, &errType, context->errStat.errBuff); if (stat) { TBADD(errType); goto cleanup; } break; } case PPL_FUNC_USERDEF: { int checked[FUNC_MAXARGS], j; pplFunc *f = fn; for (j=0; jminActive[k]!=0) { if (!checked[k]) { if (args[k].objType != PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function is not numeric, but a numeric range is specified for this argument in the function's definition.",k+1); TBADD(ERR_NUMERICAL); return; } else if (!ppl_unitsDimEqual(f->min+k , args+k)) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function is dimensionally incompatible with the argument's specified min/max range: argument has dimensions of <%s>, meanwhile range has dimensions of <%s>.",k+1,ppl_printUnit(context,args+k,NULL,NULL,0,1,0),ppl_printUnit(context,f->min+k,NULL,NULL,1,1,0)); TBADD(ERR_UNIT); return; } else if (args[k].flagComplex) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function must be a real number: any arguments which have min/max ranges specified must be real.",k+1); TBADD(ERR_NUMERICAL); return; } else { checked[k]=1; } } if (args[k].real < f->min[k].real) { f=f->next; l=0; continue; } } if (f->maxActive[k]!=0) { if (!checked[k]) { if (args[k].objType != PPLOBJ_NUM) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function is not numeric, but a numeric range is specified for this argument in the function's definition.",k+1); TBADD(ERR_NUMERICAL); return; } else if (!ppl_unitsDimEqual(f->max+k , args+k)) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function is dimensionally incompatible with the argument's specified min/max range: argument has dimensions of <%s>, meanwhile range has dimensions of <%s>.",k+1,ppl_printUnit(context,args+k,NULL,NULL,0,1,0),ppl_printUnit(context,f->max+k,NULL,NULL,1,1,0)); TBADD(ERR_UNIT); return; } else if (args[k].flagComplex) { sprintf(context->errStat.errBuff,"Argument %d supplied to this function must be a real number: any arguments which have min/max ranges specified must be real.",k+1); TBADD(ERR_UNIT); return; } else { checked[k]=1; } } if (args[k].real > f->max[k].real) { f=f->next; l=0; continue; } } } if (l) break; } if (f==NULL) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"This function is not defined in the requested region of parameter space."); TBADD(ERR_RANGE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } else { int k, lastOpAssign=0, stkp=context->stackPtr, ns_ptr=context->ns_ptr; int setSelf = (called.self_this!=NULL) && ( (called.self_this->objType==PPLOBJ_USER)||(called.self_this->objType==PPLOBJ_MOD)); pplObj *output; // If function definition is null, result is NAN if (f->functionPtr==NULL) { if (context->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(context->errStat.errBuff,"This function is not defined in the requested region of parameter space."); TBADD(ERR_RANGE); goto cleanup; } else { context->stack[context->stackPtr-1-nArgs].real = GSL_NAN; goto cleanup; } } // Check that there's enough space on the stack STACK_MUSTHAVE(context,nArgs+1); if (context->stackFull) { strcpy(context->errStat.errBuff,"Stack overflow."); TBADD(ERR_MEMORY); goto cleanup; } if (context->ns_ptr > CONTEXT_DEPTH-2) { strcpy(context->errStat.errBuff,"Stack overflow."); TBADD(ERR_MEMORY); goto cleanup; } // Consider entering a new local namespace if function is within a module if ((called.self_this!=NULL) && ( (called.self_this->objType==PPLOBJ_USER)||(called.self_this->objType==PPLOBJ_MOD)) ) { dict *d = (dict *)called.self_this->auxil; context->namespaces[++context->ns_ptr] = d; } // Insert arguments into namespace dictionary for (k=j=0; jargList+k, &varObj, &context->stack[stkp+j]); pplObjCpy(varObj, args+j, 0, varObj->amMalloced, 1); k += strlen(fn->argList+k)+1; } context->stackPtr+=nArgs; // Insert variable 'self' into namespace, if this is a method if (setSelf) { pplObj *varObj; ppl_contextGetVarPointer(context, "self", &varObj, &context->stack[stkp+j]); pplObjCpy(varObj, called.self_this, 0, varObj->amMalloced, 1); context->stackPtr++; } // Evaluate function output = ppl_expEval(context, (pplExpr *)f->functionPtr, &lastOpAssign, dollarAllowed, iterDepth+1); // Take arguments out of namespace dictionary for (k=j=0; jargList+k, &context->stack[stkp+j]); k += strlen(fn->argList+k)+1; } // Take self out of namespace dictionary if (setSelf) { ppl_contextRestoreVarPointer(context, "self", &context->stack[stkp+j]); } // Add traceback information if error happened if (context->errStat.status) { strcpy(context->errStat.errBuff,""); TBADD2(ERR_GENERIC,"called function"); } // Tidy up if (output!=NULL) { memcpy(args-1, output, sizeof(pplObj)); context->stackPtr--; } context->stackPtr-=nArgs+setSelf; context->ns_ptr = ns_ptr; } break; } case PPL_FUNC_SUBROUTINE: { dict *d; int j, k, ns_ptr=context->ns_ptr; int shellReturnableOld = context->shellReturnable; const int stkLevelOld = context->stackPtr; // Check that there's enough space on the stack if (context->ns_ptr > CONTEXT_DEPTH-2) { strcpy(context->errStat.errBuff,"Stack overflow."); TBADD(ERR_MEMORY); goto cleanup; } // Enter a new namespace d = ppl_dictInit(1); if (d==NULL) { strcpy(context->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY); goto cleanup; } context->namespaces[++context->ns_ptr] = d; // Set returnable flag context->shellReturnable = 1; // Insert arguments into namespace dictionary for (k=j=0; jargList+k, &varObj, &tmp); pplObjCpy(varObj, args+j, 0, varObj->amMalloced, 1); tmp.amMalloced=0; ppl_garbageObject(&tmp); k += strlen(fn->argList+k)+1; } // Insert variable 'self' into namespace, if this is a method if ((called.self_this!=NULL) && ( (called.self_this->objType==PPLOBJ_USER)||(called.self_this->objType==PPLOBJ_MOD)) ) { pplObj *varObj, tmp; ppl_contextGetVarPointer(context, "self", &varObj, &tmp); pplObjCpy(varObj, called.self_this, 0, varObj->amMalloced, 1); tmp.amMalloced=0; ppl_garbageObject(&tmp); } // Execute subroutine ppl_parserExecute(context, (parserLine *)fn->functionPtr, NULL, 0, iterDepth+1); // Garbage subroutine's namespace ppl_garbageNamespace(d); context->ns_ptr = ns_ptr; while (context->stackPtr>stkLevelOld) { STACK_POP; } // Add traceback information if error happened if (context->errStat.status) { strcpy(context->errStat.errBuff,""); TBADD2(ERR_GENERIC,"called subroutine"); goto cleanup; } // Output return value if (context->shellReturned) pplObjCpy(out, &context->shellReturnVal, 0, 0, 1); else pplObjNum(out, 0, 0, 0); ppl_garbageObject(&context->shellReturnVal); context->shellReturnable = shellReturnableOld; context->shellReturned = 0; break; } case PPL_FUNC_FFT: { int stat=0; FFTDescriptor *f = (FFTDescriptor *)fn->functionPtr; ppl_fft_evaluate(context, "fft", f, args, out, &stat, context->errStat.errBuff); if (stat) { TBADD(ERR_NUMERICAL); goto cleanup; } break; } case PPL_FUNC_HISTOGRAM: { int stat=0; histogramDescriptor *h = (histogramDescriptor *)fn->functionPtr; ppl_histogram_evaluate(context, "histogram", h, args, out, &stat, context->errStat.errBuff); if (stat) { TBADD(ERR_NUMERICAL); goto cleanup; } break; } case PPL_FUNC_SPLINE: { int stat=0; splineDescriptor *s = (splineDescriptor *)fn->functionPtr; ppl_spline_evaluate(context, "interpolation", s, args, out, &stat, context->errStat.errBuff); if (stat) { TBADD(ERR_NUMERICAL); goto cleanup; } break; } case PPL_FUNC_INTERP2D: case PPL_FUNC_BMPDATA: { int stat=0; splineDescriptor *s = (splineDescriptor *)fn->functionPtr; ppl_interp2d_evaluate(context, "interpolation", s, args, args+1, fn->functionType==PPL_FUNC_BMPDATA, out, &stat, context->errStat.errBuff); if (stat) { TBADD(ERR_NUMERICAL); goto cleanup; } break; } default: { sprintf(context->errStat.errBuff,"Call of unsupported function type."); TBADD(ERR_INTERNAL); goto cleanup; } } } cleanup: cast_fail: out->self_this = NULL; out->refCount = 1; for (i=0; i // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalOps.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPEVALOPS_H #define _EXPEVALOPS_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_opAdd(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText); void ppl_opSub(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText); void ppl_opMul(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText); void ppl_opDiv(ppl_context *context, pplObj *a, pplObj *b, pplObj *o, int invertible, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/expressions/expCompile.c0000664000175000017500000015055512026340554017261 0ustar dcf21dcf21// expCompile.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expCompile.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _EXPCOMPILE_C 1 #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "expressions/expCompile_fns.h" #include "pplConstants.h" // expTokenise() -- Tokenise expressions // A -- beginning of expression // B -- a string literal // C -- a string substitution operator // D -- a list of string substitutions // E -- a bracketed sub-expression // F -- a unary post-lvalue operator // G -- a variable name // H -- a unary pre-lvalue operator // I -- a unary value-based operator // J -- a binary operator // K -- a ternary operator // L -- a numeric literal // M -- a list literal // N -- a dictionary literal // O -- a dollar sign // P -- a list of function args // Q -- an array dereference [] // R -- the dot operator // S -- assignment operator // T -- dereference name // U -- end of expression // V -- parameter name after $ // A can be followed by .B..E.GHI..LMNO....... // B can be followed by ..C......JK.....QR..U. // C can be followed by .B.D..GHI..LMNO....... // D can be followed by .........JK.....Q...U. // E can be followed by .....F...JK.....QR..U. // F can be followed by .........JK.........U. // G can be followed by .....F...JK....PQRS.U. // H can be followed by ....E.G............... // I can be followed by .B..E.GH...LMNO....... // J can be followed by .B..E.GHI..LMNO....... // K can be followed by .B..E.GHI..LMNO....... // L can be followed by .........JK.........U. // M can be followed by .........JK.....QR..U. // N can be followed by .........JK.....QR..U. // O can be followed by ....E......L.........V // P can be followed by .........JK....PQR..U. // Q can be followed by .....F...JK....PQRS.U. // R can be followed by ...................T.. // S can be followed by .B..E.GHI..LMNO....... // T can be followed by .....F...JK....PQRS.U. // V can be followed by .........JK.........U. #define MARKUP_MATCH(A) (strncmp(in+scanpos,A,strlen(A))==0) #define PGE_OVERFLOW \ { \ context->tokenBuffLen *= 2; \ context->tokenBuff = (pplTokenCode *)realloc(context->tokenBuff, context->tokenBuffLen * sizeof(pplTokenCode)); \ if (context->tokenBuff == NULL) { *errPos = scanpos; *errType=ERR_OVERFLOW; strcpy(errText, "Algebraic expression too long"); *end = -1; return; } \ out = context->tokenBuff + outOffset; \ buffSize = context->tokenBuffLen - outOffset; \ } #define NEWSTATE(L,O,P) \ { \ int i; \ state=trialstate; \ opcode=O; \ precedence=P; \ for (i=0;i=buffSize) PGE_OVERFLOW; \ } \ scanpos+=L; \ } #define SAMESTATE \ { \ out[outpos].state = state; \ out[outpos].opcode = opcode; \ out[outpos].precedence = precedence; \ outpos++; \ if (outpos>=buffSize) PGE_OVERFLOW; \ scanpos++; \ } #define FFWSTATE(L) \ { \ while (outpos+L>=buffSize) PGE_OVERFLOW; \ outpos += (L); \ scanpos += (L); \ } void ppl_expTokenise(ppl_context *context, char *in, int *end, int dollarAllowed, int equalsAllowed, int allowCommaOperator, int collectCommas, int isDict, int outOffset, int *outlen, int *errPos, int *errType, char *errText) { const char *allowed[] = {"BEHILMNOG","CJKQRU","BDHILMNOG","JKQU","FJKQRU","JKU","SFJKPQRU","EG","BEHLMNOG","BEHILMNOG","BEHILMNOG","JKU","JKQRU","JKQRU","ELV","JKPQRU","SFJKPQRU","T","BEHILMNOG","SFJKPQRU","","JKU"}; int nCommaItems=1, nDictItems=0, tertiaryDepth=0; char state='A', trialstate; int scanpos=0, outpos=0, oldpos, trialpos; unsigned char opcode=0, precedence=0; pplTokenCode *out; int buffSize; int expOp = 0; // Was last named function one which acts on an expression -- e.g. unit() or int_dx()? int extraArg = 0; // Was last named function one which has a variable name encoded in it -- i.e. int_dx() or diff_dx()? if ( (outOffset==0) && (context->tokenBuffLen > ALGEBRA_MAXLEN) ) { free(context->tokenBuff); context->tokenBuff = NULL; context->tokenBuffLen = 0; } if (context->tokenBuff == NULL) { context->tokenBuff = (pplTokenCode *)malloc(ALGEBRA_MAXLEN * sizeof(pplTokenCode)); context->tokenBuffLen = ALGEBRA_MAXLEN; } if (context->tokenBuff == NULL) { *errPos = 0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory"); *end = -1; return; } out = context->tokenBuff + outOffset; buffSize = context->tokenBuffLen - outOffset; while (state!='U') { while ((in[scanpos]!='\0') && (in[scanpos]<=' ')) { SAMESTATE; } // Sop up whitespace oldpos = scanpos; for (trialpos=0; ((trialstate=allowed[(int)(state-'A')][trialpos])!='\0'); trialpos++) { if ((expOp)&&(trialstate!='P')) continue; // int_dx and diff_dx MUST be followed by arguments; they have already put one on the stack. if (trialstate=='B') // string literal { char quoteType; int raw=0; if ( (in[scanpos]=='r') && ((in[scanpos+1]=='\'') || (in[scanpos+1]=='"')) ) { raw=1; NEWSTATE(1,0,0); } // r'hello' is raw string if ( (in[scanpos]=='e') && ((in[scanpos+1]=='\'') || (in[scanpos+1]=='"')) ) { raw=0; NEWSTATE(1,0,0); } // e'hello' is string with extended escapes if ( (in[scanpos]==(quoteType='\'')) || (in[scanpos]==(quoteType='"')) ) { int j=1, tripleQuote=0; if ((in[scanpos+1]==quoteType)&&(in[scanpos+2]==quoteType)) { j=3; tripleQuote=1; } for ( ; (in[scanpos+j]!='\0') && ( ((!tripleQuote) && (in[scanpos+j]!=quoteType)) || ( tripleQuote && ((in[scanpos+j]!=quoteType)||(in[scanpos+j+1]!=quoteType)||(in[scanpos+j+2]!=quoteType)) ) ) ; j++) if ((!raw)&&(in[scanpos+j]=='\\')&&(in[scanpos+j+1]!='\0')) j++; if (in[scanpos+j]==quoteType) { if (tripleQuote) { j+=3; } else { j++; } NEWSTATE(j,0,0); } else { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Mismatched quote."); *end=-1; *outlen=0; return; } } } else if (trialstate=='C') // string substitution operator { if (MARKUP_MATCH("%")) { NEWSTATE(1,0x40,4); } } else if ( (trialstate=='D') // a list of string substitutions || (trialstate=='E') // a bracketed sub-expression || (trialstate=='P') ) // a list of function arguments { if (MARKUP_MATCH("(")) { int j,k,l,m,n=1,cp[3],cpl=3,extraStrArg=0; ppl_strBracketMatch(in+scanpos,'(',')',cp,&cpl,&j,cpl); // Search for a ) to match the ( if (j<=0) { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Mismatched ( )"); *end=-1; *outlen=0; return; } NEWSTATE(1,0,0); // Record the one character opening bracket while ((in[scanpos]!='\0') && (in[scanpos]<=' ')) { SAMESTATE; n++; } // Sop up whitespace if ((trialstate=='P')&&(expOp)&&(in[scanpos]!='\'')&&(in[scanpos]!='"')) // Function call acting on expression: save expression as string even though it's not quoted { int explen = cp[1]+(cpl!=1)-n; if (expOp>1) explen=j-n; // texify receives all arguments as a string if (cpl<1) { *errPos=scanpos; *errType=ERR_INTERNAL; strcpy(errText, "ppl_strBracketMatch returned fewer than two results."); *end=-1; *outlen=0; return; } trialstate='B'; NEWSTATE(explen,0,0); trialstate='P'; n+=explen; extraStrArg=(explen>0); } k=scanpos; l=outpos; j-=n; if ((in[k]!=')')||(trialstate=='E')) { ppl_expTokenise(context,in+k,&m,dollarAllowed,1,1,(trialstate!='E'),0,l+outOffset,&n,errPos,errType,errText); // Hierarchically tokenise the inside of the brackets if (*errPos>=0) { *errPos+=k; return; } if (m!=j) { *errPos = m+k; *errType=ERR_SYNTAX; strcpy(errText, "Unexpected trailing matter at end of expression."); *end=-1; *outlen=0; return; } } else out[outpos].depth = 0; FFWSTATE(j); // Fast-forward to closing bracket if (extraStrArg) out[outpos].depth++; if (extraArg) out[outpos].depth++; NEWSTATE(1,0,0); // Record the one character closing bracket extraArg=0; expOp=0; } } else if (trialstate=='F') // a unary post-lvalue operator { if (MARKUP_MATCH("--")) { NEWSTATE(2,0x21,3); } else if (MARKUP_MATCH("++")) { NEWSTATE(2,0x22,3); } } else if (trialstate=='H') // a unary pre-lvalue operator { if (MARKUP_MATCH("--")) { NEWSTATE(2,0x23,3); } else if (MARKUP_MATCH("++")) { NEWSTATE(2,0x24,3); } } else if ( (trialstate=='G') || // a variable name (trialstate=='T') || // a dereference name (trialstate=='V') ) // a $parameter name { if (isalpha(in[scanpos])) { const char tmp = trialstate; if ((strncmp(in+scanpos,"unit",4)==0) && (!isalnum(in[scanpos+4])) && (in[scanpos+4]!='_')) // unit() function { expOp = 1; NEWSTATE(4,0,0); } else if (strncmp(in+scanpos,"int_d",5)==0) // int_d() function { if (!isalpha(in[scanpos+5])) { *errPos=scanpos; *errType=ERR_SYNTAX; strcpy(errText, "System function int_d should be followed by a variable name to integrate over."); *end=-1; *outlen=0; return; } NEWSTATE(5,0,0); trialstate='B'; NEWSTATE(1,0,0); while ((isalnum(in[scanpos])) || (in[scanpos]=='_')) { SAMESTATE; } trialstate=tmp; NEWSTATE(0,0,0); expOp = 1; extraArg=1; } else if (strncmp(in+scanpos,"diff_d",6)==0) // diff_d() function { if (!isalpha(in[scanpos+6])) { *errPos=scanpos; *errType=ERR_SYNTAX; strcpy(errText, "System function diff_d should be followed by a variable name to differentiate with respect to."); *end=-1; *outlen=0; return; } NEWSTATE(6,0,0); trialstate='B'; NEWSTATE(1,0,0); while ((isalnum(in[scanpos])) || (in[scanpos]=='_')) { SAMESTATE; } trialstate=tmp; NEWSTATE(0,0,0); expOp = 1; extraArg=1; } else { NEWSTATE(1,0,0); while ((isalnum(in[scanpos])) || (in[scanpos]=='_')) { SAMESTATE; } expOp = 0; } } } else if (trialstate=='I') // a unary value-based operator { if (MARKUP_MATCH("-" )) { NEWSTATE(1,0x25, 3); } else if (MARKUP_MATCH("+" )) { NEWSTATE(1,0x26, 3); } else if (MARKUP_MATCH("~" )) { NEWSTATE(1,0xA7, 3); } else if (MARKUP_MATCH("!" )) { NEWSTATE(1,0xA8, 3); } else if (MARKUP_MATCH("not")&&(!isalpha(in[scanpos+3]))) { NEWSTATE(3,0xA8, 3); } else if (MARKUP_MATCH("NOT")&&(!isalpha(in[scanpos+3]))) { NEWSTATE(3,0xA8, 3); } } else if (trialstate=='J') // a binary operator { if (MARKUP_MATCH("**" )) { NEWSTATE(2,0xC9, 2); } else if (MARKUP_MATCH("<<" )) { NEWSTATE(2,0x4F, 7); } else if (MARKUP_MATCH(">>" )) { NEWSTATE(2,0x50, 7); } else if (MARKUP_MATCH("<=" )) { NEWSTATE(2,0x52, 8); } else if (MARKUP_MATCH(">=" )) { NEWSTATE(2,0x53, 8); } else if (MARKUP_MATCH("==" )) { NEWSTATE(2,0x55, 9); } else if (MARKUP_MATCH("<>" )) { NEWSTATE(2,0x56,10); } else if (MARKUP_MATCH("!=" )) { NEWSTATE(2,0x56,10); } else if (MARKUP_MATCH("&&" )) { NEWSTATE(2,0x5A,14); } else if (MARKUP_MATCH("and")&&(!isalpha(in[scanpos+3]))) { NEWSTATE(3,0x5A,14); } else if (MARKUP_MATCH("AND")&&(!isalpha(in[scanpos+3]))) { NEWSTATE(3,0x5A,14); } else if (MARKUP_MATCH("||" )) { NEWSTATE(2,0x5B,15); } else if (MARKUP_MATCH("or" )&&(!isalpha(in[scanpos+2]))) { NEWSTATE(2,0x5B,15); } else if (MARKUP_MATCH("OR" )&&(!isalpha(in[scanpos+2]))) { NEWSTATE(2,0x5B,15); } else if (MARKUP_MATCH("*" )) { NEWSTATE(1,0x4A, 5); } else if (MARKUP_MATCH("/" )) { NEWSTATE(1,0x4B, 5); } else if (MARKUP_MATCH("%" )) { NEWSTATE(1,0x4C, 5); } else if (MARKUP_MATCH("+" )) { NEWSTATE(1,0x4D, 6); } else if (MARKUP_MATCH("-" )) { NEWSTATE(1,0x4E, 6); } else if (MARKUP_MATCH("<" )) { NEWSTATE(1,0x51, 8); } else if (MARKUP_MATCH(">" )) { NEWSTATE(1,0x54, 8); } else if (MARKUP_MATCH("&" )) { NEWSTATE(1,0x57,11); } else if (MARKUP_MATCH("^" )) { NEWSTATE(1,0x58,12); } else if (MARKUP_MATCH("|" )) { NEWSTATE(1,0x59,13); } else if((MARKUP_MATCH("," ) && (collectCommas || allowCommaOperator || (tertiaryDepth>0)))) { if ((!collectCommas)||(tertiaryDepth>0)) { NEWSTATE(1,0x5C,18); } else { if (isDict && (nCommaItems>=2-(nDictItems==0))) { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Expecting : followed by value for dictionary key"); *end=-1; *outlen=0; return; } NEWSTATE(1,0x5F,18); nCommaItems++; } } } else if (trialstate=='K') // a ternary operator { if (MARKUP_MATCH("?")) { NEWSTATE(1,0xFD,16); tertiaryDepth++; } else if (MARKUP_MATCH(":")) { if (isDict && (tertiaryDepth==0)) { if (nCommaItems<2-(nDictItems==0)) { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Expecting , to separate dictionary items"); *end=-1; *outlen=0; return; } NEWSTATE(1,0x5F,18); nCommaItems=1; nDictItems++; } else { if (tertiaryDepth>0) { tertiaryDepth--; NEWSTATE(1,0xFE,16); } } } } else if (trialstate=='L') // a numeric literal { int j=0; if (ppl_validFloat(in+scanpos,&j)) { NEWSTATE(j,0,0); } } else if ( (trialstate=='M') || // a list literal (trialstate=='Q') ) // an array dereference [] { expOp=0; if (MARKUP_MATCH("[")) { int j,k,l,m=0,n=1; int slice=0,minSet=0,maxSet=0; ppl_strBracketMatch(in+scanpos,'[',']',NULL,NULL,&j,0); // Search for a ] to match the [ if (j<=0) { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Mismatched [ ]"); *end=-1; *outlen=0; return; } NEWSTATE(1,0,0); // Record the one character opening bracket if ((trialstate=='Q') && (in[scanpos]==':')) // slice of the form [:x] { SAMESTATE; n++; slice=1; while ((in[scanpos]!='\0') && (in[scanpos]<=' ')) { SAMESTATE; n++; } // Sop up whitespace } k=scanpos; l=outpos; j-=n; if ((in[k]!=']') || ((trialstate=='Q')&&(!slice))) // [] is allowed as a list literal, but not as an array dereference { if (slice) maxSet=1; ppl_expTokenise(context,in+k,&m,dollarAllowed,1,1,trialstate!='Q',0,l+outOffset,&n,errPos,errType,errText); // Hierarchically tokenise the inside of the brackets if (*errPos>=0) { *errPos+=k; return; } if ((trialstate=='Q')&&(!slice)&&(in[k+m]==':')) { slice = minSet = 1; FFWSTATE(m); j-=m; // Fast-forward over first expression in range trialstate='J'; NEWSTATE(1,0x5F,18); j--; // Treat : separating ranges as a , operator (collect items on stack) while ((in[scanpos]!='\0') && (in[scanpos]<=' ')) { SAMESTATE; j--; } // Sop up whitespace trialstate='Q'; k=scanpos; l=outpos; m=0; if (j>0) { maxSet=1; ppl_expTokenise(context,in+k,&m,dollarAllowed,1,1,trialstate!='Q',0,l+outOffset,&n,errPos,errType,errText); // Hierarchically tokenise the inside of the brackets if (*errPos>=0) { *errPos+=k; return; } } } if (m!=j) { *errPos = m+k; *errType=ERR_SYNTAX; strcpy(errText, "Unexpected trailing matter at end of expression"); *end=-1; *outlen=0; return; } } else out[outpos].depth = 0; FFWSTATE(j); // Fast-forward to closing bracket if (trialstate=='Q') { out[outpos].opcode = (((minSet<<1) + maxSet)<<1) + !slice; out[outpos].precedence = 0; } NEWSTATE(1, out[outpos].opcode, out[outpos].precedence); // Record the one character closing bracket } } else if (trialstate=='N') // a dictionary literal { if (MARKUP_MATCH("{")) { int j,k,l,m,n=1; ppl_strBracketMatch(in+scanpos,'{','}',NULL,NULL,&j,0); // Search for a } to match the { if (j<=0) { *errPos = scanpos; *errType=ERR_SYNTAX; strcpy(errText, "Mismatched { }"); *end=-1; *outlen=0; return; } NEWSTATE(1,0,0); // Record the one character opening bracket while ((in[scanpos]!='\0') && (in[scanpos]<=' ')) { SAMESTATE; n++;} // Sop up whitespace k=scanpos; l=outpos; j-=n; if (in[k]!='}') { ppl_expTokenise(context,in+k,&m,dollarAllowed,1,1,1,1,l+outOffset,&n,errPos,errType,errText); // Hierarchically tokenise the inside of the brackets if (*errPos>=0) { *errPos+=k; return; } if (m!=j) { *errPos = m+k; *errType=ERR_SYNTAX; strcpy(errText, "Unexpected trailing matter at end of expression"); *end=-1; *outlen=0; return; } } else out[outpos].depth = 0; FFWSTATE(j); // Fast-forward to closing bracket NEWSTATE(1,0,0); // Record the one character closing bracket } } else if (trialstate=='O') // a dollar sign { if ((dollarAllowed)&&(MARKUP_MATCH("$"))) { NEWSTATE(1,0,0); } } else if (trialstate=='R') // the dot operator { if (MARKUP_MATCH(".")) { NEWSTATE(1,0,0); } } else if (trialstate=='S') // assignment operator { if ((MARKUP_MATCH("=" )&&(in[scanpos+1]!='=')&&equalsAllowed)) { NEWSTATE(1,0x40,17); } // Match = but not == else if (MARKUP_MATCH("+=" )) { NEWSTATE(2,0x41,17); } else if (MARKUP_MATCH("-=" )) { NEWSTATE(2,0x42,17); } else if (MARKUP_MATCH("*=" )) { NEWSTATE(2,0x43,17); } else if (MARKUP_MATCH("/=" )) { NEWSTATE(2,0x44,17); } else if (MARKUP_MATCH("%=" )) { NEWSTATE(2,0x45,17); } else if (MARKUP_MATCH("&=" )) { NEWSTATE(2,0x46,17); } else if (MARKUP_MATCH("^=" )) { NEWSTATE(2,0x47,17); } else if (MARKUP_MATCH("|=" )) { NEWSTATE(2,0x48,17); } else if (MARKUP_MATCH("<<=")) { NEWSTATE(3,0x49,17); } else if (MARKUP_MATCH(">>=")) { NEWSTATE(3,0x4A,17); } else if (MARKUP_MATCH("**=")) { NEWSTATE(3,0x4B,17); } } else if (trialstate=='U') // end of expression { NEWSTATE(0,0,0); } if (scanpos != oldpos) break; } if (scanpos == oldpos) break; // We've got stuck } if (state=='U') // We reached state U... end of expression { *errPos = -1; *errType = 0; *errText='\0'; out[outpos].state = '@'; out[outpos].opcode = 0; if (isDict) { out[outpos].depth = nDictItems; } else if (collectCommas) { out[outpos].depth = nCommaItems; } else { out[outpos].depth = 0; } outpos++; *end = scanpos; *outlen = outpos; return; } else { // Error; we didn't reach state U int i=0,j=0; int B=0,F=0,G=0,J=0,P=0; *errPos = scanpos; *end = -1; *outlen = 0; // Now we need to construct an error string *errType = ERR_SYNTAX; strcpy(errText,"At this point, was expecting "); i=strlen(errText); for (trialpos=0; ((trialstate=allowed[(int)(state-'A')][trialpos])!='\0'); trialpos++) { if ((expOp)&&(trialstate!='P')) continue; // int_dx and diff_dx MUST be followed by arguments; they have already put one on the stack. #define W { if (j!=0) {strcpy(errText+i," or "); i+=strlen(errText+i);} else j=1; } if ((!B)&&((trialstate=='B')||(trialstate=='L')||(trialstate=='M')||(trialstate=='N')||(trialstate=='O'))) { W; strcpy(errText+i,"a literal value"); i+=strlen(errText+i); B=1; } else if (trialstate=='C') { W; strcpy(errText+i,"a string substitution operator"); i+=strlen(errText+i); } else if (trialstate=='D') { W; strcpy(errText+i,"a list of string substitutions"); i+=strlen(errText+i); } else if (trialstate=='E') { W; strcpy(errText+i,"a bracketed expression"); i+=strlen(errText+i); } else if ((!F)&&((trialstate=='F')||(trialstate=='H')||(trialstate=='I'))) { W; strcpy(errText+i,"a unary operator"); i+=strlen(errText+i); F=1; } else if ((!G)&&((trialstate=='G')||(trialstate=='T'))) { W; strcpy(errText+i,"a variable name"); i+=strlen(errText+i); G=1; } else if ((!J)&&((trialstate=='J')||(trialstate=='K')||(trialstate=='S'))) { W; strcpy(errText+i,"a binary/ternary operator"); i+=strlen(errText+i); J=1; } else if (trialstate=='P') { W; strcpy(errText+i,"a list of function arguments"); i+=strlen(errText+i); } else if ((!P)&&((trialstate=='Q')||(trialstate=='R'))) { W; strcpy(errText+i,"an object dereference"); i+=strlen(errText+i); P=1; } } strcpy(errText+i,"."); i+=strlen(errText+i); return; } } // ppl_tokenPrint() -- a debugging routine to display tokenised data void ppl_tokenPrint(ppl_context *context, char *in, int len) { pplTokenCode *tdat = context->tokenBuff; int i; for (i=0; i0) ? (stack[stackpos-1].opType) : '!' , (opType=='o')||(opType=='a')||(opType=='$')) /* while the stack is not empty and has an operator at the top */ \ { \ int stackprec = stack[stackpos-1].precedence; \ if ((stackprec==2)&&(precedence==3)) stackprec=4; /* Magic treatment of x**-1 */ \ if ( ((!rightAssoc)&&(precedence>=stackprec)) || ((rightAssoc)&&(precedence>stackprec)) ) /* pop operators with higher precedence from stack */ \ { \ const unsigned char stacko = stack[stackpos-1].opcode; /* operator number of the stack object */ \ const int charpos = stack[stackpos-1].charpos; \ int bytecode = 0; \ if (opType=='a' ) bytecode = 12; /* assignment operator */ \ else if (opType=='$' ) bytecode = 15; /* dollar operator */ \ else if (stacko==0x40) bytecode = 14; /* string subst operator */ \ else if (stacko==0x23) bytecode = 13; /* ++ lval operator */ \ else if (stacko==0x24) bytecode = 13; /* -- lval operator */ \ else bytecode = 11; /* other operator */ \ if (stacko==0x5A) { int o=stack[stackpos-1].outpos; BYTECODE_OP(20); BYTECODE_ENDOP; out[o].auxil.i=outpos; } /* || operator */ \ else if (stacko==0x5B) { int o=stack[stackpos-1].outpos; BYTECODE_OP(20); BYTECODE_ENDOP; out[o].auxil.i=outpos; } /* && operator */ \ else if (stacko==0xFE) { int o=stack[stackpos-1].outpos; out[o].auxil.i=outpos; } /* ?: operator, closing : */ \ else if (stacko!=0x5F) /* null operations get ignored (e.g. commas that collect items) */ \ { \ const int tpos = charpos; \ BYTECODE_OP(bytecode); \ out[outpos].auxil.i = stacko; \ if ((opType=='o')&&(stacko==0x40)) out[outpos].auxil.i = 1; /* string substitution operator with only one subst item (not a bracketed list) */ \ BYTECODE_ENDOP; \ } \ stackpos--; /* pop stack */ \ } \ else break; \ } \ } #define BYTECODE_OP_POS(X,P) \ { \ lastoutpos = outpos; \ out[outpos].len = 0; /* Set length of instruction equals zero for the moment */ \ out[outpos].charpos = P; /* Store character position of token for error reporting */ \ out[outpos].opcode = X; \ } #define BYTECODE_OP(X) \ { \ BYTECODE_OP_POS(X,tpos); \ } #define BYTECODE_ENDOP \ { \ outpos++; \ out[lastoutpos].len = outpos - lastoutpos; /* Write the length of the bytecode instruction we've just written */ \ } void ppl_expCompile(ppl_context *context, int srcLineN, long srcId, char *srcFname, char *in, int *end, int dollarAllowed, int equalsAllowed, int allowCommaOperator, pplExpr **outExpr, int *errPos, int *errType, char *errText) { pplExprPStack *stack; pplTokenCode *tdata; int stackpos = 0; int stacklen; int tpos; int tlen; int outpos = 0, lastoutpos = -1; pplExprBytecode *out; int outlen = 512; // malloc output structure *outExpr = (pplExpr *)calloc(1,sizeof(pplExpr)); if (*outExpr==NULL) { *errPos=0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); *end=-1; return; } (*outExpr)->refCount = 1; (*outExpr)->srcId = srcId; (*outExpr)->srcLineN = srcLineN; (*outExpr)->srcFname = (char *)malloc(strlen(srcFname)+1); out = (*outExpr)->bytecode = malloc(outlen * sizeof(pplExprBytecode)); if (((*outExpr)->bytecode==NULL)||((*outExpr)->srcFname==NULL)) { *errPos=0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); *end=-1; return; } strcpy((*outExpr)->srcFname , srcFname); // First tokenise expression ppl_expTokenise(context, in, end, dollarAllowed, equalsAllowed, allowCommaOperator, 0, 0, 0, &tlen, errPos, errType, errText); if (*errPos >= 0) return; tdata = context->tokenBuff; //ppl_tokenPrint(context, in, tlen); // Make stack if (context->parserStackLen > 1024) { free(context->parserStack); context->parserStack = NULL; context->parserStackLen = 0; } if (context->parserStack == NULL) { context->parserStackLen = 1024; context->parserStack = (pplExprPStack *)malloc(context->parserStackLen * sizeof(pplExprPStack)); } if (context->parserStack == NULL) { *errPos = 0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory"); *end = -1; return; } stack = context->parserStack; stacklen = context->parserStackLen; // Copy ASCII expression into expression object (*outExpr)->ascii = (char *)malloc(*end+1); if ((*outExpr)->ascii==NULL) { *errPos=0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); *end=-1; return; } strncpy((*outExpr)->ascii, in, *end); (*outExpr)->ascii[*end]='\0'; // The stacking-yard algorithm for ( tpos=0; tposbytecode = realloc(out, outlen*sizeof(pplExprBytecode)); if (out==NULL) { *errPos=0; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); *end=-1; return; } } if (o=='B') // Process a string literal { int i; char quoteType=in[tpos]; char *oc = (char *)(out+outpos+1); int ol = 0; BYTECODE_OP(2); // bytecode op 2 if ((quoteType=='r') && ((in[tpos+1]=='\'') || (in[tpos+1]=='\"')) ) // r'hello' raw string { int offset=2, tripleQuote=0; quoteType=in[tpos+1]; if ((in[tpos+2]==quoteType)&&(in[tpos+3]==quoteType)) { offset=4; tripleQuote=1; } for ( i=tpos+offset ; ( ((!tripleQuote) && (in[i]!=quoteType)) || ( tripleQuote && ((in[i]!=quoteType)||(in[i+1]!=quoteType)||(in[i+2]!=quoteType)) ) ); i++ ) { if (in[i]=='\0') { *errPos=i; *errType=ERR_INTERNAL; strcpy(errText, "Unexpected end of string."); *end=-1; return; } oc[ol++] = in[i]; } } else if ((quoteType=='e') && ((in[tpos+1]=='\'') || (in[tpos+1]=='\"')) ) // e'hello' string with extended escaping { int offset=2, tripleQuote=0; quoteType=in[tpos+1]; if ((in[tpos+2]==quoteType)&&(in[tpos+3]==quoteType)) { offset=4; tripleQuote=1; } for ( i=tpos+offset ; ( ((!tripleQuote) && (in[i]!=quoteType)) || ( tripleQuote && ((in[i]!=quoteType)||(in[i+1]!=quoteType)||(in[i+2]!=quoteType)) ) ); i++ ) { if (in[i]=='\0') { *errPos=i; *errType=ERR_INTERNAL; strcpy(errText, "Unexpected end of string."); *end=-1; return; } if (in[i]=='\\') switch (in[i+1]) { case '?' : oc[ol++]='\?'; i++; break; case '\'': oc[ol++]='\''; i++; break; case '\"': oc[ol++]='\"'; i++; break; case '\\': oc[ol++]='\\'; i++; break; case 'a' : oc[ol++]='\a'; i++; break; case 'b' : oc[ol++]='\b'; i++; break; case 'f' : oc[ol++]='\f'; i++; break; case 'n' : oc[ol++]='\n'; i++; break; case 'r' : oc[ol++]='\r'; i++; break; case 't' : oc[ol++]='\t'; i++; break; case 'v' : oc[ol++]='\v'; i++; break; default : oc[ol++] = in[i]; break; } else { oc[ol++] = in[i]; } } } else if ((quoteType!='\'')&&(quoteType!='"')) // Unquoted string { while ((tpos=tlen) break; } if ((ol>0)&&(oc[ol-1]==',')) ol--; } else // a string of the form 'hello' with only quote characters escaped { int offset=1, tripleQuote=0; if ((in[tpos+1]==quoteType)&&(in[tpos+2]==quoteType)) { offset=3; tripleQuote=1; } for ( i=tpos+offset ; ( ((!tripleQuote) && (in[i]!=quoteType)) || ( tripleQuote && ((in[i]!=quoteType)||(in[i+1]!=quoteType)||(in[i+2]!=quoteType)) ) ); i++ ) { if (in[i]=='\0') { *errPos=i; *errType=ERR_INTERNAL; strcpy(errText, "Unexpected end of string."); *end=-1; return; } if (in[i]=='\\') switch (in[i+1]) { case '\'': oc[ol++]='\''; i++; break; case '\"': oc[ol++]='\"'; i++; break; case '\\': oc[ol++]='\\'; i++; break; default : oc[ol++] = in[i]; break; } else { oc[ol++] = in[i]; } } } oc[ol++] = '\0'; outpos += 1 + (ol/sizeof(pplExprBytecode)); BYTECODE_ENDOP; } else if ( (o=='C') || (o=='H') || (o=='I') || (o=='J') || (o=='K') || (o=='S') ) // Process an operator { unsigned char opcode = tdata[tpos].opcode; int precedence = tdata[tpos].precedence; int rightAssoc = ((opcode & 0x80) != 0) || (o=='S'); // All assignment operators (S) are right-left associative POP_STACK; // : operator part of ? : ... pop the ? from the stack now if ((o=='K')&&(opcode==0xFE)) { int o,precedence=999; POP_STACK; if ( (stackpos<1) || (stack[stackpos-1].opType!='t') ) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match : to a ? in the ternary operator."); *end=-1; return; } o = stack[stackpos-1].outpos; out[o].auxil.i = outpos+1; stackpos--; // pop ? from stack } if ((o=='S')&&(opcode==0x40)) { GET_POINTER; } // Turn variable lookup into pointer lookup now, because assignment operators are binary and operand is guaranteed to be the last thing on the stack else if ((o=='J')&&(opcode==0x5A)) { BYTECODE_OP(17); out[outpos].flag = 0; stack[stackpos].outpos=outpos; BYTECODE_ENDOP; } // && operator compiles to if false goto else pop else if ((o=='J')&&(opcode==0x5B)) { BYTECODE_OP(18); out[outpos].flag = 0; stack[stackpos].outpos=outpos; BYTECODE_ENDOP; } // || operator compiles to if true goto else pop else if ((o=='K')&&(opcode==0xFD)) { BYTECODE_OP(17); out[outpos].flag = 1; stack[stackpos].outpos=outpos; BYTECODE_ENDOP; } // ? operator -- if false goto else if ((o=='K')&&(opcode==0xFE)) { BYTECODE_OP(19); stack[stackpos].outpos=outpos; BYTECODE_ENDOP; } // : operator -- goto if (stackpos>stacklen-4) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; if (o=='S') stack[stackpos].opType = 'a'; // push operator onto stack else if (opcode==0xFD) stack[stackpos].opType = 't'; else stack[stackpos].opType = 'o'; stack[stackpos].opcode = opcode; stack[stackpos].precedence = precedence; stackpos++; } else if ( (o=='D') || (o=='E') || (o=='P') ) // Process ( ) { char bracketType=in[tpos]; if (bracketType=='(') // open ( { if (stackpos>stacklen-4) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; stack[stackpos].opType = '('; // push bracket onto stack stack[stackpos].opcode = 0; stack[stackpos].precedence = 0; stackpos++; } else // close ) { int rightAssoc = 0; int precedence = 255; int startpos; POP_STACK; // Pop the stack of all operators (fake operator above with very low precedence) if ( (stackpos<1) || (stack[stackpos-1].opType!='(') ) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match ) to an (."); *end=-1; return; } startpos = stack[stackpos-1].charpos; stackpos--; // pop bracket if (o=='D') // apply string substitution operator straight away { if ( (stackpos<1) || (stack[stackpos-1].opcode!=0x40)) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match string substituion () to a %."); *end=-1; return; } stackpos--; // pop stack BYTECODE_OP_POS(14,startpos); // bytecode 14 -- string substitution operator out[outpos].auxil.i = (int)tdata[tpos].depth; // store the number of string substitutions; stored with closing bracket in bytecode is number of collected ,-separated items BYTECODE_ENDOP; } else if (o=='P') // make function call { BYTECODE_OP_POS(10,startpos); // bytecode 10 -- function call out[outpos].auxil.i = (int)tdata[tpos].depth; // store the number of function arguments; stored with closing bracket in bytecode is number of collected ,-separated items BYTECODE_ENDOP; } } } else if (o=='F') // a postfix ++ or -- operator { int rightAssoc = (tdata[tpos].opcode & 0x80) != 0; int precedence = tdata[tpos].precedence; POP_STACK; BYTECODE_OP(13); out[outpos].auxil.i = tdata[tpos].opcode; BYTECODE_ENDOP; } else if ( (o=='G') || (o=='T') || (o=='V') ) // a variable name or field dereferenced with the . operator { char *strout = (char *)(out+outpos+1); int slen = 0; if (o=='G') BYTECODE_OP(3) // foo -- op 3: variable lookup "foo" else if (o=='T') BYTECODE_OP(5) // foo.bar -- op 5: dereference "bar" else BYTECODE_OP(2) // $foo -- push "foo" onto stack as a string constant while ((tpos=tlen) break; } strout[slen++] = '\0'; outpos += 1 + (slen/sizeof(pplExprBytecode)); BYTECODE_ENDOP; } else if (o=='L') // a numeric literal { BYTECODE_OP(1); out[outpos].auxil.d = ppl_getFloat(in+tpos,NULL); BYTECODE_ENDOP; } else if (o=='M') // list literal { char bracketType=in[tpos]; if (bracketType=='[') // open [ { if (stackpos>stacklen-4) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; stack[stackpos].opType = '['; // push bracket onto stack stack[stackpos].opcode = 0; stack[stackpos].precedence = 0; stackpos++; } else // close ] { unsigned char rightAssoc = 0; unsigned char precedence = 255; int startpos; POP_STACK; // Pop the stack of all operators (fake operator above with very low precedence) if ( (stackpos<1) || (stack[stackpos-1].opType!='[') ) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match ] to an [."); *end=-1; return; } startpos = stack[stackpos-1].charpos; stackpos--; // pop bracket BYTECODE_OP_POS(9,startpos); // bytecode 9 -- make list out[outpos].auxil.i = tdata[tpos].depth; // store the number of list items; stored with closing bracket in bytecode is number of collected ,-separated items BYTECODE_ENDOP; } } else if (o=='N') // dictionary literal { char bracketType=in[tpos]; if (bracketType=='{') // open { { if (stackpos>stacklen-64) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; stack[stackpos].opType = '{'; // push bracket onto stack stack[stackpos].opcode = 0; stack[stackpos].precedence = 0; stackpos++; } else // close } { int rightAssoc = 0; int precedence = 255; int startpos; POP_STACK; // Pop the stack of all operators (fake operator above with very low precedence) if ( (stackpos<1) || (stack[stackpos-1].opType!='{') ) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match } to an {."); *end=-1; return; } startpos = stack[stackpos-1].charpos; stackpos--; // pop bracket BYTECODE_OP_POS(8,startpos); // bytecode 8 -- make dict out[outpos].auxil.i = tdata[tpos].depth; // store the number of list items; stored with closing bracket in bytecode is number of collected ,-separated items BYTECODE_ENDOP; } } else if (o=='O') // a dollar operator { if (stackpos>stacklen-4) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; stack[stackpos].opType = '$'; // push bracket onto stack stack[stackpos].opcode = 0; stack[stackpos].precedence = 0; stackpos++; } else if (o=='R') // a dot dereference { // Nop -- the work is done in the following T-state parameter. } else if (o=='Q') // array dereference or slice { char bracketType=in[tpos]; if (bracketType=='[') // open dereference brackets { if (stackpos>stacklen-4) { *errPos = tpos; *errType=ERR_OVERFLOW; strcpy(errText, "Stack overflow whilst parsing algebraic expression."); *end=-1; return; } stack[stackpos].charpos = tpos; stack[stackpos].opType = '<'; // push slice onto stack stack[stackpos].opcode = 0; stack[stackpos].precedence = 0; stackpos++; } else // close ] { int rightAssoc = 0; int precedence = 255; int startpos; POP_STACK; // Pop the stack of all operators (fake operator above with very low precedence) if ( (stackpos<1) || (stack[stackpos-1].opType!='<') ) { *errPos=tpos; *errType=ERR_INTERNAL; strcpy(errText, "Could not match ] to an [."); *end=-1; return; } startpos = stack[stackpos-1].charpos; stackpos--; // pop bracket BYTECODE_OP_POS(7,startpos); // bytecode 7 -- slice object out[outpos].auxil.i = tdata[tpos].opcode; // flags to distinguish [x], [x:], [:x], [x:y] and [:] BYTECODE_ENDOP; } } while ((tpos=tlen) break; if ((o=='D') && ((in[tpos]=='(')||(in[tpos]==')'))) break; // Empty list ( ) of function arguments if ((o=='E') && ((in[tpos]=='(')||(in[tpos]==')'))) break; // Empty list ( ) of function arguments if ((o=='P') && ((in[tpos]=='(')||(in[tpos]==')'))) break; // Empty list ( ) of function arguments if ((o=='M') && ((in[tpos]=='[')||(in[tpos]==']'))) break; // Empty list [ ] is two tokens if ((o=='Q') && ((in[tpos]=='[')||(in[tpos]==']'))) break; // Empty list [ ] is two tokens if ((o=='N') && ((in[tpos]=='{')||(in[tpos]=='}'))) break; // Empty dictionary { } is two tokens } } // Clean up stack { int rightAssoc = 0; int precedence = 255; POP_STACK; } // If there are still brackets on the stack, we've failed if (stackpos!=0) { *errPos=0; *errType=ERR_INTERNAL; strcpy(errText, "Unexpected junk left on stack."); *end=-1; return; } // Store final return BYTECODE_OP(0); BYTECODE_ENDOP; (*outExpr)->bcLen = outpos * sizeof(pplExprBytecode); // Optimise gotos that point directly at other gotos { int optimised; do { int i; for (optimised=i=0 ; ; i+=*(int *)(out+i)) { int o = out[i].opcode; // Opcode number if ((o==17)||(o==18)) { int o2 = out[i ].flag; int to = out[i ].auxil.i; int to_o = out[to].opcode; // Opcode branching to int to_o2 = out[to].flag; if ((to_o!=17)&&(to_o!=18)) to_o2=-1; // this shouldn't be necessary, but optimisation of the below code makes valgrind unhappy if ((o==17)&&(o2==0)&&(to_o==17)&&(to_o2==0)) { out[i].auxil.i = out[to].auxil.i; optimised=1; } if ((o==18)&&(o2==0)&&(to_o==18)&&(to_o2==0)) { out[i].auxil.i = out[to].auxil.i; optimised=1; } if ((o==17) &&(to_o==19) ) { out[i].auxil.i = out[to].auxil.i; optimised=1; } if ((o==18) &&(to_o==19) ) { out[i].auxil.i = out[to].auxil.i; optimised=1; } } else if (o==0) break; } } while (optimised); } //ppl_reversePolishPrint(context, *outExpr); return; } // Debugging routine to produce a textual representation of reverse Polish bytecode void ppl_reversePolishPrint(ppl_context *context, pplExpr *expIn) { int j=0; char op[32],optype[32],arg[1024]; pplExprBytecode *in = expIn->bytecode; while (1) { int pos = j; // Position of start of instruction int len = in[j].len ; // length of bytecode instruction with data int charpos = in[j].charpos; // character position of token (for error reporting) int o = in[j].opcode ; // Opcode number switch (o) { case 0: strcpy (op, "return"); strcpy (optype, ""); strcpy (arg, ""); break; case 1: strcpy (op, "push"); strcpy (optype, "numeric"); sprintf(arg, "%.2e", in[j].auxil.d); break; case 2: strcpy (op, "push"); strcpy (optype, "string"); sprintf(arg, "\"%s\"", (char *)&(in[j+1])); break; case 3: strcpy (op, "lookup"); strcpy (optype, "value"); sprintf(arg, "\"%s\"", (char *)&(in[j+1])); break; case 4: strcpy (op, "lookup"); strcpy (optype, "pointer"); sprintf(arg, "\"%s\"", (char *)&(in[j+1])); break; case 5: strcpy (op, "deref"); strcpy (optype, "value"); sprintf(arg, "\"%s\"", (char *)&(in[j+1])); break; case 6: strcpy (op, "deref"); strcpy (optype, "pointer"); sprintf(arg, "\"%s\"", (char *)&(in[j+1])); break; case 7: { int f = in[j].auxil.i; strcpy (op, "slice"); strcpy (optype, "value"); if (f & 1) strcpy(arg, "[--]" ); else if ((f & 6)==6) strcpy(arg, "[--:--]"); else if ((f & 6)==4) strcpy(arg, "[--:]" ); else if ((f & 6)==2) strcpy(arg, "[:--]" ); else strcpy(arg, "[:]" ); break; } case 16: strcpy (op, "slice"); strcpy (optype, "pointer"); strcpy (arg, "[--]" ); break; case 8: strcpy (op, "make"); strcpy (optype, "dict"); sprintf(arg, "%d items", in[j].auxil.i); break; case 9: strcpy (op, "make"); strcpy (optype, "list"); sprintf(arg, "%d items", in[j].auxil.i); break; case 10: strcpy (op, "call"); strcpy (optype, ""); sprintf(arg, "%d args", in[j].auxil.i); break; case 11: { int t = in[j].auxil.i; strcpy (op, "op"); if (((t>>5)&3)==1) strcpy (optype, "unary"); else if (((t>>5)&3)==2) strcpy (optype, "binary"); else if (((t>>5)&3)==3) strcpy (optype, "ternary"); else strcpy (optype, "???"); if (t==0x25) strcpy (arg, "-" ); else if (t==0x26) strcpy (arg, "+" ); else if (t==0xA7) strcpy (arg, "~" ); else if (t==0xA8) strcpy (arg, "!" ); else if (t==0xC9) strcpy (arg, "**" ); else if (t==0x4A) strcpy (arg, "*" ); else if (t==0x4B) strcpy (arg, "/" ); else if (t==0x4C) strcpy (arg, "%" ); else if (t==0x4D) strcpy (arg, "+" ); else if (t==0x4E) strcpy (arg, "-" ); else if (t==0x4F) strcpy (arg, "<<" ); else if (t==0x50) strcpy (arg, ">>" ); else if (t==0x51) strcpy (arg, "<" ); else if (t==0x52) strcpy (arg, "<=" ); else if (t==0x53) strcpy (arg, ">=" ); else if (t==0x54) strcpy (arg, ">" ); else if (t==0x55) strcpy (arg, "==" ); else if (t==0x56) strcpy (arg, "!=" ); else if (t==0x57) strcpy (arg, "&" ); else if (t==0x58) strcpy (arg, "^" ); else if (t==0x59) strcpy (arg, "|" ); else if (t==0x5A) strcpy (arg, "&& (error: should have been replaced by an if)" ); else if (t==0x5B) strcpy (arg, "|| (error: should have been replaced by an if)" ); else if (t==0x5C) strcpy (arg, "swap-pop"); else if (t==0xFD) strcpy (arg, "? -- error: should have been compiled into a conditional" ); else if (t==0xFE) strcpy (arg, "?: -- error: should have been compiled into a conditional" ); else if (t==0x5F) strcpy (arg, "nop (collect -- error: should have been optimised out)" ); else strcpy (arg, "??? (error: unknown opcode)"); break; } case 12: { int t = in[j].auxil.i; strcpy (op, "op"); strcpy (optype, "assign"); if (t==0x40) strcpy (arg, "=" ); else if (t==0x41) strcpy (arg, "+=" ); else if (t==0x42) strcpy (arg, "-=" ); else if (t==0x43) strcpy (arg, "*=" ); else if (t==0x44) strcpy (arg, "/=" ); else if (t==0x45) strcpy (arg, "%=" ); else if (t==0x46) strcpy (arg, "&=" ); else if (t==0x47) strcpy (arg, "^=" ); else if (t==0x48) strcpy (arg, "|=" ); else if (t==0x49) strcpy (arg, "<<="); else if (t==0x4A) strcpy (arg, ">>="); else if (t==0x4B) strcpy (arg, "**="); else strcpy (arg, "???"); break; } case 13: { int t = in[j].auxil.i; strcpy (op, "op"); strcpy (optype, "unary"); if (t==0x21) { strcpy (arg, "-- (post-eval)"); } else if (t==0x22) { strcpy (arg, "++ (post-eval)"); } else if (t==0x23) { strcpy (arg, "-- (pre-eval)"); } else { strcpy (arg, "++ (pre-eval)"); } break; } case 14: strcpy (op, "op"); strcpy (optype, "binary"); sprintf(arg, "string subst (%d items)", in[j].auxil.i); break; case 15: strcpy (op, "op"); strcpy (optype, "unary"); strcpy (arg, "dollar -- column lookup"); break; case 17: strcpy (op, "branch if"); strcpy (optype, "false"); sprintf(arg, "to %d (%s)", in[j].auxil.i, in[j].flag ? "pop conditional" : "pop conditional; push FALSE on branch"); break; case 18: strcpy (op, "branch if"); strcpy (optype, "true"); sprintf(arg, "to %d (%s)", in[j].auxil.i, in[j].flag ? "pop conditional" : "pop conditional; push TRUE on branch"); break; case 19: strcpy (op, "branch"); strcpy (optype, "goto"); sprintf(arg, "%d", in[j].auxil.i); break; case 20: strcpy (op, "make"); strcpy (optype, "boolean"); strcpy (arg, ""); break; default: strcpy (op, "???"); strcpy (optype, ""); strcpy (arg, "Illegal opcode"); o=0; break; } sprintf(context->errcontext.tempErrStr,"%4d %4d %10s %10s %s",pos,charpos,op,optype,arg); ppl_report(&context->errcontext, NULL); if (o==0) break; j = pos+len; } return; } void pplExpr_free(pplExpr *inExpr) { if (inExpr==NULL) return; if ( __sync_sub_and_fetch(&inExpr->refCount,1) > 0) return; if (inExpr->ascii!=NULL) free(inExpr->ascii); if (inExpr->srcFname!=NULL) free(inExpr->srcFname); if (inExpr->bytecode!=NULL) free(inExpr->bytecode); free(inExpr); return; } pplExpr *pplExpr_cpy(pplExpr *i) { pplExpr *o; if (i==NULL) return NULL; o = (pplExpr *)malloc(sizeof(pplExpr)); if (o==NULL) return NULL; memcpy(o, i, sizeof(pplExpr)); o->refCount = 1; if (i->ascii !=NULL) { if ((o->ascii =malloc(strlen(i->ascii )+1))==NULL) return NULL; strcpy(o->ascii , i->ascii ); } if (i->srcFname!=NULL) { if ((o->srcFname=malloc(strlen(i->srcFname)+1))==NULL) return NULL; strcpy(o->srcFname, i->srcFname); } if (i->bytecode!=NULL) { if ((o->bytecode=malloc(i->bcLen ))==NULL) return NULL; memcpy(o->bytecode, i->bytecode, i->bcLen); } return o; } pplExpr *pplExpr_tmpcpy(pplExpr *i) { pplExpr *o; if (i==NULL) return NULL; o = (pplExpr *)ppl_memAlloc(sizeof(pplExpr)); if (o==NULL) return NULL; memcpy(o, i, sizeof(pplExpr)); o->refCount = 1; if (i->ascii !=NULL) { if ((o->ascii =ppl_memAlloc(strlen(i->ascii )+1))==NULL) return NULL; strcpy(o->ascii , i->ascii ); } if (i->srcFname!=NULL) { if ((o->srcFname=ppl_memAlloc(strlen(i->srcFname)+1))==NULL) return NULL; strcpy(o->srcFname, i->srcFname); } if (i->bytecode!=NULL) { if ((o->bytecode=ppl_memAlloc(i->bcLen ))==NULL) return NULL; memcpy(o->bytecode, i->bytecode, i->bcLen); } return o; } pyxplot-0.9.2/src/expressions/expEvalSlice.h0000664000175000017500000000220012026340554017524 0ustar dcf21dcf21// expEvalSlice.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expEvalSlice.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPEVALSLICE_H #define _EXPEVALSLICE_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_sliceItem (ppl_context *context, int getPtr, int *status, int *errType, char *errText); void ppl_sliceRange(ppl_context *context, int minset, int min, int maxset, int max, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/expressions/expCompile_fns.h0000664000175000017500000000321512026340554020122 0ustar dcf21dcf21// expCompile_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expCompile_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPCOMPILE_FNS_H #define _EXPCOMPILE_FNS_H 1 #include "expressions/expCompile.h" #include "userspace/context.h" void ppl_expTokenise (ppl_context *context, char *in, int *end, int dollarAllowed, int equalsAllowed, int allowCommaOperator, int collectCommas, int isDict, int outOffset, int *outlen, int *errPos, int *errType, char *errText); void ppl_tokenPrint (ppl_context *context, char *in, int len); void ppl_expCompile (ppl_context *context, int srcLineN, long srcId, char *srcFname, char *in, int *end, int dollarAllowed, int equalsAllowed, int allowCommaOperator, pplExpr **outexpr, int *errPos, int *errType, char *errText); void ppl_reversePolishPrint(ppl_context *context, pplExpr *expIn); void pplExpr_free (pplExpr *inExpr); pplExpr *pplExpr_cpy (pplExpr *i); pplExpr *pplExpr_tmpcpy (pplExpr *i); #endif pyxplot-0.9.2/src/expressions/traceback_fns.h0000664000175000017500000000223312026340554017733 0ustar dcf21dcf21// traceback_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: traceback_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _TRACEBACK_FNS_H #define _TRACEBACK_FNS_H 1 #include "expressions/traceback.h" #include "userspace/context.h" void ppl_tbClear (ppl_context *c); void ppl_tbAdd (ppl_context *c, int srcLineN, long srcId, char *srcFname, int cmdOrExpr, int errType, int errPos, char *linetext, char *context); void ppl_tbWrite (ppl_context *c); #endif pyxplot-0.9.2/src/expressions/dollarOp.c0000664000175000017500000001425212026340554016721 0ustar dcf21dcf21// dollarOp.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: dollarOp.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _DOLLAROP_C 1 #include #include #include #include #include #include #include "expressions/dollarOp.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "datafile.h" #include "pplConstants.h" #define TBADD(et) ppl_tbAdd(c,inExpr->srcLineN,inExpr->srcId,inExpr->srcFname,0,et,inExprCharPos,inExpr->ascii,"") #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[context->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(c->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL); goto cleanup; } \ } void ppl_dollarOp_config (ppl_context *c, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char *usingExpr, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits) { c->dollarStat.columns_str = columns_str; c->dollarStat.columns_val = columns_val; c->dollarStat.Ncols = Ncols; c->dollarStat.filename = filename; c->dollarStat.file_linenumber = file_linenumber; c->dollarStat.file_linenumbers = file_linenumbers; c->dollarStat.linenumber_count = linenumber_count; c->dollarStat.block_count = block_count; c->dollarStat.index_number = index_number; c->dollarStat.usingRowCol = usingRowCol; c->dollarStat.usingExpr = usingExpr; c->dollarStat.colHeads = colHeads; c->dollarStat.NcolHeads = NcolHeads; c->dollarStat.colUnits = colUnits; c->dollarStat.NcolUnits = NcolUnits; c->dollarStat.warntxt[0] = '\0'; return; } void ppl_dollarOp_deconfig(ppl_context *c) { c->dollarStat.columns_str = NULL; c->dollarStat.columns_val = NULL; c->dollarStat.Ncols = -1; c->dollarStat.filename = NULL; c->dollarStat.file_linenumber = -1; c->dollarStat.file_linenumbers = NULL; c->dollarStat.linenumber_count = -1; c->dollarStat.block_count = -1; c->dollarStat.index_number = -1; c->dollarStat.usingRowCol = -1; c->dollarStat.usingExpr = NULL; c->dollarStat.colHeads = NULL; c->dollarStat.NcolHeads = -1; c->dollarStat.colUnits = NULL; c->dollarStat.NcolUnits = -1; c->dollarStat.warntxt[0] = '\0'; return; } void ppl_dollarOp_fetchColByNum(ppl_context *c, pplExpr *inExpr, int inExprCharPos, int colNum) { pplObj *out = &c->stack[c->stackPtr-1]; pplObjNum(out, 0, 0, 0); out->refCount = 1; if ((colNum<-3)||(colNum>c->dollarStat.Ncols)) { sprintf(c->dollarStat.warntxt,"%s:%ld: In the expression <%s>, the requested %s number %d does not exist %son line %ld.", c->dollarStat.filename, c->dollarStat.file_linenumber, c->dollarStat.usingExpr, (c->dollarStat.usingRowCol==DATAFILE_COL)?"column":"row", colNum, (c->dollarStat.usingRowCol==DATAFILE_COL)?"":"in the block commencing ", c->dollarStat.file_linenumber); sprintf(c->errStat.errBuff,"No %s with number %d.", (c->dollarStat.usingRowCol==DATAFILE_COL)?"column":"row", colNum); TBADD(ERR_RANGE); return; } if (colNum==-3) out->real = c->dollarStat.file_linenumber; else if (colNum==-2) out->real = c->dollarStat.index_number; else if (colNum==-1) out->real = c->dollarStat.block_count; else if (c->dollarStat.columns_val != NULL) pplObjCpy(out, &c->dollarStat.columns_val[colNum], 0, 0, 1); else if (colNum== 0) out->real = c->dollarStat.linenumber_count; else { char *s = c->dollarStat.columns_str[colNum-1]; int j=-1; if ( (!ppl_validFloat(s,&j)) || (j<1) || ((s[j]!='\0')&&(s[j]!=',')&&(s[j-1]>' ')) ) { char *str; int j=0; while ((s[j]>' ')&&(s[j]!=',')) j++; str = (char *)malloc(j+1); if (str==NULL) return; strncpy(str, s, j); str[j] = '\0'; pplObjStr(out, 0, 1, str); } else { if ((colNum>0)&&(colNum<=c->dollarStat.NcolUnits)) { ppl_unitsDimCpy(out, &c->dollarStat.colUnits[colNum-1]); out->real = ppl_getFloat(s,&j) * c->dollarStat.colUnits[colNum-1].real; } else { out->real = ppl_getFloat(s,&j); } } } return; } void ppl_dollarOp_fetchColByName(ppl_context *c, pplExpr *inExpr, int inExprCharPos, char *colName) { int i; for (i=0; idollarStat.NcolHeads; i++) if (strcmp(colName, c->dollarStat.colHeads[i])==0) { ppl_dollarOp_fetchColByNum(c, inExpr, inExprCharPos, i); return; } sprintf(c->dollarStat.warntxt,"%s:%ld: In the expression <%s>, the requested %s named '%s' does not exist %son line %ld.", c->dollarStat.filename, c->dollarStat.file_linenumber, c->dollarStat.usingExpr, (c->dollarStat.usingRowCol==DATAFILE_COL)?"column":"row", colName, (c->dollarStat.usingRowCol==DATAFILE_COL)?"":"in the block commencing ", c->dollarStat.file_linenumber); sprintf(c->errStat.errBuff,"No %s with name '%s'.", (c->dollarStat.usingRowCol==DATAFILE_COL)?"column":"row", colName); TBADD(ERR_DICTKEY); return; } pyxplot-0.9.2/src/expressions/expCompile.h0000664000175000017500000000253312026340554017256 0ustar dcf21dcf21// expCompile.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: expCompile.h 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EXPCOMPILE_H #define _EXPCOMPILE_H 1 typedef struct pplExpr { int refCount; long srcId; int srcLineN; char *srcFname; char *ascii; void *bytecode; int bcLen; } pplExpr; typedef struct pplTokenCode { unsigned char state, opcode, precedence; unsigned int depth; } pplTokenCode; typedef struct pplExprPStack { unsigned char opType, opcode, precedence; int charpos, outpos; } pplExprPStack; typedef struct pplExprBytecode { int len, charpos, opcode; unsigned char flag; union { int i; double d; } auxil; } pplExprBytecode; #endif pyxplot-0.9.2/src/pyxplot.c0000664000175000017500000003031612026340554014301 0ustar dcf21dcf21// pyxplot.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pyxplot.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PYXPLOT_C 1 #include #include #include #include #include #include #include #include #ifdef HAVE_READLINE #include #include #endif #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "epsMaker/kpse_wrap.h" #include "canvasItems.h" #include "children.h" #include "input.h" #include "pplConstants.h" #include "settings/papersizes.h" #include "settings/settings_fns.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "settings/withWords_fns.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "pyxplot.h" #include "readConf.h" // SIGINT Handling information sigjmp_buf ppl_sigjmpToMain; sigjmp_buf *ppl_sigjmpFromSigInt = NULL; int main(int argc, char **argv) { int i,fail=0; int tempdirnumber = 1; char tempdirpath[FNAME_LENGTH]; char *EnvDisplay; ppl_context *context; struct stat statinfo; sigset_t sigs; struct timespec waitperiod, waitedperiod; // A time.h timespec specifier for a 50ms nanosleep wait waitperiod.tv_sec = 0; waitperiod.tv_nsec = 50000000; // Initialise sub-modules ppl_PaperSizeInit(); context = ppl_contextInit(); setenv("TZ","UTC",1); if (DEBUG) ppl_log(&context->errcontext,"Initialising Pyxplot."); if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Detected timezone <%s>.", context->set->term_default.timezone); ppl_log(&context->errcontext,NULL); } ppl_memAlloc_MemoryInit(&context->errcontext, &ppl_error, &ppl_log); if (!ppl_inputInit(context)) ppl_fatal(&context->errcontext, __FILE__, __LINE__, "Out of memory." ); ppltxt_init(); // Turn off GSL's automatic error handler gsl_set_error_handler_off(); // Initialise GNU Readline #ifdef HAVE_READLINE ppl_parseAutocompleteSetContext(context); // Tab completer needs to be able to access root-level context, even though rl doesn't pass it rl_readline_name = "Pyxplot"; // Allow conditional parsing of the ~/.inputrc file. rl_attempted_completion_function = ppl_rl_completion; // Tell the completer that we want a crack first. #endif // Set up command-line parser; do this BEFORE reading config files, which may contain a [script] section which needs parsing if (DEBUG) ppl_log(&context->errcontext,"Setting up command-line parser from RE++ definitions."); ppl_parserInit(context); // Set default terminal EnvDisplay = getenv("DISPLAY"); // Check whether the environment variable DISPLAY is set if (strcmp(GHOSTVIEW_COMMAND, "/bin/false")!=0) context->set->term_current.viewer = context->set->term_default.viewer = SW_VIEWER_GV; else if (strcmp(GGV_COMMAND , "/bin/false")!=0) context->set->term_current.viewer = context->set->term_default.viewer = SW_VIEWER_GGV; else context->set->term_current.viewer = context->set->term_default.viewer = SW_VIEWER_NULL; // Initialise settings and read configuration file; do this BEFORE processing command-line arguments which take precedence if (DEBUG) ppl_log(&context->errcontext,"Reading configuration file."); ppl_readconfig(context); // Scan command-line options for any switches for (i=1; iwillBeInteractive==1) context->willBeInteractive=0; continue; } if (strcmp(argv[i], "-q" )==0) context->errcontext.session_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "-quiet" )==0) context->errcontext.session_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "--quiet" )==0) context->errcontext.session_default.splash = SW_ONOFF_OFF; else if (strcmp(argv[i], "-V" )==0) context->errcontext.session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "-verbose" )==0) context->errcontext.session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "--verbose" )==0) context->errcontext.session_default.splash = SW_ONOFF_ON; else if (strcmp(argv[i], "-c" )==0) context->errcontext.session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-colour" )==0) context->errcontext.session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "--colour" )==0) context->errcontext.session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-color" )==0) context->errcontext.session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "--color" )==0) context->errcontext.session_default.color = SW_ONOFF_ON; else if (strcmp(argv[i], "-m" )==0) context->errcontext.session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "-mono" )==0) context->errcontext.session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "--mono" )==0) context->errcontext.session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "-monochrome" )==0) context->errcontext.session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "--monochrome")==0) context->errcontext.session_default.color = SW_ONOFF_OFF; else if (strcmp(argv[i], "-" )==0) context->willBeInteractive=2; else if ((strcmp(argv[i], "-v")==0) || (strcmp(argv[i], "-version")==0) || (strcmp(argv[i], "--version")==0)) { printf("%s\n",ppltxt_version); if (DEBUG) ppl_log(&context->errcontext,"Reported version number as requested."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 0; } else if ((strcmp(argv[i], "-h")==0) || (strcmp(argv[i], "-help")==0) || (strcmp(argv[i], "--help")==0)) { printf("%s\n",ppltxt_help); if (DEBUG) ppl_log(&context->errcontext,"Reported help text as requested."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 0; } else { sprintf(context->errcontext.tempErrStr, "Received switch '%s' which was not recognised. Type 'pyxplot -help' for a list of available command-line options.", argv[i]); ppl_error(&context->errcontext,ERR_PREFORMED, -1, -1, NULL); if (DEBUG) ppl_log(&context->errcontext,"Received unexpected command-line switch."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); return 1; } } // Revert default terminal to postscript if we can't access display if (!context->termtypeSetInConfigfile) { if ( (EnvDisplay==NULL) || (EnvDisplay[0]=='\0') || (context->set->term_default.viewer == SW_VIEWER_NULL) || (isatty(STDIN_FILENO) != 1) ) { if (DEBUG) ppl_log(&context->errcontext,"Detected that we are running a non-interactive session; defaulting to the EPS terminal."); context->set->term_current.TermType = context->set->term_default.TermType = SW_TERMTYPE_EPS; } else if (!context->willBeInteractive) { if (DEBUG) ppl_log(&context->errcontext,"Detected that we are running a non-interactive session; defaulting to the X11_persist terminal."); context->set->term_current.TermType = context->set->term_default.TermType = SW_TERMTYPE_X11P; } } // Decide upon a path for a temporary directory for us to live in if (DEBUG) ppl_log(&context->errcontext,"Finding a filepath for a temporary directory."); if (getcwd( context->errcontext.session_default.cwd , FNAME_LENGTH ) == NULL) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not read current working directory."); } // Store cwd while (1) { sprintf(tempdirpath, "/tmp/pyxplot_%d_%d", getpid(), tempdirnumber); if (access(tempdirpath, F_OK) != 0) break; tempdirnumber++; } // Find an unused dir path strcpy(context->errcontext.session_default.tempdir, tempdirpath); // Store our chosen temporary directory path // Launch child process if (DEBUG) ppl_log(&context->errcontext,"Launching the Child Support Process."); pplcsp_init(context); // Set program name within kpathsea ppl_kpse_wrap_init(context); // Set up SIGINT handler if (sigsetjmp(ppl_sigjmpToMain, 1) == 0) { ppl_sigjmpFromSigInt = &ppl_sigjmpToMain; if (signal(SIGINT, SIG_IGN)!=SIG_IGN) signal(SIGINT, ppl_sigIntHandle); signal(SIGPIPE, SIG_IGN); // Wait for temporary directory to appear, and change directory into it if (DEBUG) ppl_log(&context->errcontext,"Waiting for temporary directory to appear."); strcpy(tempdirpath, context->errcontext.session_default.tempdir); for (i=0; i<100; i++) { if (access(tempdirpath, F_OK) == 0) break; nanosleep(&waitperiod,&waitedperiod); } // Wait for temp dir to be created by child process if (access(tempdirpath, F_OK) != 0) { fail=1; } // If it never turns up, fail. else { stat(tempdirpath, &statinfo); // Otherwise stat it and make sure it's a directory we own if (!S_ISDIR(statinfo.st_mode)) fail=1; if (statinfo.st_uid != getuid()) fail=1; } if (fail==1) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Failed to create temporary directory." ); } // Read GNU Readline history #ifdef HAVE_READLINE if (DEBUG) ppl_log(&context->errcontext,"Reading GNU Readline history."); sprintf(tempdirpath, "%s%s%s", context->errcontext.session_default.homedir, PATHLINK, ".pyxplot_history"); read_history(tempdirpath); stifle_history(1000); #endif // Scan command line and process all script files we have been given for (i=1; iwillBeInteractive==1) ppl_interactiveSession(context); // SIGINT longjmps to main return here } else { sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); sigprocmask(SIG_UNBLOCK, &sigs, NULL); ppl_error(&context->errcontext,ERR_PREFORMED, -1, -1, "\nReceived SIGINT. Terminating."); } // Notify the CSP that we are about to quit pplcsp_sendCommand(context,"B\n"); // Free all of the plot styles which are set for (i=0; iset->plot_styles [i])); for (i=0; iset->plot_styles_default[i])); // Save GNU Readline history #ifdef HAVE_READLINE if (context->willBeInteractive>0) { if (DEBUG) ppl_log(&context->errcontext,"Saving GNU Readline history."); sprintf(tempdirpath, "%s%s%s", context->errcontext.session_default.homedir, PATHLINK, ".pyxplot_history"); write_history(tempdirpath); } #endif // Terminate ppl_directive_clear(context,NULL,NULL,0); if (signal(SIGCHLD, SIG_DFL) == SIG_ERR) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Main process could not unconfigure signal handler for SIGCHLD."); ppl_memAlloc_FreeAll(0); ppl_memAlloc_MemoryStop(); if (DEBUG) ppl_log(&context->errcontext,"Terminating normally."); ppl_contextFree(context); return 0; } void ppl_sigIntHandle(int signo) { sigjmp_buf *destination = ppl_sigjmpFromSigInt; ppl_sigjmpFromSigInt = NULL; // DO NOT recursively go back to the same sigint handler over and over again if it doesn't seem to work. if (destination != NULL) siglongjmp(*destination, 1); raise(SIGTERM); raise(SIGKILL); } pyxplot-0.9.2/src/canvasItems.h0000664000175000017500000001442112026340554015043 0ustar dcf21dcf21// canvasItems.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: canvasItems.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CANVASITEMS_H #define _CANVASITEMS_H 1 #include "coreUtils/dict.h" #include "datafile.h" #include "expressions/expCompile.h" #include "settings/arrows.h" #include "settings/labels.h" #include "settings/settings.h" #include "settings/withWords.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" #define CANVAS_ARROW 22001 #define CANVAS_BOX 22002 #define CANVAS_CIRC 22003 #define CANVAS_ELLPS 22004 #define CANVAS_EPS 22005 #define CANVAS_IMAGE 22006 #define CANVAS_PIE 22007 #define CANVAS_PLOT 22008 #define CANVAS_POINT 22009 #define CANVAS_POLYGON 22010 #define CANVAS_TEXT 22011 typedef struct canvas_plotrange { double min, max; pplObj unit; unsigned char MinSet, MaxSet; unsigned char AutoMinSet, AutoMaxSet; struct canvas_plotrange *next; } canvas_plotrange; typedef struct canvas_plotdesc { unsigned char function, parametric, TRangeSet, VRangeSet, axis1set, axis2set, axis3set, ContinuitySet, IndexSet, EverySet, TitleSet, NoTitleSet; int NFunctions, axis1xyz, axis2xyz, axis3xyz, axis1, axis2, axis3, index, continuity, UsingRowCols, NUsing; long EveryList[6]; withWords ww; char *filename, *title; pplObj *vectors; pplExpr **functions, *label, *SelectCriterion, **UsingList; pplObj Tmin, Tmax, Vmin, Vmax; struct canvas_plotdesc *next; // used with plot '-' and plot '--' to indicate that data is read only once; otherwise NULL dataTable *PersistentDataTable; // Structure members which are used at plot time dataTable *data; withWords ww_final; char *filenameFinal; char *TitleFinal; int TitleFinal_col; double TitleFinal_xpos, TitleFinal_ypos, TitleFinal_width, TitleFinal_height; pplObj CRangeUnit; unsigned char CRangeDisplay; double CMinFinal, CMaxFinal; pplset_axis C1Axis; int GridXSize, GridYSize; double PieChart_total; } canvas_plotdesc; typedef struct canvas_item { int id, type, ArrowType, TransColR, TransColG, TransColB; double xpos, ypos, xpos2, ypos2, rotation; char *text; pplExpr *format; unsigned char deleted, xpos2set, ypos2set, clip, calcbbox, smooth, NoTransparency, CustomTransparency; withWords with_data; pplset_graph settings; pplset_axis *XAxes, *YAxes, *ZAxes; pplarrow_object *arrow_list; ppllabel_object *label_list; struct canvas_item *next, *prev; // Parameters which can be used to define ellipses double x1,y1,x2,y2,xc,yc,xf,yf,a,b,ecc,slr,arcfrom,arcto; // Parameters which can be used to define ellipses unsigned char x1set, xcset, xfset, aset, bset, eccset, slrset, arcset; // Parameters which can be used to define polygons double *polygonPoints; int NpolygonPoints; // Parameters which can be used to define plots unsigned char ThreeDim; canvas_plotrange *plotranges; canvas_plotdesc *plotitems; dataTable **plotdata; // used at plot time double PlotLeftMargin, PlotRightMargin, PlotTopMargin, PlotBottomMargin; int FirstTextID, TitleTextID, LegendTextID, SetLabelTextID, *DatasetTextID; } canvas_item; typedef struct canvas_itemlist { canvas_item *first; canvas_item *last; } canvas_itemlist; int ppl_directive_clear (ppl_context *c, parserLine *pl, parserOutput *in, int interactive); char *ppl_canvas_item_textify(ppl_context *c, canvas_item *ptr, char *output); int ppl_directive_list (ppl_context *c, parserLine *pl, parserOutput *in, int interactive); int ppl_directive_delete (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_undelete(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_move (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_swap (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_arrow (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_box (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_circle (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_ellipse (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_eps (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_piechart(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_point (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_polygon (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_text (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_image (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); int ppl_directive_plot (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth, int replot); #endif pyxplot-0.9.2/src/userspace/0000775000175000017500000000000012026340554014405 5ustar dcf21dcf21pyxplot-0.9.2/src/userspace/pplObjFunc.c0000664000175000017500000001112412026340554016612 0ustar dcf21dcf21// pplObjFunc.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjFunc.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include "stdlib.h" #include "string.h" #ifdef HAVE_FFTW3 #include #else #include #endif #include "expressions/expCompile_fns.h" #include "parser/parser.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc_fns.h" void pplObjFuncDestroyChain(pplFunc *f) { pplFunc *next; while (f!=NULL) { next=f->next; pplObjFuncDestroy(f); f=next; } return; } void pplObjFuncDestroy(pplFunc *f) { int type = f->functionType; if ((type==PPL_FUNC_SYSTEM)||(type==PPL_FUNC_MAGIC)) return; // Never garbage collect system functions switch(type) { case PPL_FUNC_USERDEF: { pplExpr *e = (pplExpr *)f->functionPtr; f->functionPtr=NULL; if (e!=NULL) pplExpr_free(e); break; } case PPL_FUNC_SPLINE: { splineDescriptor *d = (splineDescriptor *)f->functionPtr; f->functionPtr=NULL; if (d!=NULL) { if (d->splineType[1]!='t') // Not stepwise interpolation { if (d->splineObj != NULL) gsl_spline_free (d->splineObj ); if (d->accelerator != NULL) gsl_interp_accel_free(d->accelerator); } else { if (d->splineObj != NULL) free(d->splineObj); } free(d); } break; } case PPL_FUNC_INTERP2D: case PPL_FUNC_BMPDATA: { splineDescriptor *d = (splineDescriptor *)f->functionPtr; f->functionPtr=NULL; if (d!=NULL) { if (d->splineObj != NULL) free(d->splineObj); free(d); } break; } case PPL_FUNC_HISTOGRAM: { histogramDescriptor *h = (histogramDescriptor *)f->functionPtr; f->functionPtr=NULL; if (h!=NULL) { if (h->bins != NULL ) free(h->bins ); if (h->binvals!= NULL ) free(h->binvals); free(h); } break; } case PPL_FUNC_FFT: { FFTDescriptor *d = (FFTDescriptor *)f->functionPtr; f->functionPtr=NULL; if (d!=NULL) { if (d->datagrid != NULL) fftw_free(d->datagrid); free(d); } break; } case PPL_FUNC_SUBROUTINE: { parserLine *s = (parserLine *)f->functionPtr; f->functionPtr=NULL; if (s!=NULL) ppl_parserLineFree(s); break; } } if (f->argList !=NULL) free(f->argList); if (f->min !=NULL) free(f->min); if (f->max !=NULL) free(f->max); if (f->minActive !=NULL) free(f->minActive); if (f->maxActive !=NULL) free(f->maxActive); free(f); return; } pplFunc *pplObjFuncCpy(pplFunc *f) { pplFunc *o; int i,j; int Nargs; if (f->functionType != PPL_FUNC_USERDEF) return NULL; Nargs=f->maxArgs; for (j=0,i=0;iargList[j++]!='\0'); if ((o = (pplFunc *)malloc(sizeof(pplFunc)))==NULL) return NULL; o->functionType = PPL_FUNC_USERDEF; o->minArgs = f->minArgs; o->maxArgs = f->maxArgs; if ((o->functionPtr = (void *)pplExpr_cpy((pplExpr *)f->functionPtr))==NULL) return NULL; if ((o->argList = (char *)malloc(j ))==NULL) return NULL; memcpy( o->argList , f->argList , j ); if ((o->min = (pplObj *)malloc(Nargs*sizeof(pplObj) ))==NULL) return NULL; memcpy( o->min , f->min , Nargs*sizeof(pplObj)); if ((o->max = (pplObj *)malloc(Nargs*sizeof(pplObj) ))==NULL) return NULL; memcpy( o->max , f->max , Nargs*sizeof(pplObj)); if ((o->minActive = (unsigned char *)malloc(Nargs ))==NULL) return NULL; memcpy( o->minActive , f->minActive , Nargs); if ((o->maxActive = (unsigned char *)malloc(Nargs ))==NULL) return NULL; memcpy( o->maxActive , f->maxActive , Nargs); o->next = NULL; o->description = NULL; o->descriptionShort = NULL; o->LaTeX = NULL; return o; } pyxplot-0.9.2/src/userspace/pplObjCmp.c0000664000175000017500000002332312026340554016442 0ustar dcf21dcf21// pplObjCmp.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjCmp.c 1266 2012-07-13 18:58:58Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "mathsTools/dcfmath.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjCmp.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" void pplcol_RGBtoHSB(double ri, double gi, double bi, double *ho, double *so, double *bo) { double M = ppl_max3(ri,gi,bi); double m = ppl_min3(ri,gi,bi); double C = M-m; if (C== 0) *ho = 0; else if (M==ri) *ho = fmod((gi-bi)/C , 6); else if (M==gi) *ho = (bi-ri)/C + 2; else *ho = (ri-gi)/C + 4; *ho /= 6.0; *so = C/M; *bo = M; if (!gsl_finite(*so)) *so=0; if (*ho<0) *ho=0; if (*ho>1) *ho=1; if (*so<0) *so=0; if (*so>1) *so=1; if (*bo<0) *bo=0; if (*bo>1) *bo=1; } void pplcol_CMYKtoRGB(double ci, double mi, double yi, double ki, double *ro, double *go, double *bo) { *ro = 1.0 - (ci+ki); *go = 1.0 - (mi+ki); *bo = 1.0 - (yi+ki); if (*ro<0) *ro=0; if (*ro>1) *ro=1; if (*go<0) *go=0; if (*go>1) *go=1; if (*bo<0) *bo=0; if (*bo>1) *bo=1; } void pplcol_HSBtoRGB(double hi, double si, double bi, double *ro, double *go, double *bo) { double ch = si*bi; double h2; int h2i = (int)(h2 = hi * 6); double x = ch*(1.0-fabs(fmod(h2,2)-1.0)); double m = bi - ch; switch (h2i) { case 0 : *ro=ch; *go=x ; *bo=0 ; break; case 1 : *ro=x ; *go=ch; *bo=0 ; break; case 2 : *ro=0 ; *go=ch; *bo=x ; break; case 3 : *ro=0 ; *go=x ; *bo=ch; break; case 4 : *ro=x ; *go=0 ; *bo=ch; break; case 5 : case 6 : *ro=ch; *go=0 ; *bo=x ; break; // case 6 is for hue=1.0 only default: *ro=0 ; *go=0 ; *bo=0 ; break; } *ro+=m; *go+=m; *bo+=m; if (*ro<0) *ro=0; if (*ro>1) *ro=1; if (*go<0) *go=0; if (*go>1) *go=1; if (*bo<0) *bo=0; if (*bo>1) *bo=1; } void pplcol_CMYKtoHSB(double ci, double mi, double yi, double ki, double *ho, double *so, double *bo) { double r,g,b; pplcol_CMYKtoRGB(ci,mi,yi,ki,&r,&g,&b); pplcol_RGBtoHSB(r,g,b,ho,so,bo); } void pplcol_RGBtoCMYK(double ri, double gi, double bi, double *co, double *mo, double *yo, double *ko) { *ko = 1.0 - ppl_max3(ri,gi,bi); *co = 1.0 - ri - *ko; *mo = 1.0 - gi - *ko; *yo = 1.0 - bi - *ko; if (*co<0) *co=0; if (*co>1) *co=1; if (*mo<0) *mo=0; if (*mo>1) *mo=1; if (*yo<0) *yo=0; if (*yo>1) *yo=1; if (*ko<0) *ko=0; if (*ko>1) *ko=1; } void pplcol_HSBtoCMYK(double hi, double si, double bi, double *co, double *mo, double *yo, double *ko) { double r,g,b; pplcol_HSBtoRGB(hi,si,bi,&r,&g,&b); pplcol_RGBtoCMYK(r,g,b,co,mo,yo,ko); } static int SGN(int x) { if (x==0) return 0; if (x< 0) return -1; return 1; } int pplObjCmpQuiet(const void *a, const void *b) { const pplObj *pa = *(pplObj **)a; const pplObj *pb = *(pplObj **)b; return pplObjCmp(NULL, pa, pb, NULL, NULL, NULL, 0); } int pplObjCmp(ppl_context *c, const pplObj *a, const pplObj *b, int *status, int *errType, char *errText, int iterDepth) { int t1 = a->objType; int t2 = b->objType; int t1o = pplObjTypeOrder[t1]; int t2o = pplObjTypeOrder[t2]; if (cancellationFlag) return 0; if (iterDepth>250) return 0; if ((c!=NULL)&&(t1o!=t2o)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Attempt to compare an object of type <%s> with an object of type <%s>.", pplObjTypeNames[t1], pplObjTypeNames[t2]); return -2; } if (t1o < t2o) return -1; if (t1o > t2o) return 1; if (t1o==0) return -2; // 0 - nulls are never equal if (t1o==2) // 2 - numbers or booleans { if (!ppl_unitsDimEqual(a,b)) { if (c==NULL) { int i; for (i=0; iexponent[i]exponent[i]) return -1; if (a->exponent[i]>b->exponent[i]) return 1; } } else { *status=1; *errType=ERR_UNIT; if (a->dimensionless) sprintf(errText, "Attempt to compare a quantity which is dimensionless with one with dimensions of <%s>.", ppl_printUnit(c,b,NULL,NULL,1,1,0)); else if (b->dimensionless) sprintf(errText, "Attempt to compare a quantity with dimensions of <%s> with one which is dimensionless.", ppl_printUnit(c,a,NULL,NULL,0,1,0)); else sprintf(errText, "Attempt to compare a quantity with dimensions of <%s> with one with dimensions of <%s>.", ppl_printUnit(c,a,NULL,NULL,0,1,0), ppl_printUnit(c,b,NULL,NULL,1,1,0)); return -2; } } if ((c!=NULL)&&(c->set->term_current.ComplexNumbers==SW_ONOFF_OFF)&&((a->flagComplex)||(b->flagComplex))) return -2; if ((!gsl_finite(a->real))||(!gsl_finite(a->imag))||(!gsl_finite(b->real))||(!gsl_finite(b->imag))) return -2; if (a->real < b->real) return -1; if (a->real > b->real) return 1; if (a->imag < b->imag) return -1; if (a->imag > b->imag) return 1; return 0; } else if (t1o==3) // 3 - dates { if (a->real real) return -1; if (a->real >b->real) return 1; if (a->real==b->real) return 0; return -2; } else if ((t1o==4)||(t1o==14)||(t1o==15)) // 4 - strings; 14 - data type; 15 - exception return SGN(strcmp((const char*)a->auxil,(const char*)b->auxil)); else if (t1o==5) // 5 - colors { double h1,s1,b1,h2,s2,b2; if (round(a->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoHSB (a->exponent[8],a->exponent[9],a->exponent[10],&h1,&s1,&b1); else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoHSB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&h1,&s1,&b1); else { h1=a->exponent[8]; s1=a->exponent[9]; b1=a->exponent[10]; } if (round(b->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoHSB (b->exponent[8],b->exponent[9],b->exponent[10],&h2,&s2,&b2); else if (round(b->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoHSB(b->exponent[8],b->exponent[9],b->exponent[10],b->exponent[11],&h2,&s2,&b2); else { h2=b->exponent[8]; s2=b->exponent[9]; b2=b->exponent[10]; } if ((!gsl_finite(h1))||(!gsl_finite(s1))||(!gsl_finite(b1))||(!gsl_finite(h2))||(!gsl_finite(s2))||(!gsl_finite(b2))) return -2; if (h1 < h2) return -1; if (h1 > h2) return 1; if (b1 < b2) return -1; if (b1 > b2) return 1; if (s1 < s2) return -1; if (s1 > s2) return 1; return 0; } else if (t1o==6) // 6 - vector { int i; gsl_vector *av = ((pplVector *)a->auxil)->v; gsl_vector *bv = ((pplVector *)b->auxil)->v; if (av->size < bv->size) return -1; if (av->size > bv->size) return 1; for (i=0; iexponent[i] < b->exponent[i]) return -1; if (a->exponent[i] > b->exponent[i]) return 1; } for (i=0; isize; i++) { if (gsl_vector_get(av,i) < gsl_vector_get(bv,i)) return -1; if (gsl_vector_get(av,i) > gsl_vector_get(bv,i)) return 1; } return 0; } else if (t1o==7) // 7 - list { int out; listIterator *lia, *lib; pplObj *oba, *obb; list *la = (list *)a->auxil; list *lb = (list *)b->auxil; if (la->length < lb->length) return -1; if (la->length > lb->length) return 1; lia = ppl_listIterateInit(la); lib = ppl_listIterateInit(lb); out = 0; while ( ((oba=ppl_listIterate(&lia))!=NULL) && ((obb=ppl_listIterate(&lib))!=NULL) && ((out=pplObjCmp(NULL,oba,obb,NULL,NULL,NULL,iterDepth+1))==0) ); return out; } else if (t1o==8) // 8 - matrix { int i,j; gsl_matrix *am = ((pplMatrix *)a->auxil)->m; gsl_matrix *bm = ((pplMatrix *)b->auxil)->m; if (am->size1*am->size2 < bm->size1*bm->size2) return -1; if (am->size1*am->size2 > bm->size1*bm->size2) return 1; for (i=0; iexponent[i] < b->exponent[i]) return -1; if (a->exponent[i] > b->exponent[i]) return 1; } for (i=0; isize1; i++) for (j=0; jsize2; j++) { if (gsl_matrix_get(am,i,j) < gsl_matrix_get(bm,i,j)) return -1; if (gsl_matrix_get(am,i,j) > gsl_matrix_get(bm,i,j)) return 1; } return 0; } else if ((t1o==9)||(t1o==10)||(t1o==11)) // 9 - dictionary; 10 - instance; 11 - module { int out; dictIterator *dia, *dib; pplObj *oba, *obb; char *keya, *keyb; dict *da = (dict *)a->auxil; dict *db = (dict *)b->auxil; if (da->length < db->length) return -1; if (da->length > db->length) return 1; dia = ppl_dictIterateInit(da); dib = ppl_dictIterateInit(db); out = 0; while ( ((oba=ppl_dictIterate(&dia,&keya))!=NULL) && ((obb=ppl_dictIterate(&dib,&keyb))!=NULL) && ((out=SGN(strcmp(keya,keyb)))==0) && ((out=pplObjCmp(NULL,oba,obb,NULL,NULL,NULL,iterDepth+1))==0) ); return out; } else if ((t1o==12)||(t1o==13)) // 12 - function; 13 - file handle { if (a->auxil < b->auxil) return -1; if (a->auxil > b->auxil) return -1; return 0; } return -2; } pyxplot-0.9.2/src/userspace/unitsArithmetic.h0000664000175000017500000000370612026340554017740 0ustar dcf21dcf21// unitsArithmetic.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: unitsArithmetic.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_UNITSARITH_H #define _PPL_UNITSARITH_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_unitsDimCpy(pplObj *o, const pplObj *i); void ppl_unitsDimInverse(pplObj *o, const pplObj *i); int ppl_unitsDimEqual(const pplObj *a, const pplObj *b); int ppl_unitsDimEqual2(const pplObj *a, const unit *b); int ppl_unitsDimEqual3(const unit *a, const unit *b); unsigned char ppl_tempTypeMatch(unsigned char a, unsigned char b); void ppl_uaPow(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); void ppl_uaMul(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); void ppl_uaDiv(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); void ppl_uaAdd(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); void ppl_uaSub(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); void ppl_uaMod(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText); #endif pyxplot-0.9.2/src/userspace/pplObjUnits.h0000664000175000017500000000352712026340554017036 0ustar dcf21dcf21// pplObjUnits.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjUnits.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJUNITS_H #define _PPLOBJUNITS_H 1 #define UNITS_MAX_BASEUNITS 24 #define UNITS_MAX 1024 #define UNIT_LENGTH 0 #define UNIT_TIME 1 #define UNIT_MASS 2 #define UNIT_CURRENT 3 #define UNIT_TEMPERATURE 4 #define UNIT_MOLE 5 #define UNIT_ANGLE 6 #define UNIT_BIT 7 #define UNIT_COST 8 #define UNIT_FIRSTUSER 9 typedef struct unit { char *nameAs, *nameAp, *nameLs, *nameLp, *nameFs, *nameFp, *alt1, *alt2, *alt3, *alt4, *comment, *quantity; double multiplier, offset; unsigned char si, cgs, imperial, us, planck, ancient, userSel, notToBeCompounded, modified, tempType; int maxPrefix; int minPrefix; int userSelPrefix; double exponent[UNITS_MAX_BASEUNITS]; } unit; #include "userspace/pplObj.h" typedef struct PreferredUnit { int NUnits; int UnitID[UNITS_MAX_BASEUNITS]; int prefix[UNITS_MAX_BASEUNITS]; double exponent[UNITS_MAX_BASEUNITS]; pplObj value; unsigned char modified; } PreferredUnit; #endif pyxplot-0.9.2/src/userspace/calendars.h0000664000175000017500000000501312026340554016511 0ustar dcf21dcf21// calendars.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: calendars.h 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CALENDARS_H #define _CALENDARS_H 1 #include "userspace/context.h" void ppl_switchOverCalDate (ppl_context *ct, double *LastJulian, double *FirstGregorian); double ppl_switchOverJD (ppl_context *ct); char *ppl_getMonthName (ppl_context *ct, int i); char *ppl_getWeekDayName (ppl_context *ct, int i); void ppl_getHebrewNewYears (ppl_context *ct, int GregYear, int *YearNumbers, double *JDs, int *YearTypes); double ppl_hebrewToUnixTime (ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText); void ppl_hebrewFromUnixTime (ppl_context *ct, double UT, int *year, int *month, int *day, int *status, char *errText); double ppl_islamicToUnixTime (ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText); void ppl_islamicFromUnixTime(ppl_context *ct, double UT, int *year, int *month, int *day, int *status, char *errText); double ppl_toUnixTime (ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText); void ppl_fromUnixTime (ppl_context *ct, double UT, int *year, int *month, int *day, int *hour, int *min, double *sec, int *status, char *errText); void ppl_dateString (ppl_context *ct, char *out, double UT, const char *format, const char *timezone, int *status, char *errText); void ppl_timeDiffStr (ppl_context *ct, char *out, double UT1, double UT2, const char *format, int *status, char *errText); void ppl_calendarTimezoneSet (ppl_context *ct, int specified, char *tz); void ppl_calendarTimezoneUnset (ppl_context *ct); void ppl_calendarTimezoneOffset (ppl_context *ct, double unixTime, char *tzNameOut, double *offset); #endif pyxplot-0.9.2/src/userspace/unitsDisp.c0000664000175000017500000007233112026340554016541 0ustar dcf21dcf21// unitsDisp.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: unitsDisp.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_UNITSDISP_C 1 #include #include #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjUnits.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" const char *SIprefixes_full [] = {"yocto","zepto","atto","femto","pico","nano","micro","milli","","kilo","mega","giga","tera","peta","exa","zetta","yotta"}; const char *SIprefixes_abbrev[] = {"y","z","a","f","p","n","u","m","","k","M","G","T","P","E","Z","Y"}; const char *SIprefixes_latex [] = {"y","z","a","f","p","n","\\upmu ","m","","k","M","G","T","P","E","Z","Y"}; // NB: The LaTeX upmu character is defined by the {upgreek} package // Display a value with units and format string char *ppl_unitsNumericDisplayWithFormat(ppl_context *c, pplObj *in, int N, char *formatString, char formatChar, int maxLen, int requiredArgs, int arg1i, int arg2i) { double numberOutReal, numberOutImag; char *output, *unitstr; int i=0, done=0, intArg=0; if (N==0) output = c->udNumDispA; else output = c->udNumDispB; if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in->flagComplex!=0)) { strcpy(output, "nan"); return output; } unitstr = ppl_printUnit(c, in, &numberOutReal, &numberOutImag, N, 1, 0); if ((formatChar=='d') || (formatChar=='i') || (formatChar=='o')) { if ((numberOutReal>INT_MAX)||(numberOutImag>INT_MAX)) { strcpy(output+i, "inf"); done=1; } else if ((numberOutRealUINT_MAX)||(numberOutImag>UINT_MAX)) { strcpy(output+i, "inf"); done=1; } else if ((numberOutReal<0 )||(numberOutImag<0 )) { strcpy(output+i, "-inf"); done=1; } intArg=2; } if (done) { i+=strlen(output+i); } else if (((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in->flagComplex!=0)) || (!gsl_finite(numberOutReal)) || (!gsl_finite(numberOutImag))) { strcpy(output+i, "nan"); i+=strlen(output+i); } else { if (in->flagComplex) output[i++] = '('; // open brackets on complex number #define PRINTFORM(X) \ { \ if (intArg==0) \ { \ if (requiredArgs==1) snprintf(output+i, maxLen-i-4, formatString, X); /* Print a double (real part) */ \ if (requiredArgs==2) snprintf(output+i, maxLen-i-4, formatString, arg1i, X); \ if (requiredArgs==3) snprintf(output+i, maxLen-i-4, formatString, arg1i, arg2i, X); \ } \ else if (intArg==1) \ { \ int xi = (int)X; \ if (requiredArgs==1) snprintf(output+i, maxLen-i-4, formatString, xi); /* Print an integer */ \ if (requiredArgs==2) snprintf(output+i, maxLen-i-4, formatString, arg1i, xi); \ if (requiredArgs==3) snprintf(output+i, maxLen-i-4, formatString, arg1i, arg2i, xi); \ } \ else if (intArg==2) \ { \ unsigned int xi = (unsigned int)X; \ if (requiredArgs==1) snprintf(output+i, maxLen-i-4, formatString, xi); /* Print an unsigned integer */ \ if (requiredArgs==2) snprintf(output+i, maxLen-i-4, formatString, arg1i, xi); \ if (requiredArgs==3) snprintf(output+i, maxLen-i-4, formatString, arg1i, arg2i, xi); \ } \ } PRINTFORM(numberOutReal); i+=strlen(output+i); if (in->flagComplex) { output[i++] = '+'; PRINTFORM(numberOutImag); i+=strlen(output+i); output[i++] = 'i'; output[i++] = ')'; // close brackets on complex number } } if (unitstr[0]!='\0') { snprintf(output+i, maxLen-i, " %s", unitstr); i+=strlen(output+i); // Add unit string as required } output[i++] = '\0'; // null terminate string return output; } // Display a value with units char *ppl_unitsNumericDisplay(ppl_context *c, pplObj *in, int N, int typeable, int NSigFigs) { double numberOutReal, numberOutImag, OoM; char *output, *unitstr; int i=0; if (N==0) output = c->udNumDispA; else output = c->udNumDispB; if (NSigFigs <= 0) NSigFigs = c->set->term_current.SignificantFigures; // If number of significant figures not specified, use user-selected number if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in->flagComplex!=0)) return ppl_numericDisplay(GSL_NAN, c->numdispBuff[N], NSigFigs, (typeable==SW_DISPLAY_L)); if (typeable==0) typeable = c->set->term_current.NumDisplay; unitstr = ppl_printUnit(c, in, &numberOutReal, &numberOutImag, N, 1, typeable); if (((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) && (in->flagComplex!=0)) || (!gsl_finite(numberOutReal)) || (!gsl_finite(numberOutImag))) { if (typeable == SW_DISPLAY_L) output[i++] = '$'; strcpy(output+i, ppl_numericDisplay(GSL_NAN, c->numdispBuff[N], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(output+i); } else { OoM = hypot(numberOutReal , numberOutImag) * pow(10 , -NSigFigs); if (typeable == SW_DISPLAY_L) output[i++] = '$'; if ((fabs(numberOutReal) >= OoM) && (fabs(numberOutImag) > OoM)) output[i++] = '('; // open brackets on complex number if (fabs(numberOutReal) >= OoM) { strcpy(output+i, ppl_numericDisplay(numberOutReal, c->numdispBuff[N], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(output+i); } if ((fabs(numberOutReal) >= OoM) && (fabs(numberOutImag) > OoM) && (numberOutImag > 0)) output[i++] = '+'; if (fabs(numberOutImag) > OoM) { if (fabs(numberOutImag-1.0)>=OoM) // If this is false, imaginary part is 1, so print +i, not +1i { if (fabs(numberOutImag+1.0)>=OoM) { strcpy(output+i, ppl_numericDisplay(numberOutImag, c->numdispBuff[N], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(output+i); } else { output[i++]='-'; } // Just print -i, not -1i } if (typeable != SW_DISPLAY_T) { output[i++] = 'i'; } else if ((fabs(numberOutImag-1.0)>=OoM)&&(fabs(numberOutImag+1.0)>=OoM)) { strcpy(output+i, "*sqrt(-1)"); i+=strlen(output+i); } else { strcpy(output+i, "sqrt(-1)"); i+=strlen(output+i); } // We've not printed 1 or -1, so nothing to multiply with } if ((fabs(numberOutReal) >= OoM) && (fabs(numberOutImag) > OoM)) output[i++] = ')'; // close brackets on complex number } if (unitstr[0]!='\0') { if (typeable == SW_DISPLAY_N) output[i++] = ' '; else if (typeable == SW_DISPLAY_L) { output[i++] = '\\'; output[i++] = ','; } sprintf(output+i, "%s", unitstr); i+=strlen(output+i); // Add unit string as required } if (typeable == SW_DISPLAY_L) output[i++] = '$'; output[i++] = '\0'; // null terminate string return output; } // ------------------------------------------------------------------- // Routines for printing units // ------------------------------------------------------------------- #define UNIT_INSCHEME(X) ( ((X).si && (c->set->term_current.UnitScheme == SW_UNITSCH_SI )) \ || ((X).cgs && (c->set->term_current.UnitScheme == SW_UNITSCH_CGS )) \ || ((X).imperial && (c->set->term_current.UnitScheme == SW_UNITSCH_IMP )) \ || ((X).us && (c->set->term_current.UnitScheme == SW_UNITSCH_US )) \ || ((X).planck && (c->set->term_current.UnitScheme == SW_UNITSCH_PLK )) \ || ((X).ancient && (c->set->term_current.UnitScheme == SW_UNITSCH_ANC )) ) void ppl_udFindOptimalNextUnit(ppl_context *c, pplObj *in, unsigned char first, unit **best, double *pow) { int i,j,k,score,found=0,BestScore=0; double power; for (i=0; iunit_pos; i++) { if (!ppl_tempTypeMatch(in->tempType, c->unit_database[i].tempType)) continue; // Don't convert between different temperature units for (j=0; junit_database[i].exponent[j] == 0) || (in->exponent[j]==0) ) continue; power = in->exponent[j] / c->unit_database[i].exponent[j]; score = 0; for (k=0; kexponent[k] , power*c->unit_database[i].exponent[k])) score++; if (c->unit_database[i].notToBeCompounded && ((!first) || (scoreunit_database+i; *pow = power; BestScore = score; found = 1; } // A user-preferred unit always beats a non-user-preferred unit if ( (score >= BestScore) && ( (c->unit_database[i].userSel)) && (!((*best)->userSel)) ) { *best = c->unit_database+i; *pow = power; BestScore = score; continue; } if ( (score <= BestScore ) &&(!(c->unit_database[i].userSel)) && ( ((*best)->userSel)) ) continue; // A unit in the current scheme always beats one not in current scheme if (( UNIT_INSCHEME(c->unit_database[i])) && (!UNIT_INSCHEME(**best))) { *best = c->unit_database+i; *pow = power; BestScore = score; continue; } if ((!UNIT_INSCHEME(c->unit_database[i])) && ( UNIT_INSCHEME(**best))) continue; // A unit which matches more dimensions wins if (score > BestScore) { *best = c->unit_database+i; *pow = power; BestScore = score; continue; } if ((score == BestScore) && (ppl_dblEqual(fabs(power), 1.0) && (!ppl_dblEqual(fabs(*pow), 1.0))) ) { *best = c->unit_database+i; *pow = power; continue; } if ((score == BestScore) && (ppl_dblEqual(power, 1.0) && (!ppl_dblEqual(*pow, 1.0))) ) { *best = c->unit_database+i; *pow = power; continue; } if (score < BestScore) continue; } } if (found==0) {*pow = 0; *best = NULL; return;} for (j=0; jexponent[j] -= (*pow) * (*best)->exponent[j]; } return; } void ppl_udPrefixFix(ppl_context *c, pplObj *in, unit **UnitList, double *UnitPow, int *UnitPref, int Nunits) { int i,j; double NewValueReal, NewValueImag, PrefixBestVal, NewMagnitude, OldMagnitude; int PrefixBestPos, BestPrefix=0; // Apply unit multipliers to the value we're going to display for (i=0; ireal /= pow(UnitList[i]->multiplier , UnitPow[i]); in->imag /= pow(UnitList[i]->multiplier , UnitPow[i]); UnitPref[i]=0; } // Search for alternative dimensionally-equivalent units which give a smaller value for (i=0; iunit_pos; j++) if (ppl_tempTypeMatch(UnitList[i]->tempType, c->unit_database[j].tempType) && (ppl_unitsDimEqual3(UnitList[i] , c->unit_database + j))) { OldMagnitude = hypot(in->real , in->imag); NewValueReal = in->real * pow(UnitList[i]->multiplier / c->unit_database[j].multiplier , UnitPow[i]); NewValueImag = in->imag * pow(UnitList[i]->multiplier / c->unit_database[j].multiplier , UnitPow[i]); NewMagnitude = hypot(NewValueReal , NewValueImag); // A user-preferred unit always beats a non-user-preferred unit if ( ( (c->unit_database[j].userSel)) && (!(UnitList[i]->userSel)) ) { UnitList[i] = c->unit_database+j; in->real = NewValueReal; in->imag = NewValueImag; continue; } if ( (!(c->unit_database[j].userSel)) && ( (UnitList[i]->userSel)) ) continue; // A unit in the current scheme always beats one which is not if (( UNIT_INSCHEME(c->unit_database[j])) && (!UNIT_INSCHEME(*(UnitList[i])))) { UnitList[i] = c->unit_database+j; in->real = NewValueReal; in->imag = NewValueImag; continue; } if ((!UNIT_INSCHEME(c->unit_database[j])) && ( UNIT_INSCHEME(*(UnitList[i])))) continue; // Otherwise, a unit with a smaller display value wins if ((NewMagnitude < OldMagnitude) && (NewMagnitude >= 1)) { UnitList[i] = c->unit_database+j; in->real = NewValueReal; in->imag = NewValueImag; } } // Apply unit multiplier which arise from user-preferred SI prefixes, for example, millimetres for (i=0; iuserSel) { in->real /= pow(10,(UnitList[i]->userSelPrefix-8)*3 * UnitPow[i]); in->imag /= pow(10,(UnitList[i]->userSelPrefix-8)*3 * UnitPow[i]); UnitPref[i] = UnitList[i]->userSelPrefix-8; } // Search for an SI prefix we can use to reduce the size of this number if (c->set->term_current.UnitDisplayPrefix == SW_ONOFF_ON) { OldMagnitude = hypot(in->real , in->imag); PrefixBestPos = -1; PrefixBestVal = OldMagnitude; for (i=0; iuserSel == 0) for (j=UnitList[i]->minPrefix; j<=UnitList[i]->maxPrefix; j+=3) { NewMagnitude = OldMagnitude / pow(10,j); if ( (NewMagnitude >= 1) && ((NewMagnitude < PrefixBestVal) || (PrefixBestVal<1)) ) { PrefixBestPos = i; BestPrefix = j; PrefixBestVal = NewMagnitude; } } if (PrefixBestPos>=0) { in->real /= pow(10,BestPrefix); in->imag /= pow(10,BestPrefix); UnitPref[PrefixBestPos] = BestPrefix/3; } } return; } // Main entry point for printing units char *ppl_printUnit(ppl_context *c, const pplObj *in, double *numberOutReal, double *numberOutImag, int N, int DivAllowed, int typeable) { char *output,*temp; pplObj residual=*in; unit *UnitList[UNITS_MAX_BASEUNITS]; double UnitPow [UNITS_MAX_BASEUNITS]; int UnitPref[UNITS_MAX_BASEUNITS]; unsigned char UnitDisp[UNITS_MAX_BASEUNITS]; double ExpMax=0; int pos=0, OutputPos=0; int i, j=0, k, l, found, first; listIterator *listiter; PreferredUnit *pu; if (typeable==0) typeable = c->set->term_current.NumDisplay; if (N==0) output = c->udBuffA; else if (N==1) output = c->udBuffB; else output = c->udBuffC; // Check whether input value is dimensionally equal to any preferred units listiter = ppl_listIterateInit(c->unit_PreferredUnits); while (listiter != NULL) { pu = (PreferredUnit *)listiter->data; if (ppl_unitsDimEqual(&pu->value , in) && (in->tempType == pu->value.tempType)) break; // Preferred unit matches dimensions ppl_listIterate(&listiter); } if (listiter != NULL) // Found a preferred unit to use { for (i=0; iNUnits; i++) { UnitList[i] = c->unit_database + pu->UnitID[i]; UnitPow [i] = pu->exponent[i]; UnitPref[i] = (pu->prefix[i]>=0) ? pu->prefix[i]-8 : 0; UnitDisp[i] = 0; } pos = pu->NUnits; residual.real /= pu->value.real; residual.imag /= pu->value.real; for (i=0; idimensionless != 0) { output[0]='\0'; if (numberOutReal != NULL) *numberOutReal = in->real; if (numberOutImag != NULL) *numberOutImag = in->imag; return output; } // Find a list of units which multiply together to match dimensions of quantity to display while (1) { if (pos>=UNITS_MAX_BASEUNITS) { ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, "Overflow whilst trying to display a unit."); break; } ppl_udFindOptimalNextUnit(c, &residual, pos==0, UnitList + pos, UnitPow + pos); UnitDisp[pos] = 0; if (ppl_dblEqual(UnitPow[pos],0)!=0) break; pos++; } // Go through list of units and fix prefixes / unit choice to minimise displayed number ppl_udPrefixFix(c, &residual, UnitList, UnitPow, UnitPref, pos); } // Display units one by one first = 1; while (1) { found = 0; for (i=0; iExpMax))) { ExpMax=UnitPow[i]; found=1; j=i; } if (found==0) break; if ((typeable==SW_DISPLAY_T) && first) { strcpy(output+OutputPos, "*unit("); OutputPos+=strlen(output+OutputPos); } if (!first) // Print * or / { if ((!DivAllowed) || (UnitPow[j] > 0) || (ppl_dblEqual(UnitPow[j],0))) { if (typeable==SW_DISPLAY_L) { output[OutputPos++] = '\\'; output[OutputPos++] = ','; } else output[OutputPos++] = '*'; } else { output[OutputPos++] = '/'; } } if (typeable==SW_DISPLAY_L) { strcpy(output+OutputPos, "\\mathrm{"); OutputPos+=strlen(output+OutputPos); } if (UnitPref[j] != 0) // Print SI prefix { if (c->set->term_current.UnitDisplayAbbrev == SW_ONOFF_ON) { if (typeable!=SW_DISPLAY_L) strcpy(output+OutputPos, SIprefixes_abbrev[UnitPref[j]+8]); else strcpy(output+OutputPos, SIprefixes_latex [UnitPref[j]+8]); } else { strcpy(output+OutputPos, SIprefixes_full [UnitPref[j]+8]); } OutputPos+=strlen(output+OutputPos); } if (c->set->term_current.UnitDisplayAbbrev == SW_ONOFF_ON) { if (typeable!=SW_DISPLAY_L) { if (UnitPow[j] >= 0) strcpy(output+OutputPos, UnitList[j]->nameAp); // Use abbreviated name for unit else strcpy(output+OutputPos, UnitList[j]->nameAs); } else { if (UnitPow[j] >= 0) strcpy(output+OutputPos, UnitList[j]->nameLp); // Use abbreviated LaTeX name for unit else strcpy(output+OutputPos, UnitList[j]->nameLs); } } else { if (UnitPow[j] >= 0) temp = UnitList[j]->nameFp; // Use full name for unit... else temp = UnitList[j]->nameFs; if (typeable!=SW_DISPLAY_L) { strcpy(output+OutputPos, temp); } // ... either as it comes else { for (k=l=0;temp[k]!='\0';k++) { if (temp[k]=='_') output[OutputPos+(l++)]='\\'; // ... or with escaped underscores for LaTeX output[OutputPos+(l++)]=temp[k]; } output[OutputPos+(l++)]='\0'; } } OutputPos+=strlen(output+OutputPos); if (typeable==SW_DISPLAY_L) { output[OutputPos++]='}'; } if ( ((first||(!DivAllowed)) && (!ppl_dblEqual(UnitPow[j],1))) || (((!first)||DivAllowed) && (!ppl_dblEqual(fabs(UnitPow[j]),1))) ) // Print power { if (typeable==SW_DISPLAY_L) { output[OutputPos++]='^'; output[OutputPos++]='{'; } else { output[OutputPos++]='*'; output[OutputPos++]='*'; } if ((first)||(!DivAllowed)) sprintf(output+OutputPos, "%s", ppl_numericDisplay( UnitPow[j] , c->numdispBuff[N], c->set->term_current.SignificantFigures, (typeable==SW_DISPLAY_L))); else sprintf(output+OutputPos, "%s", ppl_numericDisplay(fabs(UnitPow[j]), c->numdispBuff[N], c->set->term_current.SignificantFigures, (typeable==SW_DISPLAY_L))); OutputPos+=strlen(output+OutputPos); if (typeable==SW_DISPLAY_L) { output[OutputPos++]='}'; } } UnitDisp[j] = 1; first = 0; } // Clean up and return if (typeable==SW_DISPLAY_T) output[OutputPos++] = ')'; output[OutputPos] = '\0'; if (numberOutReal != NULL) *numberOutReal = residual.real; if (numberOutImag != NULL) *numberOutImag = residual.imag; return output; } // ------------------------------------------------ // Function to evaluate strings of the form "m/s" // ------------------------------------------------ int ppl_unitNameCmp(const char *in, const char *unit, const unsigned char caseSensitive) { int k; if (unit==NULL) return 0; if (caseSensitive) for (k=0; ((unit[k]!='\0') && ( unit[k] == in[k] )); k++); else for (k=0; ((unit[k]!='\0') && (toupper(unit[k])==toupper(in[k]))); k++); if ((unit[k]=='\0') && (!(isalnum(in[k]) || (in[k]=='_')))) return k; return 0; } void ppl_unitsStringEvaluate(ppl_context *c, char *in, pplObj *out, int *end, int *errpos, char *errText) { int i=0,j=0,k,l,m,p; double power=1.0, powerneg=1.0, multiplier; pplObjNum(out,out->amMalloced,0.0,0.0); while ((in[i]<=' ')&&(in[i]!='\0')) i++; out->real = ppl_getFloat(in+i , &j); // Unit strings can have numbers out the front if (j<0) j=0; i+=j; if (j==0) { out->real = 1.0; } else { while ((in[i]<=' ')&&(in[i]!='\0')) i++; if (in[i]=='*') i++; else if (in[i]=='/') { i++; powerneg=-1.0; } } while (powerneg!=0.0) { p=0; while ((in[i]<=' ')&&(in[i]!='\0')) i++; for (j=0; junit_pos; j++) { multiplier = 1.0; if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].nameAp,1))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].nameAs,1))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].nameFs,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].alt1 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].alt2 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].alt3 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(in+i, c->unit_database[j].alt4 ,0))!=0) p=1; else { for (l=c->unit_database[j].minPrefix/3+8; l<=c->unit_database[j].maxPrefix/3+8; l++) { if (l==8) continue; for (k=0; ((SIprefixes_full[l][k]!='\0') && (toupper(SIprefixes_full[l][k])==toupper(in[i+k]))); k++); if (SIprefixes_full[l][k]=='\0') { if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].nameFp,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].nameFs,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].alt1 ,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].alt2 ,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].alt3 ,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].alt4 ,0))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } } for (k=0; ((SIprefixes_abbrev[l][k]!='\0') && (SIprefixes_abbrev[l][k]==in[i+k])); k++); if (SIprefixes_abbrev[l][k]=='\0') { if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].nameAp,1))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } else if ((m = ppl_unitNameCmp(in+i+k, c->unit_database[j].nameAs,1))!=0) { p=1; k+=m; multiplier=pow(10,(l-8)*3); break; } } } } if (p==0) continue; i+=k; while ((in[i]<=' ')&&(in[i]!='\0')) i++; if (((in[i]=='^') && (i++,1)) || (((in[i]=='*') && (in[i+1]=='*')) && (i+=2,1))) { power = ppl_getFloat(in+i,&k); if (k<=0) { *errpos=i; strcpy(errText, "Syntax Error: Was expecting a numerical constant here."); return; } i+=k; while ((in[i]<=' ')&&(in[i]!='\0')) i++; } if (c->unit_database[j].tempType != 0) { if ((out->tempType >0) && (out->tempType!=c->unit_database[j].tempType)) { *errpos=i; strcpy(errText, "Unit Error: Attempt to mix Kelvin, oC and oF in the units of a single quantity. Try again with all quantities converted into Kelvin. Type 'help units temperatures' for more details."); return; } out->tempType = c->unit_database[j].tempType; } for (k=0; kexponent[k] += c->unit_database[j].exponent[k] * power * powerneg; if (ppl_dblEqual(out->exponent[UNIT_TEMPERATURE], 0)) out->tempType = 0; // We've lost our temperature dependence out->real *= pow( multiplier * c->unit_database[j].multiplier , power*powerneg ); power = 1.0; if (in[i]=='*') { powerneg= 1.0; i++; } else if (in[i]=='/') { powerneg=-1.0; i++; } else { powerneg= 0.0; } break; } if (p==0) { if ((in[i]==')') || (in[i]=='\0')) { powerneg=0.0; } else { *errpos=i; strcpy(errText, "No such unit."); return; } } } j=1; for (k=0; kexponent[k], 0) == 0) j=0; out->dimensionless = j; if (end != NULL) *end=i; return; } // Function for making preferred unit structures void ppl_newPreferredUnit(ppl_context *c, PreferredUnit **output, char *instr, int OutputContext, int *errpos, char *errText) { int end, outpos, PrefixOut, i, j, k, l, m, p; double power=1.0, powerneg=1.0; pplObj UnitVal; *output = NULL; *errpos = -1; end = strlen(instr); ppl_unitsStringEvaluate(c, instr, &UnitVal, &end, errpos, errText); if (*errpos>=0) return; // Error in parsing unit expression *output = (PreferredUnit *)malloc(sizeof(PreferredUnit)); if (*output==NULL) { errpos=0; sprintf(errText, "Out of memory."); return; } (*output)->value = UnitVal; (*output)->modified = 1; // Read list of units from preferred unit string outpos=i=0; while ((powerneg!=0.0) && (outposunit_pos; j++) { if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].nameAp,1))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].nameAs,1))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].nameFs,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].alt1 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].alt2 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].alt3 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(instr+i, c->unit_database[j].alt4 ,0))!=0) p=1; else { for (l=c->unit_database[j].minPrefix/3+8; l<=c->unit_database[j].maxPrefix/3+8; l++) { if (l==8) continue; for (k=0; ((SIprefixes_full[l][k]!='\0') && (toupper(SIprefixes_full[l][k])==toupper(instr[i+k]))); k++); if (SIprefixes_full[l][k]=='\0') { if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].nameFp,0))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].nameFs,0))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].alt1 ,0))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].alt2 ,0))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].alt3 ,0))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].alt4 ,0))!=0) { p=1; k+=m; PrefixOut=l; break; } } for (k=0; ((SIprefixes_abbrev[l][k]!='\0') && (SIprefixes_abbrev[l][k]==instr[i+k])); k++); if (SIprefixes_abbrev[l][k]=='\0') { if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].nameAp,1))!=0) { p=1; k+=m; PrefixOut=l; break; } else if ((m = ppl_unitNameCmp(instr+i+k, c->unit_database[j].nameAs,1))!=0) { p=1; k+=m; PrefixOut=l; break; } } } } if (p==0) continue; i+=k; while ((instr[i]<=' ')&&(instr[i]!='\0')) i++; if (((instr[i]=='^') && (i++,1)) || (((instr[i]=='*') && (instr[i+1]=='*')) && (i+=2,1))) { power = ppl_getFloat(instr+i,&k); if (k<=0) { *errpos=i; strcpy(errText, "Syntax Error: Was expecting a numerical constant here."); return; } i+=k; while ((instr[i]<=' ')&&(instr[i]!='\0')) i++; } (*output)->UnitID [outpos] = j; (*output)->prefix [outpos] = PrefixOut; (*output)->exponent[outpos] = power*powerneg; outpos++; power = 1.0; if (instr[i]=='*') { powerneg= 1.0; i++; } else if (instr[i]=='/') { powerneg=-1.0; i++; } else { powerneg= 0.0; } break; } if (p==0) { if ((instr[i]==')') || (instr[i]=='\0')) { powerneg=0.0; } else { *errpos=i; strcpy(errText, "No such unit."); return; } } } (*output)->NUnits = outpos; return; } pyxplot-0.9.2/src/userspace/context.h0000664000175000017500000000646512026340554016255 0ustar dcf21dcf21// context.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: context.h 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CONTEXT_H #define _CONTEXT_H 1 #include "settings/settings.h" #include "stringTools/strConstants.h" #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "coreUtils/errorReport.h" #include "expressions/traceback.h" #include "pplConstants.h" typedef struct dollarStatus { char **columns_str; pplObj *columns_val; int Ncols; char *filename; long file_linenumber; long *file_linenumbers; long linenumber_count; long block_count; long index_number; int usingRowCol; char *usingExpr; // Used for error reporting only char **colHeads; int NcolHeads; pplObj *colUnits; int NcolUnits; char warntxt[LSTR_LENGTH]; char lastFilename[FNAME_LENGTH]; } dollarStatus; typedef struct ppl_context_struc { // Shell status int willBeInteractive; char *inputLineBuffer; int inputLineBufferLen; char *inputLineAddBuffer; int shellBreakable, shellReturnable, shellBreakLevel; int shellExiting, shellBroken, shellContinued, shellReturned; char *shellLoopName[MAX_RECURSION_DEPTH+8]; pplObj shellReturnVal; long int historyNLinesWritten; int termtypeSetInConfigfile; int replotFocus; int algebraErrPos; // CSP status char pplcsp_ghostView_fname[FNAME_LENGTH]; // Code position to report when ppl_error() is called pplerr_context errcontext; // traceback errStatus errStat; // dollar operator status dollarStatus dollarStat; // Buffers for parsing and evaluating expressions pplTokenCode *tokenBuff; int tokenBuffLen; pplExprPStack *parserStack; int parserStackLen; pplObj *stack; int stackSize, stackFull; int stackPtr; // Settings ppl_settings *set; // Units settings unit *unit_database; int unit_pos; int baseunit_pos; list *unit_PreferredUnits; list *unit_PreferredUnits_default; double tempTypeMultiplier[8]; // These are filled in by ppl_userspace_init.c double tempTypeOffset [8]; // They store the offsets and multiplier for each of the units of temperature // Buffers used by ppl_printUnit() char udBuffA[LSTR_LENGTH], udBuffB[LSTR_LENGTH], udBuffC[LSTR_LENGTH]; char udNumDispA[LSTR_LENGTH], udNumDispB[LSTR_LENGTH]; char numdispBuff[4][128]; // Namespace hierarchy int ns_ptr , ns_branch; dict *namespaces[CONTEXT_DEPTH]; // canvas void *canvas_items; } ppl_context; ppl_context *ppl_contextInit(); void ppl_contextFree(ppl_context *in); #endif pyxplot-0.9.2/src/userspace/pplObjMethods.c0000664000175000017500000032236212026340554017333 0ustar dcf21dcf21// pplObjMethods.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjMethods.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPLOBJMETHODS_C 1 #include #include #include #include #include #include "gsl/gsl_blas.h" #include "gsl/gsl_eigen.h" #include "gsl/gsl_linalg.h" #include "gsl/gsl_math.h" #include "gsl/gsl_matrix.h" #include "gsl/gsl_permutation.h" #include "gsl/gsl_vector.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "defaultObjs/defaultFuncs.h" #include "defaultObjs/defaultFuncsMacros.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "expressions/fnCall.h" #include "mathsTools/dcfmath.h" #include "userspace/calendars.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjCmp.h" #include "userspace/pplObjDump.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjMethods.h" #include "userspace/pplObjPrint.h" #include "userspace/pplObjUnits.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" dict **pplObjMethods; #define COPYSTR(X,Y) \ { \ X = (char *)malloc(strlen(Y)+1); \ if (X==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } \ strcpy(X, Y); \ } #define STACK_POP_LISTMETHOD \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { fprintf(stderr,"Stack forward reference detected."); } \ } #define TBADD_LISTMETHOD(et) ppl_tbAdd(c,dummy.srcLineN,dummy.srcId,dummy.srcFname,0,et,0,dummy.ascii,"") // Universal methods of all objects static void pplmethod_class(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; if (t==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,t->objPrototype,0,0,1); OUTPUT.self_lval = NULL; } static void pplmethod_data(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int count=0; char *keys[4096] , *key , *tmp; pplObj v; pplObj *st = in[-1].self_this; pplObj *iter = in[-1].self_this; int t = iter->objType; pplObj *item; list *l; dictIterator *di; if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; for ( ; (t==PPLOBJ_MOD)||(t==PPLOBJ_USER) ; iter=iter->objPrototype , t=iter->objType ) { di = ppl_dictIterateInit((dict *)iter->auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; iobjType==PPLOBJ_FUNC) continue; // Non-methods only COPYSTR(tmp,key); pplObjStr(&v,1,1,tmp); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); keys[count++]=key; if (count>4094) break; } } di = ppl_dictIterateInit( pplObjMethods[st->objType] ); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; iobjType==PPLOBJ_FUNC) continue; // Non-methods only COPYSTR(tmp,key); pplObjStr(&v,1,1,tmp); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); keys[count++]=key; if (count>4094) break; } } static void pplmethod_contents(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int count=0; char *keys[4096] , *key , *tmp; pplObj v; pplObj *st = in[-1].self_this; pplObj *iter = in[-1].self_this; int t = iter->objType; pplObj *item; list *l; dictIterator *di; if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; for ( ; (t==PPLOBJ_MOD)||(t==PPLOBJ_USER) ; iter=iter->objPrototype , t=iter->objType ) { di = ppl_dictIterateInit((dict *)iter->auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; i4094) break; } } di = ppl_dictIterateInit( pplObjMethods[st->objType] ); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; i4094) break; } } static void pplmethod_methods(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int count=0; char *keys[4096] , *key , *tmp; pplObj v; pplObj *st = in[-1].self_this; pplObj *iter = in[-1].self_this; int t = iter->objType; pplObj *item; list *l; dictIterator *di; if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; for ( ; (t==PPLOBJ_MOD)||(t==PPLOBJ_USER) ; iter=iter->objPrototype , t=iter->objType ) { di = ppl_dictIterateInit((dict *)iter->auxil); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; iobjType!=PPLOBJ_FUNC) continue; // List methods only COPYSTR(tmp,key); pplObjStr(&v,1,1,tmp); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); keys[count++]=key; if (count>4094) break; } } di = ppl_dictIterateInit( pplObjMethods[st->objType] ); while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { int i,new=1; for (i=0; iobjType!=PPLOBJ_FUNC) continue; // List methods only COPYSTR(tmp,key); pplObjStr(&v,1,1,tmp); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); keys[count++]=key; if (count>4094) break; } } static void pplmethod_str(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *tmp = (char *)malloc(LSTR_LENGTH); if (tmp==NULL) { *status=1; sprintf(errText,"Out of memory."); return; } pplObjPrint(c,t,NULL,tmp,LSTR_LENGTH,0,0); pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_type(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; if (t==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,&pplObjPrototypes[t->objType],0,0,1); OUTPUT.self_lval = NULL; } // String methods static void pplmethod_strUpper(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i=0; pplObj *t = in[-1].self_this; char *tmp, *work=(char *)t->auxil; COPYSTR(tmp, work); while (tmp[i]!='\0') { tmp[i] = toupper(tmp[i]); i++; } pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_strLower(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i=0; pplObj *t = in[-1].self_this; char *tmp, *work=(char *)t->auxil; COPYSTR(tmp, work); while (tmp[i]!='\0') { tmp[i] = tolower(tmp[i]); i++; } pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_strSplit(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *instr = (char *)t->auxil; int i,j; list *lst; if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } lst = (list *)OUTPUT.auxil; for (i=0,j=0 ; ; i++) if ((instr[i]<=' ')&&(instr[i]>='\0')) { if (jauxil; int i,j; list *lst; for (i=0; i.",i+1,pplObjTypeNames[in[i].objType]); return; } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } lst = (list *)OUTPUT.auxil; for (i=0,j=0 ; ; i++) { int breaking = (instr[i]=='\0'); int k,l=0; for (k=0; ((kauxil; COPYSTR(tmp, work); for (i=0; ((tmp[i]>'\0')&&(tmp[i]<=' ')); i++); for (j=0; tmp[i]!='\0'; i++,j++) tmp[j]=tmp[i]; j--; for ( ; ((j>=0)&&(tmp[j]>'\0')&&(tmp[j]<=' ')); j--) tmp[j]='\0'; tmp[j+1]='\0'; pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_strLStrip(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i=0,j=0; pplObj *t = in[-1].self_this; char *tmp, *work=(char *)t->auxil; COPYSTR(tmp, work); for (i=0; ((tmp[i]>'\0')&&(tmp[i]<=' ')); i++); for (j=0; tmp[i]!='\0'; i++,j++) tmp[j]=tmp[i]; tmp[j]='\0'; pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_strRStrip(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i=0,j=0; pplObj *t = in[-1].self_this; char *tmp, *work=(char *)t->auxil; COPYSTR(tmp, work); for (j=0; tmp[i]!='\0'; i++,j++) tmp[j]=tmp[i]; j--; for ( ; ((j>=0)&&(tmp[j]>'\0')&&(tmp[j]<=' ')); j--) tmp[j]='\0'; tmp[j+1]='\0'; pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_strisalpha(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *s = (char *)t->auxil; int i, l=strlen(s), out=1; for (i=0; iauxil; int i, l=strlen(s), out=1; for (i=0; iauxil; int i, l=strlen(s), out=1; for (i=0; iauxil, *astr; int alen; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The append() method requires a single string argument."); return; } if ((t==NULL)||(t->self_lval==NULL)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The append() method can only be called on a string lvalue."); return; } if ((t->immutable)||(t->self_lval->immutable)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The append() method cannot act on immutable strings."); return; } t = t->self_lval; astr = (char *)in[0].auxil; alen = strlen(astr); if (in[0].auxilMalloced) { int ilen = t->auxilLen - 1; int newlen = t->auxilLen + alen; instr = (char *)realloc(t->auxil, newlen); if (instr==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } t->auxilLen = newlen; strcpy(instr+ilen, astr); } else { int ilen = strlen(instr); int newlen = ilen + alen + 1; char *ns = (char *)malloc(newlen); if (ns==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } t->auxilLen = newlen; sprintf(ns, "%s%s", instr, astr); instr = ns; } t->auxil = (void *)instr; pplObjCpy(&OUTPUT,t,0,0,1); } static void pplmethod_strBeginsWith(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *instr = (char *)t->auxil, *cmpstr; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The beginsWith() method requires a single string argument."); return; } cmpstr = (char *)in[0].auxil; pplObjBool(&OUTPUT,0,strncmp(instr,cmpstr,strlen(cmpstr))==0); } static void pplmethod_strEndsWith(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *instr = (char *)t->auxil, *cmpstr; int il, cl; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The endsWith() method requires a single string argument."); return; } cmpstr = (char *)in[0].auxil; il = strlen(instr); cl = strlen(cmpstr); instr += il-cl; if (ilauxil, *cmpstr; int il, cl, pmax, p; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The find() method requires a single string argument."); return; } cmpstr = (char *)in[0].auxil; il = strlen(instr); cl = strlen(cmpstr); pmax = il-cl; for (p=0; p<=pmax; p++) if (strncmp(instr+p,cmpstr,cl)==0) { pplObjNum(&OUTPUT,0,p,0); return; } pplObjNum(&OUTPUT,0,-1,0); } static void pplmethod_strFindAll(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *instr = (char *)t->auxil, *cmpstr; int il, cl, pmax, p; pplObj v; list *l; if ((nArgs!=1)||(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The findAll() method requires a single string argument."); return; } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; cmpstr = (char *)in[0].auxil; il = strlen(instr); cl = strlen(cmpstr); pmax = il-cl; for (p=0; p<=pmax; p++) if (strncmp(instr+p,cmpstr,cl)==0) { pplObjNum(&v,1,p,0); ppl_listAppendCpy(l, &v, sizeof(v)); } } static void pplmethod_strLen(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; char *instr = (char *)t->auxil; pplObjNum(&OUTPUT,0,strlen(instr),0); } // Date methods #define TZ_INIT \ double offset; \ { \ if ((nArgs>0)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } \ if (nArgs>0) ppl_calendarTimezoneSet(c, 1, (char*)in[0].auxil); \ else ppl_calendarTimezoneSet(c, 0, NULL ); \ ppl_calendarTimezoneOffset(c, t->real, NULL, &offset); \ ppl_calendarTimezoneUnset(c); \ } static void pplmethod_dateToDayOfMonth(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toDayOfMonth()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,day,0); } static void pplmethod_dateToDayWeekName(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toDayWeekName()"; pplObj *t = in[-1].self_this; char *tmp; TZ_INIT; COPYSTR(tmp , ppl_getWeekDayName(c, floor( fmod((t->real+offset)/3600/24+3 , 7)))); pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_dateToDayWeekNum(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toDayWeekNum()"; pplObj *t = in[-1].self_this; TZ_INIT; pplObjNum(&OUTPUT,0,floor( fmod((t->real+offset)/3600/24+4 , 7))+1,0); } static void pplmethod_dateToHour(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toHour()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,hour,0); } static void pplmethod_dateToJD(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; pplObjNum(&OUTPUT,0, t->real / 86400.0 + 2440587.5 ,0); } static void pplmethod_dateToMinute(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toMinute()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,day,0); } static void pplmethod_dateToMJD(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; pplObjNum(&OUTPUT,0, t->real / 86400.0 + 40587.0 ,0); } static void pplmethod_dateToMonthName(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toMonthName()"; int year, month, day, hour, minute; double second; char *tmp; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } COPYSTR(tmp, ppl_getMonthName(c,month)); pplObjStr(&OUTPUT,0,1,tmp); } static void pplmethod_dateToMonthNum(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toMonthNum()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,month,0); } static void pplmethod_dateToSecond(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toSecond()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,second,0); } static void pplmethod_dateToStr(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "str(,)"; pplObj *t = in[-1].self_this; char *format=NULL, *out=NULL, timezone[FNAME_LENGTH]; double offset; if ((nArgs>0)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its first argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } if ((nArgs>1)&&(in[1].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function %s requires a string as its second argument; supplied argument had type <%s>.", FunctionDescription, pplObjTypeNames[in[1].objType]); return; } out = (char *)malloc(8192); if (out==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } if (nArgs>0) format = (char *)in[0].auxil; // Format specified else format = NULL; // Format not specified if (nArgs>1) ppl_calendarTimezoneSet(c, 1, (char*)in[1].auxil); else ppl_calendarTimezoneSet(c, 0, NULL ); ppl_calendarTimezoneOffset(c, t->real, timezone, &offset); ppl_dateString(c, out, t->real+offset, format, timezone, status, errText); ppl_calendarTimezoneUnset(c); if (*status) { *errType=ERR_NUMERICAL; return; } pplObjStr(&OUTPUT,0,1,out); } static void pplmethod_dateToUnix(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *t = in[-1].self_this; pplObjNum(&OUTPUT,0,t->real,0); } static void pplmethod_dateToYear(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "toYear()"; int year, month, day, hour, minute; double second; pplObj *t = in[-1].self_this; TZ_INIT; ppl_fromUnixTime(c,t->real+offset,&year,&month,&day,&hour,&minute,&second,status,errText); if (*status) { *errType=ERR_RANGE; return; } pplObjNum(&OUTPUT,0,year,0); } // Color methods static void pplmethod_colCompRGB(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double r,g,b; gsl_vector *v; if (round(a->exponent[0])==SW_COLSPACE_RGB ) { r=a->exponent[8]; g=a->exponent[9]; b=a->exponent[10]; } else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&r,&g,&b); else pplcol_HSBtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],&r,&g,&b); pplObjVector(&OUTPUT,0,1,3); v = ((pplVector *)OUTPUT.auxil)->v; gsl_vector_set(v,0,r); gsl_vector_set(v,1,g); gsl_vector_set(v,2,b); } static void pplmethod_colCompCMYK(ppl_context *dummy, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double c,m,y,k; gsl_vector *v; if (round(a->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoCMYK(a->exponent[8],a->exponent[9],a->exponent[10],&c,&m,&y,&k); else if (round(a->exponent[0])==SW_COLSPACE_CMYK) { c=a->exponent[8]; m=a->exponent[9]; y=a->exponent[10]; k=a->exponent[11]; } else pplcol_HSBtoCMYK(a->exponent[8],a->exponent[9],a->exponent[10],&c,&m,&y,&k); pplObjVector(&OUTPUT,0,1,4); v = ((pplVector *)OUTPUT.auxil)->v; gsl_vector_set(v,0,c); gsl_vector_set(v,1,m); gsl_vector_set(v,2,y); gsl_vector_set(v,2,k); } static void pplmethod_colCompHSB(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double h,s,b; gsl_vector *v; if (round(a->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoHSB (a->exponent[8],a->exponent[9],a->exponent[10],&h,&s,&b); else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoHSB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&h,&s,&b); else { h=a->exponent[8]; s=a->exponent[9]; b=a->exponent[10]; } pplObjVector(&OUTPUT,0,1,3); v = ((pplVector *)OUTPUT.auxil)->v; gsl_vector_set(v,0,h); gsl_vector_set(v,1,s); gsl_vector_set(v,2,b); } static void pplmethod_colToRGB(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double r,g,b; if (round(a->exponent[0])==SW_COLSPACE_RGB ) { r=a->exponent[8]; g=a->exponent[9]; b=a->exponent[10]; } else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&r,&g,&b); else pplcol_HSBtoRGB(a->exponent[8],a->exponent[9],a->exponent[10],&r,&g,&b); pplObjColor(&OUTPUT,0,SW_COLSPACE_RGB,r,g,b,0); } static void pplmethod_colToCMYK(ppl_context *dummy, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double c,m,y,k; if (round(a->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoCMYK(a->exponent[8],a->exponent[9],a->exponent[10],&c,&m,&y,&k); else if (round(a->exponent[0])==SW_COLSPACE_CMYK) { c=a->exponent[8]; m=a->exponent[9]; y=a->exponent[10]; k=a->exponent[11]; } else pplcol_HSBtoCMYK(a->exponent[8],a->exponent[9],a->exponent[10],&c,&m,&y,&k); pplObjColor(&OUTPUT,0,SW_COLSPACE_CMYK,c,m,y,k); } static void pplmethod_colToHSB(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *a = in[-1].self_this; double h,s,b; if (round(a->exponent[0])==SW_COLSPACE_RGB ) pplcol_RGBtoHSB (a->exponent[8],a->exponent[9],a->exponent[10],&h,&s,&b); else if (round(a->exponent[0])==SW_COLSPACE_CMYK) pplcol_CMYKtoHSB(a->exponent[8],a->exponent[9],a->exponent[10],a->exponent[11],&h,&s,&b); else { h=a->exponent[8]; s=a->exponent[9]; b=a->exponent[10]; } pplObjColor(&OUTPUT,0,SW_COLSPACE_HSB,h,s,b,0); } // Vector methods static void pplmethod_vectorAppend(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i; pplObj *st = in[-1].self_this; gsl_vector *v = ((pplVector *)st->auxil)->v; gsl_vector *vo; if (!ppl_unitsDimEqual(st, &in[0])) { if (st->dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", ppl_printUnit(c, &in[0], NULL, NULL, 1, 1, 0) ); } else if (in[0].dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[0], NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if (pplObjVector(&OUTPUT,0,1,v->size+1)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(OUTPUT.auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo , i , gsl_vector_get(v,i)); gsl_vector_set(vo, i, in[0].real); ppl_unitsDimCpy(&OUTPUT,st); if (st->self_lval!=NULL) { pplObj *o = st->self_lval; int om=o->amMalloced; int rc=o->refCount; o->amMalloced=0; o->refCount=1; ppl_garbageObject(o); o->refCount=rc; pplObjCpy(o,&OUTPUT,0,om,1); } } static void pplmethod_vectorExtend(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i,l=0; pplObj *st = in[-1].self_this; gsl_vector *va = ((pplVector *)st->auxil)->v; gsl_vector *vo; int t = in[0].objType; if (t==PPLOBJ_VEC) { if (!ppl_unitsDimEqual(st, &in[0])) { if (st->dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", ppl_printUnit(c, &in[0], NULL, NULL, 1, 1, 0) ); } else if (in[0].dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[0], NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } l = ((pplVector *)in[0].auxil)->v->size; } else if (t==PPLOBJ_LIST) { l = ((list *)in[0].auxil)->length; } else { *status=1; *errType=ERR_TYPE; sprintf(errText, "Argument to the extend(x) method must be either a list or a vector. Supplied argument had type <%s>.", pplObjTypeNames[t]); return; } if (pplObjVector(&OUTPUT,0,1,va->size+l)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(OUTPUT.auxil))->v; for (i=0; isize; i++) gsl_vector_set(vo , i , gsl_vector_get(va,i)); ppl_unitsDimCpy(&OUTPUT,st); if (t==PPLOBJ_VEC) { int j; gsl_vector *vi = ((pplVector *)in[0].auxil)->v; for (j=0; jsize; j++,i++) gsl_vector_set(vo, i, gsl_vector_get(vi,j)); } else if (t==PPLOBJ_LIST) { list *listin = (list *)in[0].auxil; listIterator *li = ppl_listIterateInit(listin); pplObj *item; while ((item = (pplObj*)ppl_listIterate(&li))!=NULL) { if (item->objType!=PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Can only append numbers to vectors; supplied object has type <%s>.",pplObjTypeNames[item->objType]); return; } if (!ppl_unitsDimEqual(st, item)) { if (st->dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", ppl_printUnit(c, item, NULL, NULL, 1, 1, 0) ); } else if (item->dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0), ppl_printUnit(c, item, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if (item->flagComplex) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Can only append real numbers to vectors; supplied value is complex."); return; } gsl_vector_set(vo, i++, item->real); } } if (st->self_lval!=NULL) { pplObj *o = st->self_lval; int om=o->amMalloced; int rc=o->refCount; o->amMalloced=0; o->refCount=1; ppl_garbageObject(o); o->refCount=rc; pplObjCpy(o,&OUTPUT,0,om,1); } } static void pplmethod_vectorFilter(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { ppl_context *context = c; char *FunctionDescription = "filter(f)"; pplObj *st = in[-1].self_this; gsl_vector *va = ((pplVector *)st->auxil)->v; gsl_vector *vo; double *ovec; int ovlen=0, i=0; pplObj v; pplFunc *fi; pplExpr dummy; STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } ovec = (double *)malloc(va->size * sizeof(double)); if (ovec==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; pplObjNum(&v,0,0,0); v.refCount = 1; ppl_unitsDimCpy(&v, st); for (i=0; isize; i++) { const int stkLevelOld = c->stackPtr; // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push a v.real = gsl_vector_get(va,i); pplObjCpy(&c->stack[c->stackPtr], &v, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); free(ovec); return; } CAST_TO_BOOL(&c->stack[c->stackPtr-1]); if (c->stack[c->stackPtr-1].real) ovec[ovlen++] = v.real; while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } if (pplObjVector(&OUTPUT,0,1,ovlen)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); free(ovec); return; } vo = ((pplVector *)(OUTPUT.auxil))->v; for (i=0; iauxil)->v; gsl_vector *vo; if (in[0].objType!=PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "First argument to the insert(n,x) method must be a number. Supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } if (in[0].flagComplex) { *status=1; *errType=ERR_TYPE; sprintf(errText, "First argument to the insert(n,x) method must be a real number. Supplied argument is complex."); return; } if (in[0].real < 0) in[0].real += v->size+1; p = (long)round(in[0].real); if (p<0) { *status=1; *errType=ERR_RANGE; sprintf(errText, "Attempt to insert a vector item before the beginning of a vector."); return; } if (p>v->size) { *status=1; *errType=ERR_RANGE; sprintf(errText, "Vector index out of range."); return; } if (!ppl_unitsDimEqual(st, &in[1])) { if (st->dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", ppl_printUnit(c, &in[1], NULL, NULL, 1, 1, 0) ); } else if (in[1].dimensionless) { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to append a number to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", ppl_printUnit(c, st, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &in[1], NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } if (pplObjVector(&OUTPUT,0,1,v->size+1)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplVector *)(OUTPUT.auxil))->v; gsl_vector_set(vo, p, in[1].real); for (i=0; isize; i++) gsl_vector_set(vo , i+(i>=p) , gsl_vector_get(v,i)); ppl_unitsDimCpy(&OUTPUT,st); if (st->self_lval!=NULL) { pplObj *o = st->self_lval; int om=o->amMalloced; int rc=o->refCount; o->amMalloced=0; o->refCount=1; ppl_garbageObject(o); o->refCount=rc; pplObjCpy(o,&OUTPUT,0,om,1); } } static void pplmethod_vectorLen(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { gsl_vector *v = ((pplVector *)in[-1].self_this->auxil)->v; pplObjNum(&OUTPUT,0,v->size,0); } static void pplmethod_vectorList(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; gsl_vector *vec = ((pplVector *)st->auxil)->v; int i; const int l = vec->size; pplObj v; list *lo; if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { strcpy(errText, "Out of memory."); *status=1; *errType=ERR_MEMORY; return; } lo = (list *)OUTPUT.auxil; v.refCount = 1; pplObjNum(&v,1,0,0); ppl_unitsDimCpy(&v, st); for (i=0; iauxil)->v; int i; gsl_vector *ovec; pplObj v, val2; pplFunc *fi; pplExpr dummy; STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (pplObjVector(&OUTPUT,0,1,vec->size)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ovec = ((pplVector *)OUTPUT.auxil)->v; // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; pplObjNum(&v,0,0,0); v.refCount = 1; ppl_unitsDimCpy(&v, st); for (i=0; isize; i++) { const int stkLevelOld = c->stackPtr; // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push a v.real = gsl_vector_get(vec, i); pplObjCpy(&c->stack[c->stackPtr], &v, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } if (c->stack[c->stackPtr-1].objType != PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: function should have returned number, but returned object of type <%s> for element %d.", FunctionDescription, pplObjTypeNames[c->stack[c->stackPtr-1].objType], i); return; } if (i==0) memcpy(&val2, &c->stack[c->stackPtr-1], sizeof(pplObj)); else if (!ppl_unitsDimEqual(&val2, &c->stack[c->stackPtr-1])) { *status=1; *errType=ERR_UNIT; sprintf(errText, "Error inside function supplied to the %s function: function returned values with inconsistent units of <%s> and <%s>. All of the elements of a vector must have matching dimensions.", FunctionDescription, ppl_printUnit(c, &val2, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &c->stack[c->stackPtr-1], NULL, NULL, 1, 1, 0)); return; } if (c->stack[c->stackPtr-1].flagComplex) { *status=1; *errType=ERR_NUMERICAL; sprintf(errText, "Error inside function supplied to the %s function: function returned a complex number for element %d; vectors can only hold real numbers.", FunctionDescription, i); return; } gsl_vector_set(ovec, i, c->stack[c->stackPtr-1].real); while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } return; } static void pplmethod_vectorNorm(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; gsl_vector *v = ((pplVector *)st->auxil)->v; pplObjNum(&OUTPUT,0,gsl_blas_dnrm2(v),0); ppl_unitsDimCpy(&OUTPUT, st); } static void pplmethod_vectorReduce(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "reduce(f)"; const int stkLevelOld = c->stackPtr; int i; pplExpr dummy; pplObj *st = in[-1].self_this; gsl_vector *v = ((pplVector *)st->auxil)->v; pplObj val, val2; pplFunc *fi; STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (v->size < 2) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The %s method cannot be called on vectors containing fewer than two elements. Supplied vector has %d element.", FunctionDescription, (int)v->size); return; } // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; // Fetch first item from vector pplObjNum(&val,0,gsl_vector_get(v,0),0); val.refCount = 1; ppl_unitsDimCpy(&val, st); memcpy(&val2, &val, sizeof(pplObj)); for (i=1; isize; i++) { // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push old value pplObjCpy(&c->stack[c->stackPtr], &val, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push next value val2.real = gsl_vector_get(v,i); pplObjCpy(&c->stack[c->stackPtr], &val2, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 2, 1, 1); // Garbage collect val ppl_garbageObject(&val); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } pplObjCpy(&val, &c->stack[c->stackPtr-1], 0, 0, 1); val.refCount=1; while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } pplObjCpy(&OUTPUT, &val, 0, 0, 1); ppl_garbageObject(&val); return; } static void pplmethod_vectorReverse(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; gsl_vector *v = ((pplVector *)st->auxil)->v; long i,j; long n = v->size; pplObjCpy(&OUTPUT,st,0,0,1); if (v->size<2) return; for ( i=0 , j=n-1 ; iauxil)->v; pplObjCpy(&OUTPUT,st,0,0,1); if (v->size<2) return; qsort((void *)v->data , v->size , sizeof(double)*v->stride , ppl_dblSort); } // List methods static void pplmethod_listAppend(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj v; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; v.refCount=1; pplObjCpy(&v,&in[0],0,1,1); ppl_listAppendCpy(l, &v, sizeof(pplObj)); pplObjCpy(&OUTPUT,st,0,0,1); } static void pplmethod_listCount(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; int count = 0; listIterator *li = ppl_listIterateInit(l); pplObj *item; while ((item = (pplObj*)ppl_listIterate(&li))!=NULL) { pplObj *a = item; pplObj *b = &in[0]; if (pplObjCmpQuiet(&a,&b)==0) count++; } OUTPUT.real = count; return; } static void pplmethod_listExtend(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj v; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; int t = in[0].objType; if (t==PPLOBJ_VEC) { int i; gsl_vector *vi = ((pplVector *)in[0].auxil)->v; pplObjNum(&v,1,0,0); ppl_unitsDimCpy(&v, &in[0]); for (i=0; isize; i++) { v.real = gsl_vector_get(vi,i); ppl_listAppendCpy(l, &v, sizeof(pplObj)); } } else if (t==PPLOBJ_LIST) { list *listin = (list *)in[0].auxil; listIterator *li = ppl_listIterateInit(listin); pplObj *item; while ((item = (pplObj*)ppl_listIterate(&li))!=NULL) { v.refCount=1; pplObjCpy(&v,item,0,1,1); ppl_listAppendCpy(l, &v, sizeof(pplObj)); } } else { *status=1; *errType=ERR_TYPE; sprintf(errText, "Argument to the extend(x) method must be either a list or a vector. Supplied argument had type <%s>.", pplObjTypeNames[t]); return; } pplObjCpy(&OUTPUT,st,0,0,1); } static void pplmethod_listFilter(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { ppl_context *context = c; char *FunctionDescription = "filter(f)"; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; list *ol; pplObj *item; pplFunc *fi; listIterator *li = ppl_listIterateInit(l); pplExpr dummy; STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ol = (list *)OUTPUT.auxil; // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { const int stkLevelOld = c->stackPtr; // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push a pplObjCpy(&c->stack[c->stackPtr], item, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } CAST_TO_BOOL(&c->stack[c->stackPtr-1]); if (c->stack[c->stackPtr-1].real) { pplObj v; pplObjCpy(&v, item, 0, 1, 1); v.refCount=1; ppl_listAppendCpy(ol, &v, sizeof(v)); } while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } return; } static void pplmethod_listIndex(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; int i = 0; listIterator *li = ppl_listIterateInit(l); pplObj *item; while ((item = (pplObj*)ppl_listIterate(&li))!=NULL) { pplObj *a = item; pplObj *b = &in[0]; if (pplObjCmpQuiet(&a,&b)==0) { OUTPUT.real=i; return; } i++; } OUTPUT.real = -1; return; } static void pplmethod_listInsert(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long p; pplObj v; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; if (in[0].objType!=PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "First argument to the insert(n,x) method must be a number. Supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } if (in[0].flagComplex) { *status=1; *errType=ERR_TYPE; sprintf(errText, "First argument to the insert(n,x) method must be a real number. Supplied argument is complex."); return; } if (in[0].real < 0) in[0].real += l->length+1; p = (long)round(in[0].real); if (p<0) { *status=1; *errType=ERR_RANGE; sprintf(errText, "Attempt to insert a list item before the beginning of a list."); return; } if (p>l->length) { *status=1; *errType=ERR_RANGE; sprintf(errText, "List index out of range."); return; } v.refCount=1; pplObjCpy(&v,&in[1],0,1,1); ppl_listInsertCpy(l, p, &v, sizeof(pplObj)); pplObjCpy(&OUTPUT,st,0,0,1); } static void pplmethod_listLen(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { list *l = (list *)in[-1].self_this->auxil; pplObjNum(&OUTPUT,0,l->length,0); } static void pplmethod_listMap(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "map(f)"; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; list *ol; pplObj *item; pplFunc *fi; pplExpr dummy; listIterator *li = ppl_listIterateInit(l); STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } ol = (list *)OUTPUT.auxil; // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { const int stkLevelOld = c->stackPtr; // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push a pplObjCpy(&c->stack[c->stackPtr], item, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } { pplObj v; pplObjCpy(&v, &c->stack[c->stackPtr-1], 0, 1, 1); v.refCount=1; ppl_listAppendCpy(ol, &v, sizeof(v)); } while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } return; } static void pplmethod_listMax(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; pplObj *item, *best=NULL; listIterator *li = ppl_listIterateInit(l); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { if ((best==NULL)||(pplObjCmpQuiet((void*)&item, (void*)&best)==1)) best=item; } if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,best,0,0,1); } static void pplmethod_listMin(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; pplObj *item, *best=NULL; listIterator *li = ppl_listIterateInit(l); while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { if ((best==NULL)||(pplObjCmpQuiet((void*)&item, (void*)&best)==-1)) best=item; } if (best==NULL) pplObjNull(&OUTPUT,0); else pplObjCpy (&OUTPUT,best,0,0,1); } static void pplmethod_listPop(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *obj; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; if (nArgs==0) { obj = ppl_listPop(l); } else { long p; if (in[0].objType!=PPLOBJ_NUM) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Optional argument to the pop(n) method must be a number. Supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } if (in[0].flagComplex) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Optional argument to the pop(n) method must be a real number. Supplied argument is complex."); return; } if (in[0].real < 0) in[0].real += l->length; p = (long)round(in[0].real); if (p<0) { *status=1; *errType=ERR_RANGE; sprintf(errText, "Attempt to pop a list item before the beginning of a list."); return; } if (p>=l->length) { *status=1; *errType=ERR_RANGE; sprintf(errText, "List index out of range."); return; } obj = ppl_listPopItem(l,p); } pplObjCpy(&OUTPUT,obj,0,0,1); ppl_garbageObject(obj); } static void pplmethod_listReduce(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "reduce(f)"; const int stkLevelOld = c->stackPtr; pplExpr dummy; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; pplObj *item, v; pplFunc *fi; listIterator *li = ppl_listIterateInit(l); STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } if (l->length < 2) { *status=1; *errType=ERR_RANGE; sprintf(errText, "The %s method cannot be called on lists containing fewer than two items. Supplied list has length %d.", FunctionDescription, l->length); return; } // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; // Fetch first item from list item = (pplObj *)ppl_listIterate(&li); pplObjCpy(&v, item, 0, 0, 1); v.refCount = 1; while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { // Push function object pplObjCpy(&c->stack[c->stackPtr], &in[0], 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push old value pplObjCpy(&c->stack[c->stackPtr], &v, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push next value pplObjCpy(&c->stack[c->stackPtr], item, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 2, 1, 1); // Garbage collect v ppl_garbageObject(&v); // Propagate error if function failed if (c->errStat.status) { *status=1; *errType=ERR_TYPE; sprintf(errText, "Error inside function supplied to the %s function: %s", FunctionDescription, c->errStat.errMsgExpr); return; } pplObjCpy(&v, &c->stack[c->stackPtr-1], 0, 0, 1); v.refCount=1; while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } } pplObjCpy(&OUTPUT, &v, 0, 0, 1); ppl_garbageObject(&v); return; } static void pplmethod_listReverse(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long i; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; listItem *l1 = l->first; listItem *l2 = l->last; long n = l->length; pplObjCpy(&OUTPUT,st,0,0,1); if (n<2) return; for (i=0; idata; l1->data=l2->data; l2->data=tmp; l1=l1->next; l2=l2->prev; } } static void pplmethod_listSort(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long i; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; long n = l->length; pplObj **items; listIterator *li = ppl_listIterateInit(l); pplObjCpy(&OUTPUT,st,0,0,1); if (n<2) return; items = (pplObj **)malloc(n * sizeof(pplObj *)); if (items==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } i=0; while (li!=NULL) { items[i++]=(pplObj*)li->data; ppl_listIterate(&li); } qsort(items, n, sizeof(pplObj*), pplObjCmpQuiet); li = ppl_listIterateInit(l); i=0; while (li!=NULL) { li->data=(void*)items[i++]; ppl_listIterate(&li); } free(items); } static pplObj *pplmethod_listSortOnCustom_fn = NULL; static ppl_context *pplmethod_listSortOnCustom_context = NULL; static int pplmethod_listSortOnCustom_errFlag = 0; static int pplmethod_listSortOnCustom_slave(const void *a, const void *b) { ppl_context *c = pplmethod_listSortOnCustom_context; pplExpr dummy; int stkLevelOld; int out = 0; pplObj **ao = (pplObj **)a; pplObj **bo = (pplObj **)b; if (pplmethod_listSortOnCustom_errFlag) return 0; if ((c==NULL)||(a==NULL)||(b==NULL)) return 0; stkLevelOld = c->stackPtr; // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = ""; // Push function object pplObjCpy(&c->stack[c->stackPtr], pplmethod_listSortOnCustom_fn, 1, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push a pplObjCpy(&c->stack[c->stackPtr], *ao, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push b pplObjCpy(&c->stack[c->stackPtr], *bo, 0, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 2, 1, 1); // Propagate error if function failed if (c->errStat.status) { pplmethod_listSortOnCustom_errFlag=1; return 0; } // Return error if function didn't return a number if (c->stack[c->stackPtr-1].objType!=PPLOBJ_NUM) { sprintf(c->errStat.errBuff, "The sortOn(f) function requires a comparison function that returns a number. Supplied function returned an object of type <%s>.", pplObjTypeNames[c->stack[c->stackPtr-1].objType]); TBADD_LISTMETHOD(ERR_TYPE); pplmethod_listSortOnCustom_errFlag=1; return 0; } // Get number back and clean stack if (c->stack[c->stackPtr-1].real < 0) out=-1; else if (c->stack[c->stackPtr-1].real > 0) out= 1; else out= 0; while (c->stackPtr>stkLevelOld) { STACK_POP_LISTMETHOD; } return out; } static void pplmethod_listSortOnCustom(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *FunctionDescription = "sortOn(f)"; long i; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; long n = l->length; pplObj **items; pplFunc *fi; int fail; listIterator *li = ppl_listIterateInit(l); STACK_MUSTHAVE(c,4); if (c->stackFull) { *status=1; *errType=ERR_TYPE; strcpy(errText,"Stack overflow."); return; } if (in[0].objType != PPLOBJ_FUNC) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Supplied object is of type <%s>.", FunctionDescription, pplObjTypeNames[in[0].objType]); return; } fi = (pplFunc *)in[0].auxil; if ((fi==NULL)||(fi->functionType==PPL_FUNC_MAGIC)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The %s method requires a function object as its first argument. Integration and differentiation operators are not suitable functions.", FunctionDescription); return; } pplObjCpy(&OUTPUT,st,0,0,1); if (n<2) return; items = (pplObj **)malloc(n * sizeof(pplObj *)); if (items==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } i=0; while (li!=NULL) { items[i++]=(pplObj*)li->data; ppl_listIterate(&li); } pplmethod_listSortOnCustom_fn = &in[0]; pplmethod_listSortOnCustom_errFlag = 0; pplmethod_listSortOnCustom_context = c; qsort(items, n, sizeof(pplObj*), pplmethod_listSortOnCustom_slave); fail = pplmethod_listSortOnCustom_errFlag; pplmethod_listSortOnCustom_fn = NULL; pplmethod_listSortOnCustom_errFlag = 0; pplmethod_listSortOnCustom_context = NULL; if (fail) { *status=1; *errType=ERR_GENERIC; strcpy(errText, "Failure of user-supplied comparison function."); return; } li = ppl_listIterateInit(l); i=0; while (li!=NULL) { li->data=(void*)items[i++]; ppl_listIterate(&li); } free(items); } static void pplmethod_listSortOnElement(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long i; pplObj *st = in[-1].self_this; list *l = (list *)st->auxil; long n = l->length; pplObj **items; int eNum = (int)floor(in[0].real); listIterator *li = ppl_listIterateInit(l); i=0; while (li!=NULL) { pplObj *o=(pplObj*)li->data; ppl_listIterate(&li); i++; if (o->objType!=PPLOBJ_LIST) { *status=1; *errType=ERR_TYPE; sprintf(errText,"The sortOnElement() method expects to be sorting a list of lists. Element %ld of list is not a list, but has type <%s>.",i,pplObjTypeNames[o->objType]); return; } } li = ppl_listIterateInit(l); i=0; while (li!=NULL) { list *o=(list *)((pplObj*)li->data)->auxil; ppl_listIterate(&li); i++; if ((eNum>=o->length)||(eNum<-o->length)) { *status=1; *errType=ERR_RANGE; sprintf(errText,"The sortOnElement() method is sorting on element number %d of each sublist. However, sublist %ld only has elements 0-%d.", eNum, i, o->length-1); return; } } pplObjCpy(&OUTPUT,st,0,0,1); if (n<2) return; items = (pplObj **)malloc(n * 2 * sizeof(pplObj *)); if (items==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } li = ppl_listIterateInit(l); i=0; while (li!=NULL) { pplObj *o=(pplObj*)li->data; list *l=(list *)o->auxil; items[i++]=ppl_listGetItem(l , (eNum>=0) ? eNum : (l->length+eNum)); items[i++]=(pplObj*)li->data; ppl_listIterate(&li); } qsort(items, n, 2*sizeof(pplObj*), pplObjCmpQuiet); li = ppl_listIterateInit(l); i=0; while (li!=NULL) { i++; li->data=(void*)items[i++]; ppl_listIterate(&li); } free(items); } static void pplmethod_listVector(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long i = 0; pplObj *st = in[-1].self_this; list *listin = (list *)st->auxil; listIterator *li = ppl_listIterateInit(listin); const long len = listin->length; gsl_vector *v; if (len==0) { *errType = ERR_MEMORY; sprintf(errText,"Cannot create a vector of length zero."); *status=1; return; } if (pplObjVector(&OUTPUT,0,1,len)==NULL) { *status=1; sprintf(errText,"Out of memory."); *errType=ERR_MEMORY; return; } v = ((pplVector *)OUTPUT.auxil)->v; if (len>0) { pplObj *item = (pplObj*)ppl_listIterate(&li); if (item->objType!=PPLOBJ_NUM) { *status=1; sprintf(errText,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); *errType=ERR_TYPE; return; } if (item->flagComplex) { *status=1; sprintf(errText,"Vectors can only hold real numeric values. Attempt to add a complex number."); *errType=ERR_TYPE; return; } ppl_unitsDimCpy(&OUTPUT,item); gsl_vector_set(v,i,item->real); } for (i=1; iobjType!=PPLOBJ_NUM) { *status=1; sprintf(errText,"Vectors can only hold numeric values. Attempt to add object of type <%s> to vector.", pplObjTypeNames[item->objType]); *errType=ERR_TYPE; return; } if (item->flagComplex) { *status=1; sprintf(errText,"Vectors can only hold real numeric values. Attempt to add a complex number."); *errType=ERR_TYPE; return; } if (!ppl_unitsDimEqual(item, &OUTPUT)) { if (OUTPUT.dimensionless) { sprintf(errText, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector is dimensionless, but number has units of <%s>.", i+1, ppl_printUnit(c, item, NULL, NULL, 1, 1, 0) ); } else if (item->dimensionless) { sprintf(errText, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number is dimensionless.", i+1, ppl_printUnit(c, &OUTPUT, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to append a number (argument %ld) to a vector with conflicting dimensions: vector has units of <%s>, while number has units of <%s>.", i+1, ppl_printUnit(c, &OUTPUT, NULL, NULL, 0, 1, 0), ppl_printUnit(c, item, NULL, NULL, 1, 1, 0) ); } *status = 1; *errType = ERR_UNIT; return; } gsl_vector_set(v,i,item->real); } return; } // Dictionary methods static void pplmethod_dictDelete(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *item; pplObj *st = in[-1].self_this; dict *di = (dict *)st->auxil; char *instr; if ((nArgs!=1)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The method delete(x) requires a string as its argument; supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } if (in[-1].self_this->immutable) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The method delete(x) cannot be called on an immutable object."); return; } instr = (char *)in[0].auxil; item = ppl_dictLookup(di, instr); if (item==NULL) return; if (item->immutable) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The method delete(x) cannot be called on an immutable object."); return; } item->amMalloced = 0; ppl_garbageObject(item); ppl_dictRemoveKey(di, instr); pplObjCpy(&OUTPUT,st,0,0,1); return; } static void pplmethod_dictHasKey(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; dict *di = (dict *)st->auxil; char *instr; if ((nArgs!=1)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The method hasKey() requires a string as its argument; supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } instr = (char *)in[0].auxil; pplObjBool(&OUTPUT,0,ppl_dictContains(di, instr)); return; } static void pplmethod_dictItems(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *key, *tmp; pplObj v, va, vb, *item; list *l, *l2; dictIterator *di = ppl_dictIterateInit((dict *)in[-1].self_this->auxil); if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l = (list *)OUTPUT.auxil; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { v .refCount=1; va.refCount=1; vb.refCount=1; COPYSTR(tmp,key); if (pplObjStr(&va,1,1,tmp )==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } pplObjCpy(&vb,item,0,1,1); if (pplObjList(&v,1,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l2 = (list *)v.auxil; ppl_listAppendCpy(l2, (void *)&va, sizeof(pplObj)); ppl_listAppendCpy(l2, (void *)&vb, sizeof(pplObj)); ppl_listAppendCpy(l , (void *)&v , sizeof(pplObj)); } } static void pplmethod_dictKeys(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *key, *tmp; pplObj v, *item; list *l; dictIterator *di = ppl_dictIterateInit((dict *)in[-1].self_this->auxil); if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { COPYSTR(tmp,key); pplObjStr(&v,1,1,tmp); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); } } static void pplmethod_dictLen(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { dict *d = (dict *)in[-1].self_this->auxil; pplObjNum(&OUTPUT,0,d->length,0); } static void pplmethod_dictValues(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *key, *tmp; pplObj v, *item; list *l; dictIterator *di = ppl_dictIterateInit((dict *)in[-1].self_this->auxil); if (pplObjList(&OUTPUT,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } v.refCount=1; l = (list *)OUTPUT.auxil; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { COPYSTR(tmp,key); pplObjCpy(&v,item,0,1,1); ppl_listAppendCpy(l, (void *)&v, sizeof(pplObj)); } } // Matrix methods static void pplmethod_matrixDet(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; gsl_matrix *m = ((pplMatrix *)in[-1].self_this->auxil)->m; double d = 0; int n = m->size1, i; int s; gsl_matrix *tmp = NULL; gsl_permutation *p = NULL; if (m->size1 != m->size2) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "The determinant is only defined for square matrices."); return; } if ((tmp=gsl_matrix_alloc(n,n))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } gsl_matrix_memcpy(tmp,m); if ((p = gsl_permutation_alloc(n))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } if (gsl_linalg_LU_decomp(tmp,p,&s)!=0) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "LU decomposition failed whilst computing matrix determinant."); return; } d = gsl_linalg_LU_det(tmp,s); gsl_permutation_free(p); gsl_matrix_free(tmp); pplObjNum(&OUTPUT,0,d,0); ppl_unitsDimCpy(&OUTPUT, st); for (i=0; iauxil)->m; if (m->size1 != m->size2) { pplObjBool(&OUTPUT,0,0); return; } for (i=0; isize1; i++) for (j=0; jsize2; j++) if ((i!=j) && (gsl_matrix_get(m,i,j)!=0)) { pplObjBool(&OUTPUT,0,0); return; } pplObjBool(&OUTPUT,0,1); } static void pplmethod_matrixEigenvalues(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i,j; pplObj *st = in[-1].self_this; gsl_matrix *m = ((pplMatrix *)st->auxil)->m; gsl_matrix *tmp = NULL; gsl_vector *vo; int n = m->size1; gsl_eigen_symm_workspace *w; if (m->size1 != m->size2) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "Eigenvalues are only defined for square matrices."); return; } for (i=0; isize1; i++) for (j=0; jv; if (gsl_eigen_symm(tmp, vo, w)!=0) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "Numerical failure whilst trying to compute eigenvalues."); return; } gsl_matrix_free(tmp); gsl_eigen_symm_free(w); ppl_unitsDimCpy(&OUTPUT, st); } static void pplmethod_matrixEigenvectors(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i,j; gsl_matrix *m = ((pplMatrix *)in[-1].self_this->auxil)->m; gsl_matrix *tmp1 = NULL; gsl_matrix *tmp2 = NULL; gsl_vector *vtmp = NULL; list *lo; pplObj v; gsl_vector *vo; int n = m->size1; gsl_eigen_symmv_workspace *w; v.refCount=1; if (m->size1 != m->size2) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "Eigenvectors are only defined for square matrices."); return; } for (i=0; isize1; i++) for (j=0; jv; for (j=0; jauxil)->m; int n = m->size1; int s; gsl_matrix *tmp = NULL; gsl_matrix *mo = NULL; gsl_permutation *p = NULL; if (m->size1 != m->size2) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "The inverse is only defined for square matrices."); return; } if ((tmp=gsl_matrix_alloc(n,n))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } gsl_matrix_memcpy(tmp,m); if ((p = gsl_permutation_alloc(n))==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } if (gsl_linalg_LU_decomp(tmp,p,&s)!=0) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "LU decomposition failed whilst computing matrix determinant."); return; } if (pplObjMatrix(&OUTPUT,0,1,n,n)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } mo = ((pplMatrix *)OUTPUT.auxil)->m; if (gsl_linalg_LU_invert(tmp,p,mo)) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "Numerical failure while computing matrix inverse."); return; } gsl_permutation_free(p); gsl_matrix_free(tmp); ppl_unitsDimInverse(&OUTPUT,st); } static void pplmethod_matrixSize(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { gsl_matrix *m = ((pplMatrix *)in[-1].self_this->auxil)->m; gsl_vector *vo; if (pplObjVector(&OUTPUT,0,1,2)==NULL) { *status=1; *errType=ERR_MEMORY; strcpy(errText, "Out of memory."); return; } vo = ((pplVector *)OUTPUT.auxil)->v; gsl_vector_set(vo,0,m->size1); gsl_vector_set(vo,1,m->size2); } static void pplmethod_matrixSymmetric(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { int i,j; gsl_matrix *m = ((pplMatrix *)in[-1].self_this->auxil)->m; if (m->size1 != m->size2) { pplObjBool(&OUTPUT,0,0); return; } for (i=0; isize1; i++) for (j=0; jauxil)->m; int n = m->size1, i, j; gsl_matrix *vo = NULL; if (m->size1 != m->size2) { *status=1; *errType=ERR_NUMERICAL; strcpy(errText, "The transpose is only defined for square matrices."); return; } if (pplObjMatrix(&OUTPUT,0,1,n,n)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } vo = ((pplMatrix *)OUTPUT.auxil)->m; for (i=0; isize1; i++) for (j=0; jsize2; j++) gsl_matrix_set(vo,i,j,gsl_matrix_get(m,j,i)); ppl_unitsDimCpy(&OUTPUT,st); } // File methods static void pplmethod_fileClose(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; if (f->open) { if (f->pipe==2) { *status=1; *errType=ERR_TYPE; strcpy(errText, "It is not permitted to close this file handle."); return; } f->open=0; if (!f->pipe) fclose(f->file); else pplObjNum(&OUTPUT,0,pclose(f->file),0); f->file=NULL; } } static void pplmethod_fileDump(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; pplObjDump(c, &in[0], f->file); return; } static void pplmethod_fileEof(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; if (!f->open) { pplObjNull(&OUTPUT,0); return; } pplObjBool(&OUTPUT,0,feof(f->file)!=0); } static void pplmethod_fileFlush(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; if (!f->open) { pplObjNull(&OUTPUT,0); return; } if (fflush(f->file)<0) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } } static void pplmethod_fileGetpos(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { long int fp; pplFile *f = (pplFile *)in[-1].self_this->auxil; if (!f->open) { pplObjNull(&OUTPUT,0); return; } if ((fp = ftell(f->file))<0) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } pplObjNum(&OUTPUT,0,fp*8,0); CLEANUP_APPLYUNIT(UNIT_BIT); } static void pplmethod_fileIsOpen(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; pplObjBool(&OUTPUT,0,f->open!=0); } static void pplmethod_fileRead(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char *out=NULL, *new; int chunk = 8192; long pos = 0; long size = chunk; pplFile *f = (pplFile *)in[-1].self_this->auxil; if (!f->open) { pplObjNull(&OUTPUT,0); return; } new = (char *)malloc(chunk+4); while (!feof(f->file)) { int n; if (new==NULL) { if (out!=NULL) free(out); *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } out = new; n = fread(out+pos,1,chunk,f->file); pos += n; if (nauxil; if (!f->open) { pplObjNull(&OUTPUT,0); return; } out = (char *)malloc(chunk); if (out==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } while (!feof(f->file)) { int n; n = fread(out+pos,1,1,f->file); if ((n==0)||(out[pos]=='\n')) break; pos++; if (pos>size-4) { char *new; size += chunk; new = (char *)realloc(out,size); if (new==NULL) { if (out!=NULL) free(out); *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } out = new; } } out[pos]='\0'; pplObjStr(&OUTPUT,0,1,out); } static void pplmethod_fileReadlines(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplObj *st = in[-1].self_this; pplObj v; pplFile *f = (pplFile *)st->auxil; list *l; v.refCount=1; if (!f->open) { pplObjNull(&OUTPUT,0); return; } if (pplObjList(&v,0,1,NULL)==NULL) { *status=1; *errType=ERR_MEMORY; sprintf(errText,"Out of memory."); return; } l = (list *)v.auxil; while (!feof(f->file)) { in[-1].self_this = st; pplmethod_fileReadline(c,in,0,status,errType,errText); if (*status) { ppl_garbageObject(&v); return; } OUTPUT.amMalloced=1; ppl_listAppendCpy(l,&OUTPUT,sizeof(pplObj)); pplObjZom(&OUTPUT,0); } memcpy(&OUTPUT,&v,sizeof(pplObj)); } static void pplmethod_fileSetpos(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { char FunctionDescription[] = "setPos(x)"; int i; long int fp = (long int)in[0].real; pplFile *f = (pplFile *)in[-1].self_this->auxil; CHECK_DIMLESS_OR_HAS_UNIT(in[0] , "first", "a number of bytes", UNIT_BIT, 1); if (!f->open) { pplObjNull(&OUTPUT,0); return; } if (!in[0].dimensionless) fp/=8; if (fseek(f->file,fp,SEEK_SET)!=0) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } if ((fp = ftell(f->file))<0) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } pplObjNum(&OUTPUT,0,fp*8,0); CLEANUP_APPLYUNIT(UNIT_BIT); } static void pplmethod_fileWrite(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { pplFile *f = (pplFile *)in[-1].self_this->auxil; char *s = (char *)in[0].auxil; long int l , o; if ((nArgs!=1)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function write() requires a string as its argument; supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } if (!f->open) { pplObjNull(&OUTPUT,0); return; } l = strlen(s); o = fwrite(s,1,l,f->file); if (o!=l) { *status=1; *errType=ERR_FILE; strcpy(errText, strerror(errno)); return; } } // Exception methods static void pplmethod_excRaise(ppl_context *c, pplObj *in, int nArgs, int *status, int *errType, char *errText) { if ((nArgs!=1)&&(in[0].objType!=PPLOBJ_STR)) { *status=1; *errType=ERR_TYPE; sprintf(errText, "The function raise() requires a string as its argument; supplied argument had type <%s>.", pplObjTypeNames[in[0].objType]); return; } *status = 1; *errType = (int)round(in[-1].self_this->real); strncpy(errText, in[0].auxil, FNAME_LENGTH); errText[FNAME_LENGTH-1]='\0'; return; } // Build dictionaries of the above methods void pplObjMethodsInit(ppl_context *c) { int i; const int n = PPLOBJ_USER+1; pplObjMethods = (dict **)malloc(n * sizeof(dict *)); if (pplObjMethods==NULL) ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Out of memory."); for (i=0; ierrcontext,__FILE__,__LINE__,"Out of memory."); ppl_addSystemMethod(d,"class" ,0,0,1,1,1,1,(void *)&pplmethod_class , "class()", "\\mathrm{class}@<@>", "class() returns the class prototype of an object"); ppl_addSystemMethod(d,"contents",0,0,1,1,1,1,(void *)&pplmethod_contents, "contents()", "\\mathrm{contents}@<@>", "contents() returns a list of all the methods and internal variables of an object"); ppl_addSystemMethod(d,"data" ,0,0,1,1,1,1,(void *)&pplmethod_data , "data()", "\\mathrm{data}@<@>", "data() returns a list of all the internal variables (not methods) of an object"); ppl_addSystemMethod(d,"methods" ,0,0,1,1,1,1,(void *)&pplmethod_methods , "methods()", "\\mathrm{methods}@<@>", "methods() returns a list of the methods of an object"); ppl_addSystemMethod(d,"str" ,0,0,1,1,1,1,(void *)&pplmethod_str , "str()", "\\mathrm{str}@<@>", "str() returns a string representation of an object"); ppl_addSystemMethod(d,"type" ,0,0,1,1,1,1,(void *)&pplmethod_type , "type()", "\\mathrm{type}@<@>", "type() returns the type of an object"); } // String methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"append" ,1,1,0,0,0,0,(void *)&pplmethod_strAppend , "append(x)", "\\mathrm{append}@<@1@>", "append(x) appends the string x to the end of a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"beginsWith",1,1,0,0,0,0,(void *)&pplmethod_strBeginsWith, "beginsWith(x)", "\\mathrm{beginsWith}@<@1@>", "beginsWith(x) returns a boolean indicating whether a string begins with the substring x"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"endsWith" ,1,1,0,0,0,0,(void *)&pplmethod_strEndsWith , "endsWith(x)", "\\mathrm{endsWith}@<@1@>", "endsWith(x) returns a boolean indicating whether a string ends with the substring x"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"find" ,1,1,0,0,0,0,(void *)&pplmethod_strFind , "find(x)", "\\mathrm{find}@<@1@>", "find(x) returns the position of the first occurrence of x in a string, or -1 if it is not found"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"findAll" ,1,1,0,0,0,0,(void *)&pplmethod_strFindAll , "findAll(x)", "\\mathrm{findAll}@<@1@>", "findAll(x) returns a list of the positions where the substring x occurs in a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"isalnum" ,0,0,1,1,1,1,(void *)&pplmethod_strisalnum , "isalnum()", "\\mathrm{isalnum}@<@>", "isalnum() returns a boolean indicating whether all of the characters of a string are alphanumeric"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"isalpha" ,0,0,1,1,1,1,(void *)&pplmethod_strisalpha , "isalpha()", "\\mathrm{isalpha}@<@>", "isalpha() returns a boolean indicating whether all of the characters of a string are alphabetic"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"isdigit" ,0,0,1,1,1,1,(void *)&pplmethod_strisdigit , "isdigit()", "\\mathrm{isdigit}@<@>", "isdigit() returns a boolean indicating whether all of the characters of a string are numeric"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"len" ,0,0,1,1,1,1,(void *)&pplmethod_strLen , "len()", "\\mathrm{len}@<@>", "len() returns the length of a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"lower" ,0,0,1,1,1,1,(void *)&pplmethod_strLower , "lower()", "\\mathrm{lower}@<@>", "lower() converts a string to lowercase"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"split" ,0,0,1,1,1,1,(void *)&pplmethod_strSplit , "split()", "\\mathrm{split}@<@>", "split() returns a list of all the whitespace-separated words in a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"splitOn" ,1,1e3,0,0,0,0,(void *)&pplmethod_strSplitOn , "splitOn(x,...)", "\\mathrm{splitOn}@<@0@>", "splitOn(x,...) splits a string whenever it encounters any of the substrings supplied as arguments, and returns a list of the split string segments"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"lstrip" ,0,0,1,1,1,1,(void *)&pplmethod_strLStrip , "lstrip()", "\\mathrm{lstrip}@<@>", "lstrip() strips whitespace off the beginning of a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"strip" ,0,0,1,1,1,1,(void *)&pplmethod_strStrip , "strip()", "\\mathrm{strip}@<@>", "strip() strips whitespace off the beginning and end of a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"rstrip" ,0,0,1,1,1,1,(void *)&pplmethod_strRStrip , "rstrip()", "\\mathrm{rstrip}@<@>", "rstrip() strips whitespace off the end of a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_STR],"upper" ,0,0,1,1,1,1,(void *)&pplmethod_strUpper , "upper()", "\\mathrm{upper}@<@>", "upper() converts a string to uppercase"); // Date methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toDayOfMonth",0,1,0,0,0,0,(void *)pplmethod_dateToDayOfMonth, "toDayOfMonth()", "\\mathrm{toDayOfMonth}@<@0@>", "toDayOfMonth() returns the day of the month of a date object in the current calendar"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toDayWeekName",0,1,0,0,0,0,(void *)pplmethod_dateToDayWeekName, "toDayWeekName()", "\\mathrm{toDayWeekName}@<@0@>", "toDayWeekName() returns the name of the day of the week of a date object"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toDayWeekNum",0,1,0,0,0,0,(void *)pplmethod_dateToDayWeekNum, "toDayWeekNum()", "\\mathrm{toDayWeekNum}@<@0@>", "toDayWeekNum() returns the day of the week (1-7) of a date object"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toHour",0,1,0,0,0,0,(void *)pplmethod_dateToHour, "toHour()", "\\mathrm{toHour}@<@0@>", "toHour() returns the integer hour component (0-23) of a date object"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toJD",0,0,0,0,0,0,(void *)pplmethod_dateToJD, "toJD()", "\\mathrm{toJD}@<@>", "toJD() converts a date object to a numerical Julian date"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toMinute",0,1,0,0,0,0,(void *)pplmethod_dateToMinute, "toMinute()", "\\mathrm{toMinute}@<@0@>", "toMinute() returns the integer minute component (0-59) of a date object"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toMJD",0,0,0,0,0,0,(void *)pplmethod_dateToMJD, "toMJD()", "\\mathrm{toMJD}@<@>", "toMJD() converts a date object to a modified Julian date"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toMonthName",0,1,0,0,0,0,(void *)pplmethod_dateToMonthName, "toMonthName()", "\\mathrm{toMonthName}@<@0@>", "toMonthName() returns the name of the month in which a date object falls"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toMonthNum",0,1,0,0,0,0,(void *)pplmethod_dateToMonthNum, "toMonthNum()", "\\mathrm{toMonthNum}@<@0@>", "toMonthNum() returns the number (1-12) of the month in which a date object falls"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toSecond",0,1,0,0,0,0,(void *)pplmethod_dateToSecond, "toSecond()", "\\mathrm{toSecond}@<@0@>", "toSecond() returns the seconds component (0.0-60.0) of a date object"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"str",0,2,0,0,0,0,(void *)pplmethod_dateToStr, "str(,)", "\\mathrm{str}@<@0@>", "str(,) converts a date object to a string with an optional format string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toUnix",0,0,0,0,0,0,(void *)pplmethod_dateToUnix, "toUnix()", "\\mathrm{toUnix}@<@>", "toUnix() converts a date object to a Unix time"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_DATE],"toYear",0,1,0,0,0,0,(void *)pplmethod_dateToYear, "toYear()", "\\mathrm{toYear}@<@0@>", "toYear() returns the year in which a date object falls in the current calendar"); // Color methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"componentsCMYK",0,0,1,1,1,1,(void *)pplmethod_colCompCMYK, "componentsCMYK()", "\\mathrm{componentsCMYK}@<@>", "componentsCMYK() returns a vector CMYK representation of a color"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"componentsHSB",0,0,1,1,1,1,(void *)pplmethod_colCompHSB, "componentsHSB()", "\\mathrm{componentsHSB}@<@>", "componentsHSB() returns a vector HSB representation of a color"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"componentsRGB",0,0,1,1,1,1,(void *)pplmethod_colCompRGB, "componentsRGB()", "\\mathrm{componentsRGB}@<@>", "componentsRGB() returns a vector RGB representation of a color"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"toCMYK",0,0,1,1,1,1,(void *)pplmethod_colToCMYK, "toCMYK()", "\\mathrm{toCMYK}@<@>", "toCMYK() returns a CMYK representation of a color"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"toHSB",0,0,1,1,1,1,(void *)pplmethod_colToHSB, "toHSB()", "\\mathrm{toHSB}@<@>", "toHSB() returns an HSB representation of a color"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_COL],"toRGB",0,0,1,1,1,1,(void *)pplmethod_colToRGB, "toRGB()", "\\mathrm{toRGB}@<@>", "toRGB() returns an RGB representation of a color"); // Vector methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"append",1,1,1,1,1,0,(void *)pplmethod_vectorAppend, "append(x)", "\\mathrm{append}@<@0@>", "append(x) appends the object x to a vector"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"extend",1,1,0,0,0,0,(void *)pplmethod_vectorExtend, "extend(x)", "\\mathrm{extend}@<@0@>", "extend(x) appends the members of the list x to the end of a vector"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"filter",1,1,0,0,0,0,(void *)pplmethod_vectorFilter, "filter(f)", "\\mathrm{filter}@<@0}@>", "filter(f) takes a pointer to a function of one argument, f(a). It calls the function for every element of the vector, and returns a new vector of those elements for which f(a) tests true"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"insert",2,2,0,0,0,0,(void *)pplmethod_vectorInsert, "insert(n,x)", "\\mathrm{insert}@<@0@>", "insert(n,x) inserts the object x into a vector at position n"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"len",0,0,1,1,1,1,(void *)pplmethod_vectorLen, "len()", "\\mathrm{len}@<@>", "len() returns the number of dimensions of a vector"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"list",0,0,1,1,1,1,(void *)pplmethod_vectorList, "list()", "\\mathrm{list}@<@>", "list() returns a list representation of a vector"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"map",1,1,0,0,0,0,(void *)pplmethod_vectorMap, "map(f)", "\\mathrm{map}@<@0}@>", "map(f) takes a pointer to a function of one argument, f(a). It calls the function for every element of the vector, and returns a vector of the results"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"norm",0,0,1,1,1,1,(void *)pplmethod_vectorNorm, "norm()", "\\mathrm{norm}@<@>", "norm() returns the norm (quadrature sum) of a vector's elements"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"reduce",1,1,0,0,0,0,(void *)pplmethod_vectorReduce, "reduce(f)", "\\mathrm{reduce}@<@0}@>", "reduce(f) takes a pointer to a function of two arguments. It first calls f(a,b) on the first two elements of the vector, and then continues through the vector calling f(a,b) on the result and the next item in the vector. The final result is returned"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"reverse",0,0,1,1,1,1,(void *)pplmethod_vectorReverse, "reverse()", "\\mathrm{reverse}@<@>", "reverse() reverses the order of the elements of a vector"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_VEC],"sort",0,0,1,1,1,1,(void *)pplmethod_vectorSort, "sort()", "\\mathrm{sort}@<@>", "sort() sorts the members of a vector"); // List methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"append",1,1,0,0,0,0,(void *)pplmethod_listAppend, "append(x)", "\\mathrm{append}@<@0}@>", "append(x) appends the object x to a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"count",1,1,0,0,0,0,(void *)pplmethod_listCount, "count(x)", "\\mathrm{count}@<@0}@>", "count(x) returns the number of items in a list that equal x"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"extend",1,1,0,0,0,0,(void *)pplmethod_listExtend, "extend(x)", "\\mathrm{extend}@<@0}@>", "extend(x) appends the members of the list x to the end of a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"filter",1,1,0,0,0,0,(void *)pplmethod_listFilter, "filter(f)", "\\mathrm{filter}@<@0}@>", "filter(f) takes a pointer to a function of one argument, f(a). It calls the function for every element of the list, and returns a new list of those elements for which f(a) tests true"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"index",1,1,0,0,0,0,(void *)pplmethod_listIndex, "index(x)", "\\mathrm{index}@<@0}@>", "index(x) returns the index of the first element of a list that equals x, or -1 if no elements match"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"insert",2,2,0,0,0,0,(void *)pplmethod_listInsert, "insert(n,x)", "\\mathrm{insert}@<@0@>", "insert(n,x) inserts the object x into a list at position n"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"len",0,0,1,1,1,1,(void *)pplmethod_listLen, "len()", "\\mathrm{len}@<@>", "len() returns the length of a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"map",1,1,0,0,0,0,(void *)pplmethod_listMap, "map(f)", "\\mathrm{map}@<@0}@>", "map(f) takes a pointer to a function of one argument, f(a). It calls the function for every element of the list, and returns a list of the results"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"max",0,0,1,1,1,1,(void *)pplmethod_listMax, "max()", "\\mathrm{max}@<@>", "max() returns the highest-valued item in a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"min",0,0,1,1,1,1,(void *)pplmethod_listMin, "min()", "\\mathrm{min}@<@>", "min() returns the lowest-valued item in a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"pop",0,1,1,1,1,1,(void *)pplmethod_listPop, "pop()", "\\mathrm{pop}@<@0@>", "pop(n) removes the nth item from a list and returns it. If n is not specified, the last list item is popped"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"reduce",1,1,0,0,0,0,(void *)pplmethod_listReduce, "reduce(f)", "\\mathrm{reduce}@<@0}@>", "reduce(f) takes a pointer to a function of two arguments. It first calls f(a,b) on the first two elements of the list, and then continues through the list calling f(a,b) on the result and the next item in the list. The final result is returned"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"reverse",0,0,1,1,1,1,(void *)pplmethod_listReverse, "reverse()", "\\mathrm{reverse}@<@>", "reverse() reverses the order of the members of a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"sort",0,0,1,1,1,1,(void *)pplmethod_listSort, "sort()", "\\mathrm{sort}@<@>", "sort() sorts the members of a list"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"sortOn",1,1,0,0,0,0,(void *)pplmethod_listSortOnCustom, "sortOn(f)", "\\mathrm{sortOn}@<@0@>", "sortOn(f) sorts the members of a list using the user-supplied function f(a,b) to determine the sort order. f should return 1, 0 or -1 depending whether a>b, a==b or a", "sortOnElement(n) sorts a list of lists on the nth element of each sublist"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_LIST],"vector",0,0,1,1,1,1,(void *)pplmethod_listVector, "vector()", "\\mathrm{vector}@<@>", "vector() turns a list into a vector, providing all the list elements are numbers with the same physical dimensions"); // Dictionary methods for (i=0 ;i<3; i++) { int pplobj; if (i==0) pplobj = PPLOBJ_DICT; else if (i==1) pplobj = PPLOBJ_MOD; else pplobj = PPLOBJ_USER; ppl_addSystemMethod(pplObjMethods[pplobj],"delete",1,1,0,0,0,0,(void *)pplmethod_dictDelete, "delete(x)", "\\mathrm{delete}@<@1@>", "delete(x) deletes the key x from the dictionary, if it exists"); ppl_addSystemMethod(pplObjMethods[pplobj],"hasKey",1,1,0,0,0,0,(void *)pplmethod_dictHasKey, "hasKey(x)", "\\mathrm{hasKey}@<@1@>", "hasKey(x) returns a boolean indicating whether the key x exists in the dictionary"); ppl_addSystemMethod(pplObjMethods[pplobj],"items" ,0,0,1,1,1,1,(void *)pplmethod_dictItems , "items()", "\\mathrm{items}@<@>", "items() returns a list of the [key,value] pairs in a dictionary"); ppl_addSystemMethod(pplObjMethods[pplobj],"keys" ,0,0,1,1,1,1,(void *)pplmethod_dictKeys , "keys()", "\\mathrm{keys}@<@>", "keys() returns a list of the keys defined in a dictionary"); ppl_addSystemMethod(pplObjMethods[pplobj],"len" ,0,0,1,1,1,1,(void *)pplmethod_dictLen , "len()", "\\mathrm{len}@<@>", "len() returns the number of entries in a dictionary"); ppl_addSystemMethod(pplObjMethods[pplobj],"values",0,0,1,1,1,1,(void *)pplmethod_dictValues, "values()", "\\mathrm{values}@<@>", "values() returns a list of the values in a dictionary"); } // Matrix methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"det" ,0,0,1,1,1,1,(void *)pplmethod_matrixDet,"det()", "\\mathrm{det}@<@>", "det() returns the determinant of a square matrix"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"diagonal",0,0,1,1,1,1,(void *)pplmethod_matrixDiagonal,"diagonal()", "\\mathrm{diagonal}@<@>", "diagonal() returns a boolean indicating whether a matrix is diagonal"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"eigenvalues",0,0,1,1,1,1,(void *)pplmethod_matrixEigenvalues,"eigenvalues()", "\\mathrm{eigenvalues}@<@>", "eigenvalues() returns a vector containing the eigenvalues of a square symmetric matrix"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"eigenvectors",0,0,1,1,1,1,(void *)pplmethod_matrixEigenvectors,"eigenvectors()", "\\mathrm{eigenvectors}@<@>", "eigenvectors() returns a list of the eigenvectors of a square symmetric matrix"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"inv" ,0,0,1,1,1,1,(void *)pplmethod_matrixInv,"inv()", "\\mathrm{inv}@<@>", "inv() returns the inverse of a square matrix"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"size",0,0,1,1,1,1,(void *)pplmethod_matrixSize, "size()", "\\mathrm{size}@<@>", "size() returns the dimensions of a matrix"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"symmetric",0,0,1,1,1,1,(void *)pplmethod_matrixSymmetric, "symmetric()", "\\mathrm{symmetric}@<@>", "symmetric() returns a boolean indicating whether a matrix is symmetric"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_MAT],"transpose",0,0,1,1,1,1,(void *)pplmethod_matrixTrans, "transpose()", "\\mathrm{transpose}@<@>", "transpose() returns the transpose of a matrix"); // File methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"close",0,0,1,1,1,1,(void *)pplmethod_fileClose,"close()", "\\mathrm{close}@<@>", "close() closes a file handle"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"dump",1,1,0,0,0,0,(void *)pplmethod_fileDump,"dump()", "\\mathrm{dump@<@0@>", "dump(x) writes a typeable ASCII representation of the object x to the file handle"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"eof",0,0,1,1,1,1,(void *)pplmethod_fileEof,"eof()", "\\mathrm{eof}@<@>", "eof() returns a boolean flag to indicate whether the end of a file has been reached"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"flush",0,0,1,1,1,1,(void *)pplmethod_fileFlush,"flush()", "\\mathrm{flush}@<@>", "flush() flushes any buffered data which has not yet physically been written to a file"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"getPos",0,0,1,1,1,1,(void *)pplmethod_fileGetpos,"getPos()", "\\mathrm{getPos}@<@>", "getPos() returns a file handle's current position in a file"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"isOpen",0,0,1,1,1,1,(void *)pplmethod_fileIsOpen,"isOpen()", "\\mathrm{isOpen}@<@>", "isOpen() returns a boolean flag indicating whether a file is open"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"read",0,0,1,1,1,1,(void *)pplmethod_fileRead,"read()", "\\mathrm{read}@<@>", "read() returns the contents of a file as a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"readline",0,0,1,1,1,1,(void *)pplmethod_fileReadline,"readline()", "\\mathrm{readline}@<@>", "readline() returns a single line of a file as a string"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"readlines",0,0,1,1,1,1,(void *)pplmethod_fileReadlines,"readlines()", "\\mathrm{readlines}@<@>", "readlines() returns the lines of a file as a list of strings"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"setPos",1,1,1,1,1,1,(void *)pplmethod_fileSetpos,"setPos(x)", "\\mathrm{setPos}@<@0@>", "setPos(x) sets a file handle's current position in a file"); ppl_addSystemMethod(pplObjMethods[PPLOBJ_FILE],"write",1,1,0,0,0,0,(void *)pplmethod_fileWrite,"write(x)", "\\mathrm{write}@<@0@>", "write(x) writes the string x to a file"); // Exception methods ppl_addSystemMethod(pplObjMethods[PPLOBJ_EXC],"raise",1,1,0,0,0,0,(void *)pplmethod_excRaise,"raise(s)", "\\mathrm{raise}@<@0@>", "raise(s) raises an exception with error string s"); return; } pyxplot-0.9.2/src/userspace/garbageCollector.c0000664000175000017500000001176112026340554020016 0ustar dcf21dcf21// garbageCollector.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: garbageCollector.c 1305 2012-09-14 17:48:04Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include "stdlib.h" #include "stdio.h" #include "gsl/gsl_matrix.h" #include "gsl/gsl_vector.h" #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "expressions/expCompile_fns.h" #include "parser/parser.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc_fns.h" void ppl_garbageNamespace(dict *n) { dictItem *ptr, *ptrnext; if ((n==NULL)||(!n->useMalloc)) return; ptr = n->first; while (ptr != NULL) { ptrnext = ptr->next; ppl_garbageObject((pplObj *)ptr->data); free(ptr->key); // free(ptr->data); -- already done by garbage collector free(ptr); ptr = ptrnext; } ppl_dictFreeTree(n->hashTree); free(n); return; } void ppl_garbageList(list *l) { listItem *ptr, *ptrnext; if ((l==NULL)||(!l->useMalloc)) return; ptr = l->first; while (ptr != NULL) { ptrnext = ptr->next; ppl_garbageObject((pplObj *)ptr->data); // free(ptr->data); -- already done by garbage collector free(ptr); ptr = ptrnext; } free(l); return; } void ppl_garbageObject(pplObj *o) { int objType; if (o==NULL) return; if ( __sync_sub_and_fetch(&o->refCount,1) > 0) return; objType = o->objType; o->objType = PPLOBJ_ZOM; // Object is now a zombie if (o->self_lval!=NULL) { ppl_garbageObject(o->self_lval); o->self_lval=NULL; } if (o->self_this!=NULL) { ppl_garbageObject(o->self_this); o->self_this=NULL; } switch(objType) { case PPLOBJ_STR: case PPLOBJ_EXC: if (o->auxilMalloced) { void *old=o->auxil; o->auxil=NULL; if (old!=NULL) free(old); } break; case PPLOBJ_EXP: { void *old=o->auxil; o->auxil=NULL; if ((old!=NULL)&&o->auxilMalloced) pplExpr_free((pplExpr *)old); break; } case PPLOBJ_BYT: { void *old=o->auxil; o->auxil=NULL; if ((old!=NULL)&&(o->auxilMalloced)) ppl_parserLineFree((parserLine *)old); break; } case PPLOBJ_FILE: { pplFile *f = (pplFile *)(o->auxil); o->auxil = NULL; if ((f!=NULL)&&( __sync_sub_and_fetch(&f->refCount,1) <= 0)) { if ((f->open) && (f->file!=NULL)) { FILE *old=f->file; f->file=NULL; if (f->pipe==2) { /* never close stdin */ } else if (f->pipe) pclose(old); else fclose(old); } free(f); } break; } case PPLOBJ_FUNC: { pplFunc *f = (pplFunc *)(o->auxil); o->auxil = NULL; if ((f!=NULL)&&( __sync_sub_and_fetch(&f->refCount,1) <= 0)) pplObjFuncDestroyChain(f); break; } case PPLOBJ_TYPE: { pplType *t = (pplType *)(o->auxil); o->auxil = NULL; if (t!=NULL) { __sync_sub_and_fetch(&t->refCount,1); } break; // Types don't ever get garbage collected } case PPLOBJ_LIST: { list *l = (list *)(o->auxil); o->auxil = NULL; if ((l!=NULL)&&( __sync_sub_and_fetch(&l->refCount,1) <= 0)) ppl_garbageList(l); break; } case PPLOBJ_VEC: { pplVector *v = (pplVector *)(o->auxil); pplVectorRaw *vr = v->raw; pplMatrixRaw *vrm= v->rawm; o->auxil = NULL; if ((vr!=NULL)&&( __sync_sub_and_fetch(&vr->refCount,1) <= 0)) { gsl_vector_free(vr->v); if (o->auxilMalloced) free(vr); } if ((vrm!=NULL)&&( __sync_sub_and_fetch(&vrm->refCount,1) <= 0)) { gsl_matrix_free(vrm->m); if (o->auxilMalloced) free(vrm); } if ((v!=NULL)&&( __sync_sub_and_fetch(&v->refCount,1) <= 0)&&(o->auxilMalloced)) free(v); break; } case PPLOBJ_MAT: { pplMatrix *m = (pplMatrix *)(o->auxil); pplMatrixRaw *mr = m->raw; o->auxil = NULL; if ((mr!=NULL)&&( __sync_sub_and_fetch(&mr->refCount,1) <= 0)) { gsl_matrix_free(mr->m); if (o->auxilMalloced) free(mr); } if ((m!=NULL)&&( __sync_sub_and_fetch(&m->refCount,1) <= 0)&&(o->auxilMalloced)) free(m); break; } case PPLOBJ_USER: { ppl_garbageObject(o->objPrototype); } case PPLOBJ_DICT: case PPLOBJ_MOD: { dict *d = (dict *)(o->auxil); if ((d!=NULL)&&( __sync_sub_and_fetch(&d->refCount,1) <= 0)) ppl_garbageNamespace(d); break; } } if (o->amMalloced) free(o); return; } pyxplot-0.9.2/src/userspace/contextVarDef.c0000664000175000017500000001355612026340554017337 0ustar dcf21dcf21// contextVarDef.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: contextVarDef.c 1267 2012-07-15 00:11:04Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CONTEXT_C 1 #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "expressions/traceback_fns.h" #include "settings/settings_fns.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjUnits.h" #include "defaultObjs/defaultUnits.h" #include "defaultObjs/defaultVars.h" #define TBADD(et,pos) ppl_tbAdd(c,srcLineN,srcId,srcFname,0,et,pos,linetxt,"") void ppl_contextVarHierLookup(ppl_context *c, int srcLineN, int srcId, char *srcFname, char *linetxt, pplObj *stk, int *stkPos, pplObj **out, int base, int offset) { int first=1; int pos=base; while (stk[pos].objType == PPLOBJ_NUM) { int last; char *name; pos = (int)round(stk[pos].real); if (pos<=0) break; last = (stk[pos].objType!=PPLOBJ_NUM); name = (char *)stk[pos+offset].auxil; if (first && !last) { ppl_contextVarLookup(c, name, out, 0); if (*out==NULL) { sprintf(c->errStat.errBuff,"No such variable, '%s'.",name); TBADD(ERR_NAMESPACE,stkPos[pos+offset]); return; } if (((*out)->objType!=PPLOBJ_DICT)&&((*out)->objType!=PPLOBJ_MOD)&&((*out)->objType!=PPLOBJ_USER)) { sprintf(c->errStat.errBuff,"Cannot reference members of object of type '%s'.",pplObjTypeNames[(*out)->objType]); TBADD(ERR_TYPE,stkPos[pos+offset]); return; } } else if (first) { pplObj tmp; ppl_contextGetVarPointer(c, name, out, &tmp); ppl_contextRestoreVarPointer(c, name, &tmp); if ((*out)->objType==PPLOBJ_GLOB) { int ns_ptr = c->ns_ptr; c->ns_ptr = 1; ppl_contextGetVarPointer(c, name, out, &tmp); ppl_contextRestoreVarPointer(c, name, &tmp); c->ns_ptr = ns_ptr; } } else if (!last) { dict *d = (dict *)(*out)->auxil; if (d->immutable) { sprintf(c->errStat.errBuff,"Cannot %s '%s'.",last?"modify the immutable variable":"set variables in the immutable namespace",name); TBADD(ERR_NAMESPACE,stkPos[pos+offset]); return; } *out = (pplObj *)ppl_dictLookup(d, name); if ((*out)==NULL) { sprintf(c->errStat.errBuff,"No such variable, '%s'.",name); TBADD(ERR_NAMESPACE,stkPos[pos+offset]); return; } if (((*out)->objType!=PPLOBJ_DICT)&&((*out)->objType!=PPLOBJ_MOD)&&((*out)->objType!=PPLOBJ_USER)) { sprintf(c->errStat.errBuff,"Cannot reference members of object of type '%s'.",pplObjTypeNames[(*out)->objType]); TBADD(ERR_TYPE,stkPos[pos+offset]); return; } } else { dict *d = (dict *)(*out)->auxil; if (d->immutable) { sprintf(c->errStat.errBuff,"Cannot %s '%s'.",last?"modify the immutable variable":"set variables in the immutable namespace",name); TBADD(ERR_NAMESPACE,stkPos[pos+offset]); return; } *out = (pplObj *)ppl_dictLookup((dict *)(*out)->auxil, name); if ((*out)==NULL) { pplObj tmp; tmp.refCount=1; pplObjNum(&tmp,1,1,0); ppl_dictAppendCpy(d, name, &tmp, sizeof(pplObj)); *out = (pplObj *)ppl_dictLookup(d, name); } } if (((*out)!=NULL)&&((*out)->immutable)) { sprintf(c->errStat.errBuff,"Cannot %s '%s'.",last?"modify the immutable variable":"set variables in the immutable namespace",name); TBADD(ERR_NAMESPACE,stkPos[pos+offset]); return; } first=0; } if ((*out)==NULL) { sprintf(c->errStat.errBuff,"No such variable."); TBADD(ERR_NAMESPACE,0); return; } return; } void ppl_contextVarLookup(ppl_context *c, char *name, pplObj **output, int returnGlobObjs) { int i; for (i=c->ns_ptr ; i>=0 ; i=(i>1)?1:i-1) { pplObj *obj = (pplObj *)ppl_dictLookup(c->namespaces[i] , name); if (obj==NULL) continue; if ((!returnGlobObjs)&&((obj->objType==PPLOBJ_GLOB)||(obj->objType==PPLOBJ_ZOM))) continue; *output = obj; return; } *output = NULL; return; } void ppl_contextGetVarPointer(ppl_context *c, char *name, pplObj **output, pplObj *temp) { dict *d=c->namespaces[c->ns_ptr]; *output = (pplObj *)ppl_dictLookup(d, name); if (*output!=NULL) { int om = (*output)->amMalloced; *temp = **output; pplObjNum(*output,om,1,0); } else // If variable is not defined, create it now { temp->refCount=1; pplObjNum(temp,1,1,0); ppl_dictAppendCpy(d, name, temp, sizeof(pplObj)); *output = (pplObj *)ppl_dictLookup(d, name); pplObjZom(temp,1); } } void ppl_contextRestoreVarPointer(ppl_context *c, char *name, pplObj *temp) { dict *d = c->namespaces[c->ns_ptr]; pplObj *obj = (pplObj *)ppl_dictLookup(d, name); if (obj!=NULL) { int om = obj->amMalloced; int tm = temp->amMalloced; int rc = obj->refCount; obj->amMalloced = 0; ppl_garbageObject(obj); memcpy(obj,temp,sizeof(pplObj)); obj->amMalloced = om; obj->refCount = rc; pplObjZom(temp,tm); } else { int tm = temp->amMalloced; temp->amMalloced = 1; temp->refCount = 1; ppl_dictAppendCpy(d, name, temp, sizeof(pplObj)); pplObjZom(temp,tm); } } pyxplot-0.9.2/src/userspace/pplObjDump.c0000664000175000017500000001576412026340554016642 0ustar dcf21dcf21// pplObjPrint.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjDump.c 1271 2012-07-18 23:51:56Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #define GSL_RANGE_CHECK_OFF 1 #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/calendars.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsDisp.h" void pplObjDump(ppl_context *c, pplObj *o, FILE *output) { char *buffer = c->errcontext.tempErrStr; int t; const int NSigFigs = 17; if (cancellationFlag) return; if (o==NULL) { fprintf(output, "types.null()"); return; } t = o->objType; switch (t) { case PPLOBJ_NUM: fprintf(output, "%s", ppl_unitsNumericDisplay(c, o, 0, SW_DISPLAY_T, NSigFigs)); break; case PPLOBJ_STR: ppl_strEscapify(o->auxil, buffer); fprintf(output, "%s", buffer); break; case PPLOBJ_BOOL: if (o->real==0) fprintf(output, "false"); else fprintf(output, "true" ); break; case PPLOBJ_DATE: { int status=0; int year, month, day, hour, minute; double second; ppl_fromUnixTime(c, o->real, &year, &month, &day, &hour, &minute, &second, &status, c->errcontext.tempErrStr); fprintf(output,"time.fromCalendar(%d,%d,%d,%d,%d,%.12f)",year,month,day,hour,minute,second); } break; case PPLOBJ_COL: { int n; int ct=floor(o->exponent[0]+0.01); if (ct == SW_COLSPACE_CMYK) { fprintf(output, "cmyk("); n=4; } else if (ct == SW_COLSPACE_RGB) { fprintf(output, "rgb(" ); n=3; } else if (ct == SW_COLSPACE_HSB) { fprintf(output, "hsb(" ); n=3; } else { ppl_warning(&c->errcontext, ERR_INTERNAL, "Unknown color space in pplObjPrint."); fprintf(output, "ERR("); n=0; } if (n>=1) { fprintf(output,"%s",ppl_numericDisplay(o->exponent[ 8], c->numdispBuff[0], NSigFigs, 0)); } if (n>=2) { fprintf(output, ","); fprintf(output,"%s",ppl_numericDisplay(o->exponent[ 9], c->numdispBuff[0], NSigFigs, 0)); } if (n>=3) { fprintf(output, ","); fprintf(output,"%s",ppl_numericDisplay(o->exponent[10], c->numdispBuff[0], NSigFigs, 0)); } if (n>=4) { fprintf(output, ","); fprintf(output,"%s",ppl_numericDisplay(o->exponent[11], c->numdispBuff[0], NSigFigs, 0)); } fprintf(output, ")"); break; } case PPLOBJ_DICT: { int first=1; dictIterator *iter = ppl_dictIterateInit((dict *)o->auxil); char *key; pplObj *item; fprintf(output,"{"); while ((item = (pplObj *)ppl_dictIterate(&iter, &key))!=NULL) { if (cancellationFlag) break; if ((item->objType==PPLOBJ_GLOB) || (item->objType==PPLOBJ_ZOM)) continue; // Hide globals and zombies if (!first) fprintf(output,","); ppl_strEscapify(key, buffer); fprintf(output,"%s:",buffer); pplObjDump(c, item, output); first=0; } fprintf(output,"}"); break; } case PPLOBJ_USER: case PPLOBJ_MOD: { int first=1; dictIterator *iter = ppl_dictIterateInit((dict *)o->auxil); char *key; pplObj *item; fprintf(output,"module({"); while ((item = (pplObj *)ppl_dictIterate(&iter, &key))!=NULL) { if (cancellationFlag) break; if ((item->objType==PPLOBJ_GLOB) || (item->objType==PPLOBJ_ZOM)) continue; // Hide globals and zombies if (!first) fprintf(output,","); ppl_strEscapify(key, buffer); fprintf(output,"%s:",buffer); pplObjDump(c, item, output); first=0; } fprintf(output,"})"); break; } case PPLOBJ_LIST: { int first=1; listIterator *iter = ppl_listIterateInit((list *)o->auxil); pplObj *item; fprintf(output,"["); while ((item = (pplObj *)ppl_listIterate(&iter))!=NULL) { if (cancellationFlag) break; if (!first) fprintf(output,","); pplObjDump(c, item, output); first=0; } fprintf(output,"]"); break; } case PPLOBJ_VEC: { int j=0; double real,imag; char *unit; o->real=1; o->imag=0; o->flagComplex=0; unit = ppl_printUnit(c,o,&real,&imag,1,1,SW_DISPLAY_T); if (o->dimensionless) real=1; gsl_vector *v = ((pplVector *)(o->auxil))->v; fprintf(output,"vector(["); for(j=0; jsize; j++) { if (cancellationFlag) break; if (j>0) fprintf(output,","); fprintf(output,"%s",ppl_numericDisplay(gsl_vector_get(v,j)*real, c->numdispBuff[0], NSigFigs, 0)); } fprintf(output,"])"); if (!o->dimensionless) fprintf(output, "%s", unit); break; } case PPLOBJ_MAT: { int j=0, k=0; double real,imag; char *unit; o->real=1; o->imag=0; o->flagComplex=0; unit = ppl_printUnit(c,o,&real,&imag,1,1,SW_DISPLAY_T); if (o->dimensionless) real=1; gsl_matrix *m = ((pplMatrix *)(o->auxil))->m; { fprintf(output,"matrix(["); for(j=0; jsize1; j++) { if (cancellationFlag) break; if (j>0) fprintf(output,","); fprintf(output,"["); for(k=0; ksize2; k++) { if (cancellationFlag) break; if (k>0) fprintf(output,","); fprintf(output,"%s",ppl_numericDisplay(gsl_matrix_get(m,j,k)*real, c->numdispBuff[0], NSigFigs, 0)); } fprintf(output,"]"); } fprintf(output,"])"); if (!o->dimensionless) fprintf(output, "%s", unit); } break; } case PPLOBJ_EXC: { fprintf(output, "types.exception("); ppl_strEscapify(o->auxil, buffer); fprintf(output, "%s", buffer); fprintf(output, ")"); break; } case PPLOBJ_FILE: case PPLOBJ_FUNC: case PPLOBJ_TYPE: case PPLOBJ_NULL: case PPLOBJ_GLOB: case PPLOBJ_ZOM: case PPLOBJ_EXP: case PPLOBJ_BYT: default: fprintf(output, "types.null()"); break; } return; } pyxplot-0.9.2/src/userspace/unitsDisp.h0000664000175000017500000000373512026340554016550 0ustar dcf21dcf21// unitsDisp.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: unitsDisp.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPL_UNITSDISP_H #define _PPL_UNITSDISP_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" #ifndef _PPL_UNITSDISP_C extern const char *SIprefixes_full[]; extern const char *SIprefixes_abbrev[]; extern const char *SIprefixes_latex[]; #endif char *ppl_unitsNumericDisplayWithFormat(ppl_context *c, pplObj *in, int N, char *formatString, char formatChar, int maxLen, int requiredArgs, int arg1i, int arg2i); char *ppl_unitsNumericDisplay(ppl_context *c, pplObj *in, int N, int typeable, int NSigFigs); void ppl_udFindOptimalNextUnit(ppl_context *c, pplObj *in, unsigned char first, unit **best, double *pow); void ppl_udPrefixFix(ppl_context *c, pplObj *in, unit **UnitList, double *UnitPow, int *UnitPref, int Nunits); char *ppl_printUnit(ppl_context *c, const pplObj *in, double *numberOutReal, double *numberOutImag, int N, int DivAllowed, int typeable); int ppl_unitNameCmp(const char *in, const char *unit, const unsigned char caseSensitive); void ppl_unitsStringEvaluate(ppl_context *c, char *in, pplObj *out, int *end, int *errpos, char *errText); void ppl_newPreferredUnit(ppl_context *c, PreferredUnit **output, char *instr, int OutputContext, int *errpos, char *errText); #endif pyxplot-0.9.2/src/userspace/pplObjDump.h0000664000175000017500000000166312026340554016640 0ustar dcf21dcf21// pplObjDump.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjDump.h 1270 2012-07-18 22:02:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJDUMP_H #define _PPLOBJDUMP_H 1 #include "userspace/pplObj.h" void pplObjDump(ppl_context *c, pplObj *o, FILE *output); #endif pyxplot-0.9.2/src/userspace/contextVarDef.h0000664000175000017500000000253412026340554017336 0ustar dcf21dcf21// contextVarDef.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: contextVarDef.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CONTEXTVARDEF_H #define _CONTEXTVARDEF_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_contextVarHierLookup (ppl_context *c, int srcLineN, int srcId, char *srcFname, char *linetxt, pplObj *stk, int *stkPos, pplObj **out, int base, int offset); void ppl_contextVarLookup (ppl_context *c, char *name, pplObj **output, int returnGlobObjs); void ppl_contextGetVarPointer (ppl_context *c, char *name, pplObj **output, pplObj *temp); void ppl_contextRestoreVarPointer(ppl_context *c, char *name, pplObj *temp); #endif pyxplot-0.9.2/src/userspace/pplObj.h0000664000175000017500000000612512026340554016010 0ustar dcf21dcf21// pplObj.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObj.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include "userspace/pplObjUnits.h" #include #include #include "coreUtils/dict.h" #ifndef _PPLOBJ_H #define _PPLOBJ_H 1 #define PPLOBJ_NUM 0 /* numeric value */ #define PPLOBJ_STR 1 /* string value */ #define PPLOBJ_BOOL 2 /* boolean */ #define PPLOBJ_DATE 3 /* date/time */ #define PPLOBJ_COL 4 /* color */ #define PPLOBJ_DICT 5 /* dictionary */ #define PPLOBJ_MOD 6 /* module */ #define PPLOBJ_LIST 7 /* list */ #define PPLOBJ_VEC 8 /* vector (list of numerical values with common units) */ #define PPLOBJ_MAT 9 /* matrix */ #define PPLOBJ_FILE 10 /* file handle */ #define PPLOBJ_FUNC 11 /* function */ #define PPLOBJ_TYPE 12 /* data type */ #define PPLOBJ_NULL 13 /* null value */ #define PPLOBJ_EXC 14 /* exception type */ #define PPLOBJ_GLOB 15 /* global variable marker */ #define PPLOBJ_ZOM 16 /* zombie */ #define PPLOBJ_EXP 17 /* expression bytecode (returned from parser in expressions like while (foo) { ... } */ #define PPLOBJ_BYT 18 /* command bytecode (returned from parser for CODEBLOCKs */ #define PPLOBJ_USER 19 /* user-defined datatype */ typedef struct pplObj { double real, imag; unsigned char dimensionless, flagComplex, tempType, immutable; unsigned char amMalloced, auxilMalloced; int objType, auxilLen; struct pplObj *objPrototype; void *auxil; double exponent[UNITS_MAX_BASEUNITS]; struct pplObj *self_lval; double *self_dval; struct pplObj *self_this; int refCount; } pplObj; #ifndef _PPLOBJ_C extern const char *pplObjTypeNames[]; extern const int pplObjTypeOrder[]; extern pplObj *pplObjPrototypes; #endif // Structures for describing files and types typedef struct pplFile { int refCount; FILE *file; int open; int pipe; } pplFile; typedef struct pplType { int refCount; dict *methods; int id; } pplType; typedef struct pplVectorRaw { int refCount; gsl_vector *v; } pplVectorRaw; typedef struct pplMatrixRaw { int refCount; gsl_matrix *m; } pplMatrixRaw; typedef struct pplVector { int refCount; gsl_vector *v; gsl_vector_view view; pplVectorRaw *raw; gsl_matrix_view view_m; pplMatrixRaw *rawm; } pplVector; typedef struct pplMatrix { int refCount; gsl_matrix *m; gsl_matrix_view view; int sliceNext; pplMatrixRaw *raw; } pplMatrix; #endif pyxplot-0.9.2/src/userspace/pplObjFunc.h0000664000175000017500000000515212026340554016623 0ustar dcf21dcf21// pplObjFunc.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjFunc.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJFUNC_H #define _PPLOBJFUNC_H 1 // Structures for describing functions #include #include "parser/parser.h" #ifdef HAVE_FFTW3 #include #else #include #endif #include "userspace/pplObj.h" #include "pplConstants.h" #define PPL_FUNC_USERDEF 32050 #define PPL_FUNC_SYSTEM 32051 #define PPL_FUNC_MAGIC 32052 #define PPL_FUNC_SPLINE 32053 #define PPL_FUNC_INTERP2D 32054 #define PPL_FUNC_BMPDATA 32055 #define PPL_FUNC_HISTOGRAM 32056 #define PPL_FUNC_FFT 32057 #define PPL_FUNC_SUBROUTINE 32058 typedef struct functionDescriptor { int functionType, refCount; int minArgs , maxArgs; void *functionPtr; // Can be any of the structures below char *argList; pplObj *min, *max; // Range of values over which this function definition can be used; used in function splicing unsigned char *minActive, *maxActive, numOnly, notNan, realOnly, dimlessOnly, needSelfThis; struct functionDescriptor *next; // A linked list of spliced alternative function definitions char *LaTeX; char *description, *descriptionShort; } pplFunc; typedef struct splineDescriptor { gsl_spline *splineObj; gsl_interp_accel *accelerator; pplObj unitX, unitY, unitZ; long sizeX, sizeY; unsigned char logInterp; char *filename, *splineType; } splineDescriptor; typedef struct histogramDescriptor { long int Nbins; double *bins; double *binvals; unsigned char log; pplObj unit; char *filename; } histogramDescriptor; typedef struct FFTDescriptor { int Ndims; int XSize[USING_ITEMS_MAX]; fftw_complex *datagrid; pplObj range[USING_ITEMS_MAX], invRange[USING_ITEMS_MAX], outputUnit; double normalisation; } FFTDescriptor; #endif pyxplot-0.9.2/src/userspace/pplObjMethods.h0000664000175000017500000000204712026340554017333 0ustar dcf21dcf21// pplObjMethods.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjMethods.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJMETHODS_H #define _PPLOBJMETHODS_H 1 #include "coreUtils/dict.h" #include "userspace/context.h" #include "userspace/pplObj.h" #ifndef _PPLOBJMETHODS_C extern dict **pplObjMethods; #endif void pplObjMethodsInit(ppl_context *c); #endif pyxplot-0.9.2/src/userspace/pplObjPrint.h0000664000175000017500000000175612026340554017032 0ustar dcf21dcf21// pplObjPrint.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjPrint.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJPRINT_H #define _PPLOBJPRINT_H 1 #include "userspace/pplObj.h" void pplObjPrint(ppl_context *c, pplObj *o, char *oname, char *out, int outlen, int internal, int modIterDepth); #endif pyxplot-0.9.2/src/userspace/garbageCollector.h0000664000175000017500000000207312026340554020017 0ustar dcf21dcf21// garbageCollector.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: garbageCollector.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _GARBAGECOLLECTOR_H #define _GARBAGECOLLECTOR_H 1 #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "userspace/pplObj.h" void ppl_garbageNamespace(dict *n); void ppl_garbageList (list *l); void ppl_garbageObject (pplObj *o); #endif pyxplot-0.9.2/src/userspace/context.c0000664000175000017500000000637512026340554016250 0ustar dcf21dcf21// context.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: context.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CONTEXT_C 1 #include #include #include "coreUtils/errorReport.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "expressions/dollarOp.h" #include "expressions/traceback_fns.h" #include "settings/settings_fns.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjUnits.h" #include "defaultObjs/defaultUnits.h" #include "defaultObjs/defaultVars.h" ppl_context *ppl_contextInit() { int i; ppl_context *out = malloc(sizeof(ppl_context)); if (out==NULL) return NULL; out->set = (ppl_settings *)malloc(sizeof(ppl_settings)); if (out->set==NULL) { free(out); return NULL; } out->errcontext.error_input_linenumber = -1; out->errcontext.error_input_filename[0] = '\0'; strcpy(out->errcontext.error_source,"main "); ppl_memAlloc_MemoryInit(&out->errcontext, &ppl_error, &ppl_log); pplset_makedefault(out); ppl_dollarOp_deconfig(out); out->dollarStat.lastFilename[0]='\0'; out->errStat.status = out->errStat.tracebackDepth = 0; out->errStat.errPosExpr = out->errStat.oldErrPosExpr = -1; out->errStat.errPosCmd = out->errStat.oldErrPosCmd = -1; ppl_tbClear(out); out->canvas_items = NULL; out->replotFocus = -1; out->algebraErrPos = -1; out->stackSize = STACK_DEFAULT; out->stack = (pplObj *)malloc(STACK_DEFAULT * sizeof(pplObj)); out->stackPtr = 0; out->stackFull = 0; if (out->stack==NULL) { free(out); return NULL; } out->tokenBuff = NULL; out->tokenBuffLen = 0; out->parserStack = NULL; out->parserStackLen = 0; out->willBeInteractive = 1; out->inputLineBuffer = NULL; out->inputLineAddBuffer = NULL; out->shellExiting = 0; out->shellBreakable = 0; out->shellReturnable = 0; out->shellBroken = 0; out->shellContinued = 0; out->shellReturned = 0; for (i=0; ishellLoopName[i]=NULL; out->shellReturnVal.refCount = 1; pplObjNum(&out->shellReturnVal,0,0,0); out->historyNLinesWritten = 0; out->termtypeSetInConfigfile = 0; out->errcontext.error_input_linenumber = -1; out->errcontext.error_input_filename[0] = '\0'; strcpy(out->errcontext.error_source,"main "); pplObjInit(out); ppl_makeDefaultUnits(out); ppl_makeDefaultVars(out); return out; } void ppl_contextFree(ppl_context *in) { int i; for (i=in->ns_ptr; i>in->ns_branch; i--) ppl_garbageNamespace(in->namespaces[i]); free(in); return; } pyxplot-0.9.2/src/userspace/pplObjCmp.h0000664000175000017500000000322512026340554016446 0ustar dcf21dcf21// pplObjCmp.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjCmp.h 1264 2012-07-12 19:01:23Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJCMP_H #define _PPLOBJCMP_H 1 #include "userspace/context.h" #include "userspace/pplObj.h" void pplcol_RGBtoHSB(double ri, double gi, double bi, double *ho, double *so, double *bo); void pplcol_CMYKtoRGB(double ci, double mi, double yi, double ki, double *ro, double *go, double *bo); void pplcol_HSBtoRGB(double hi, double si, double bi, double *ro, double *go, double *bo); void pplcol_CMYKtoHSB(double ci, double mi, double yi, double ki, double *ho, double *so, double *bo); void pplcol_RGBtoCMYK(double ri, double gi, double bi, double *co, double *mo, double *yo, double *ko); void pplcol_HSBtoCMYK(double hi, double si, double bi, double *co, double *mo, double *yo, double *ko); int pplObjCmpQuiet(const void *a, const void *b); int pplObjCmp(ppl_context *c, const pplObj *a, const pplObj *b, int *status, int *errType, char *errText, int iterDepth); #endif pyxplot-0.9.2/src/userspace/unitsArithmetic.c0000664000175000017500000005101312026340554017725 0ustar dcf21dcf21// unitsArithmetic.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: unitsArithmetic.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include "stringTools/asciidouble.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjUnits.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" // ------------------------------------------------------------------- // Functions for comparing the units of quantities // ------------------------------------------------------------------- void ppl_unitsDimCpy(pplObj *o, const pplObj *i) { int j; o->dimensionless = i->dimensionless; o->tempType = i->tempType; for (j=0; jexponent[j] = i->exponent[j]; return; } void ppl_unitsDimInverse(pplObj *o, const pplObj *i) { int j; o->dimensionless = i->dimensionless; for (j=0; jexponent[j] = -i->exponent[j]; o->tempType = 0; // Either input was per temperature, or we are now per temperature. return; } int ppl_unitsDimEqual(const pplObj *a, const pplObj *b) { int j; if (a->dimensionless && b->dimensionless) return 1; for (j=0; jexponent[j] , b->exponent[j]) == 0) return 0; return 1; } int ppl_unitsDimEqual2(const pplObj *a, const unit *b) { int j; for (j=0; jexponent[j] , b->exponent[j]) == 0) return 0; return 1; } int ppl_unitsDimEqual3(const unit *a, const unit *b) { int j; for (j=0; jexponent[j] , b->exponent[j]) == 0) return 0; return 1; } unsigned char ppl_tempTypeMatch(unsigned char a, unsigned char b) { if ((a<1)||(b<1)) return 1; // anything is compatible with something which doesn't have dimensions of temperature return (a==b); } // ------------------------------- // ARITHMETIC OPERATIONS ON VALUES // ------------------------------- void ppl_uaPow(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { int i; double exponent; gsl_complex ac, bc; unsigned char DimLess=1; exponent = b->real; // We may overwrite this when we set o->real, so store a copy if (b->dimensionless == 0) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } else { sprintf(errText, "Exponent should be dimensionless, but instead has dimensions of <%s>.", ppl_printUnit(c, b, NULL, NULL, 0, 1, 0)); *errType=ERR_UNIT; *status = 1; return; } } if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) // Real pow() { if (a->flagComplex || b->flagComplex) { o->real = GSL_NAN; } else { o->real = pow(a->real, exponent); if ((!gsl_finite(o->real))&&(c->set->term_current.ExplicitErrors == SW_ONOFF_ON)) { sprintf(errText, "Exponentiation operator produced an overflow error or a complex number result. To enable complex arithmetic, type 'set numerics complex'."); *errType=ERR_NUMERICAL; *status = 1; return; } } o->imag = 0.0; o->flagComplex=0; } else // Complex pow() { if ((a->dimensionless == 0) && (b->flagComplex)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } else { sprintf(errText, "Raising quantities with physical units to complex powers produces quantities with complex physical dimensions, which is forbidden. The operand in question has dimensions of <%s>.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0)); *errType=ERR_UNIT; *status = 1; return; } } else { if (!b->flagComplex) { GSL_SET_COMPLEX(&ac, a->real, a->imag); ac = gsl_complex_pow_real(ac, b->real); } else { GSL_SET_COMPLEX(&ac, a->real, a->imag); GSL_SET_COMPLEX(&bc, b->real, b->imag); ac = gsl_complex_pow(ac, bc); } o->real = GSL_REAL(ac); o->imag = GSL_IMAG(ac); o->flagComplex = fabs(o->imag)>(fabs(o->real)*1e-15); if (!o->flagComplex) o->imag=0.0; // Enforce that real numbers have positive zero imaginary components if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Exponentiation operator produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } } } if (a->dimensionless != 0) { if ((o != a) && (o != b)) ppl_unitsDimCpy(o,a); return; } for (i=0; iexponent[i] = a->exponent[i] * exponent; if (ppl_dblEqual(o->exponent[i], 0) == 0) DimLess=0; if (fabs(o->exponent[i]) > 20000 ) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } else { sprintf(errText, "Overflow of physical dimensions of argument."); *errType=ERR_OVERFLOW; *status = 1; return; } } } o->tempType = a->tempType; o->dimensionless = DimLess; return; } void ppl_uaMul(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { int i; double tmp, areal, breal, aimag, bimag; unsigned char DimLess=1; areal = a->real ; aimag = a->imag; breal = b->real ; bimag = b->imag; // Two inputs have conflicting temperature units. This is only allowed in the special case of oC/oF and friends, when temperature conversion happens. if (!ppl_tempTypeMatch(a->tempType, b->tempType)) { if (ppl_dblEqual(a->exponent[UNIT_TEMPERATURE], 1.0) && (ppl_dblEqual(b->exponent[UNIT_TEMPERATURE],-1.0))) { areal = areal + c->tempTypeOffset[a->tempType] - c->tempTypeOffset[b->tempType]; // Remember, areal and breal have already had multipliers applied. } else if (ppl_dblEqual(a->exponent[UNIT_TEMPERATURE],-1.0) && (ppl_dblEqual(b->exponent[UNIT_TEMPERATURE], 1.0))) { breal = breal + c->tempTypeOffset[b->tempType] - c->tempTypeOffset[a->tempType]; // Imaginary part needs to conversion... multiplication already done. } else { *status = 1; *errType=ERR_UNIT; sprintf(errText, "Attempt to multiply quantities with different temperature units: left operand has units of <%s>, while right operand has units of <%s>. These must be explicitly cast onto the same temperature scale before multiplication is allowed. Type 'help units temperatures' for more details.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) );} } // If one or other input has temperature dependence, we need to propagate which unit of temperature is being used. // If we're in one of the cases handled above, don't worry as temperature exponent is about to end up as zero after, e.g. oC/oF o->tempType = (a->tempType > b->tempType) ? a->tempType : b->tempType; if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) || ((!a->flagComplex) && (!b->flagComplex))) // Real multiplication { if (a->flagComplex || b->flagComplex) { o->real = GSL_NAN; } else { o->real = areal * breal; } o->imag = 0.0; o->flagComplex=0; } else // Complex multiplication { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; } else { tmp = (areal * breal - aimag * bimag); o->imag = (aimag * breal + areal * bimag); o->real = tmp; o->flagComplex = !ppl_dblEqual(o->imag, 0); if (!o->flagComplex) o->imag=0.0; // Enforce that real numbers have positive zero imaginary components } } if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Multiplication produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } if ((a->dimensionless != 0) && (b->dimensionless != 0)) { if ((o != a) && (o != b)) ppl_unitsDimCpy(o,a); return; } for (i=0; iexponent[i] = a->exponent[i] + b->exponent[i]; if (ppl_dblEqual(o->exponent[i], 0) == 0) DimLess=0; if (fabs(o->exponent[i]) > 20000 ) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } else { sprintf(errText, "Overflow of physical dimensions of argument."); *errType=ERR_OVERFLOW; *status = 1; return; } } } o->dimensionless = DimLess; if (o->exponent[UNIT_TEMPERATURE]==0) o->tempType = 0; // We've lost our temperature dependence return; } void ppl_uaDiv(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { int i; double mag, tmp, areal, breal, aimag, bimag; unsigned char DimLess=1; areal = a->real ; aimag = a->imag; breal = b->real ; bimag = b->imag; // Two inputs have conflicting temperature units. This is only allowed in the special case of oC/oF and friends, when temperature conversion happens. if (!ppl_tempTypeMatch(a->tempType, b->tempType)) { if (ppl_dblEqual(a->exponent[UNIT_TEMPERATURE], 1.0) && (ppl_dblEqual(b->exponent[UNIT_TEMPERATURE], 1.0))) { areal = areal + c->tempTypeOffset[a->tempType] - c->tempTypeOffset[b->tempType]; // Remember, areal and breal have already had multipliers applied. } else if (ppl_dblEqual(a->exponent[UNIT_TEMPERATURE],-1.0) && (ppl_dblEqual(b->exponent[UNIT_TEMPERATURE],-1.0))) { breal = breal + c->tempTypeOffset[b->tempType] - c->tempTypeOffset[a->tempType]; // Imaginary part needs to conversion... multiplication already done. } else {* status = 1; *errType=ERR_UNIT; sprintf(errText, "Attempt to divide quantities with different temperature units: left operand has units of <%s>, while right operand has units of <%s>. These must be explicitly cast onto the same temperature scale before division is allowed. Type 'help units temperatures' for more details.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) );} } // If one or other input has temperature dependence, we need to propagate which unit of temperature is being used. // If we're in one of the cases handled above, don't worry as temperature exponent is about to end up as zero after, e.g. oC/oF o->tempType = (a->tempType > b->tempType) ? a->tempType : b->tempType; if ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) || ((!a->flagComplex) && (!b->flagComplex))) // Real division { if (a->flagComplex || b->flagComplex) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; } else if (fabs(breal) < 1e-200) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; } else { sprintf(errText, "Division by zero error."); *errType=ERR_NUMERICAL; *status = 1; return; } } else { if (a->flagComplex || b->flagComplex) { o->real = GSL_NAN; } else { o->real = areal / breal; } o->imag = 0.0; o->flagComplex=0; } } else // Complex division { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; } else if ((mag = pow(breal,2)+pow(bimag,2)) < 1e-200) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; } else { sprintf(errText, "Division by zero error."); *errType=ERR_NUMERICAL; *status = 1; return; } } else { tmp = (areal * breal + aimag * bimag) / mag; o->imag = (aimag * breal - areal * bimag) / mag; o->real = tmp; o->flagComplex = !ppl_dblEqual(o->imag, 0); if (!o->flagComplex) o->imag=0.0; // Enforce that real numbers have positive zero imaginary components } } if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Division produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } if ((a->dimensionless != 0) && (b->dimensionless != 0)) { if ((o != a) && (o != b)) ppl_unitsDimCpy(o,a); return; } for (i=0; iexponent[i] = a->exponent[i] - b->exponent[i]; if (ppl_dblEqual(o->exponent[i], 0) == 0) DimLess=0; if (fabs(o->exponent[i]) > 20000 ) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_OFF) { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } else { sprintf(errText, "Overflow of physical dimensions of argument."); *errType=ERR_UNIT; *status = 1; return; } } } o->dimensionless = DimLess; if (o->exponent[UNIT_TEMPERATURE]==0) o->tempType = 0; // We've lost our temperature dependence return; } void ppl_uaAdd(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { o->real = a->real + b->real; if ((o != a) && (o != b)) { ppl_unitsDimCpy(o,a); o->imag = 0.0; o->flagComplex=0; } if ((a->dimensionless == 0) || (b->dimensionless == 0)) { if (ppl_unitsDimEqual(a, b) == 0) { if (a->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to add quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } } if (!ppl_tempTypeMatch(a->tempType, b->tempType)) { *errType=ERR_UNIT; *status = 1; sprintf(errText, "Attempt to add quantities with different temperature units: left operand has units of <%s>, while right operand has units of <%s>. These must be explicitly cast onto the same temperature scale before addition is allowed. Type 'help units temperatures' for more details.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } if (a->flagComplex || b->flagComplex) { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; return; } o->imag = a->imag + b->imag; o->flagComplex = !ppl_dblEqual(o->imag, 0); if (!o->flagComplex) o->imag=0.0; // Enforce that real numbers have positive zero imaginary components } if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Addition produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } return; } void ppl_uaSub(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { o->real = a->real - b->real; if ((o != a) && (o != b)) { ppl_unitsDimCpy(o,a); o->imag = 0.0; o->flagComplex=0; } if ((a->dimensionless == 0) || (b->dimensionless == 0)) { if (ppl_unitsDimEqual(a, b) == 0) { if (a->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to subtract quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } } if (!ppl_tempTypeMatch(a->tempType, b->tempType)) { *errType=ERR_UNIT; *status = 1; sprintf(errText, "Attempt to subtract quantities with different temperature units: left operand has units of <%s>, while right operand has units of <%s>. These must be explicitly cast onto the same temperature scale before subtraction is allowed. Type 'help units temperatures' for more details.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } if (a->flagComplex || b->flagComplex) { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; return; } o->imag = a->imag - b->imag; o->flagComplex = !ppl_dblEqual(o->imag, 0); if (!o->flagComplex) o->imag=0.0; // Enforce that real numbers have positive zero imaginary components } if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Subtraction produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } return; } void ppl_uaMod(ppl_context *c, const pplObj *a, const pplObj *b, pplObj *o, int *status, int *errType, char *errText) { o->real = a->real - floor(a->real / b->real) * b->real; if ((o != a) && (o != b)) { ppl_unitsDimCpy(o,a); o->imag = 0.0; o->flagComplex=0; } if ((a->dimensionless == 0) || (b->dimensionless == 0)) { if (ppl_unitsDimEqual(a, b) == 0) { if (a->dimensionless) { sprintf(errText, "Attempt to apply mod operator to quantities with conflicting dimensions: left operand is dimensionless, while right operand has units of <%s>.", ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } else if (b->dimensionless) { sprintf(errText, "Attempt to apply mod operator to quantities with conflicting dimensions: left operand has units of <%s>, while right operand is dimensionless.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0) ); } else { sprintf(errText, "Attempt to apply mod operator to quantities with conflicting dimensions: left operand has units of <%s>, while right operand has units of <%s>.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } *errType=ERR_UNIT; *status = 1; return; } } if (!ppl_tempTypeMatch(a->tempType, b->tempType)) { *errType=ERR_UNIT; *status = 1; sprintf(errText, "Attempt to apply mod operator to quantities with different temperature units: left operand has units of <%s>, while right operand has units of <%s>. These must be explicitly cast onto the same temperature scale before the use of the mod operator is allowed. Type 'help units temperatures' for more details.", ppl_printUnit(c, a, NULL, NULL, 0, 1, 0), ppl_printUnit(c, b, NULL, NULL, 1, 1, 0) ); } if (a->flagComplex || b->flagComplex) { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { o->real = GSL_NAN; o->imag = 0; o->flagComplex=0; return; } sprintf(errText, "Mod operator can only be applied to real operands; complex operands supplied."); *errType=ERR_NUMERICAL; *status = 1; return; } if ((!gsl_finite(o->real))||(!gsl_finite(o->imag))) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errText, "Modulo operator produced an overflow error."); *errType=ERR_OVERFLOW; *status = 1; return; } else { pplObjNum(o, o->amMalloced, GSL_NAN, 0.0); return; } } return; } pyxplot-0.9.2/src/userspace/pplObjFunc_fns.h0000664000175000017500000000204412026340554017466 0ustar dcf21dcf21// pplObjFunc_fn.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjFunc_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJFUNC_FN_H #define _PPLOBJFUNC_FN_H 1 #include "pplObjFunc.h" // Routines for manipulating function descriptors void pplObjFuncDestroyChain(pplFunc *f); void pplObjFuncDestroy(pplFunc *f); pplFunc *pplObjFuncCpy(pplFunc *f); #endif pyxplot-0.9.2/src/userspace/pplObj_fns.h0000664000175000017500000000614512026340554016660 0ustar dcf21dcf21// pplObj_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObj_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLOBJ_FNS_H #define _PPLOBJ_FNS_H 1 #include #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/context.h" // Functions for acting on pplObjs void pplObjInit (ppl_context *c); pplObj *pplObjNum (pplObj *in, unsigned char amMalloced, double real, double imag); pplObj *pplObjStr (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, char *str); pplObj *pplObjBool (pplObj *in, unsigned char amMalloced, int stat); pplObj *pplObjDate (pplObj *in, unsigned char amMalloced, double unixTime); pplObj *pplObjColor (pplObj *in, unsigned char amMalloced, int scheme, double c1, double c2, double c3, double c4); pplObj *pplObjDict (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, dict *d); pplObj *pplObjModule (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, unsigned char frozen); pplObj *pplObjList (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, list *l); pplObj *pplObjVector (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, int size); pplObj *pplObjMatrix (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, int size1, int size2); pplObj *pplObjFile (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, FILE *f, int pipe); pplObj *pplObjFunc (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplFunc *f); pplObj *pplObjType (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplType *t); pplObj *pplObjNull (pplObj *in, unsigned char amMalloced); pplObj *pplObjException(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, char *str, int errCode); pplObj *pplObjGlobal (pplObj *in, unsigned char amMalloced); pplObj *pplObjExpression(pplObj *in, unsigned char amMalloced, void *bytecode); pplObj *pplObjBytecode (pplObj *in, unsigned char amMalloced, void *parserline); pplObj *pplObjZom (pplObj *in, unsigned char amMalloced); pplObj *pplObjUser (pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplObj *prototype); pplObj *pplObjCpy (pplObj *out, pplObj *in, unsigned char lval, unsigned char outMalloced, unsigned char useMalloc); pplObj *pplObjDeepCpy(pplObj *out, pplObj *in, int deep, unsigned char outMalloced, unsigned char useMalloc); #endif pyxplot-0.9.2/src/userspace/pplObj.c0000664000175000017500000004464612026340554016015 0ustar dcf21dcf21// pplObj.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObj.c 1308 2012-09-16 21:53:52Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPLOBJ_C 1 #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjMethods.h" #include "userspace/pplObjUnits.h" // Items with ! should never be displayed because they are internal markers const char *pplObjTypeNames[] = {"number","string","boolean","date","color","dictionary","module","list","vector","matrix","fileHandle","function","type","null","exception","!global","!zombie","!expression","!bytecode","instance",NULL}; const int pplObjTypeOrder[] = { 2 , 4 , 2 , 3 , 5 , 9 , 11 , 7 , 6 , 8 , 13 , 12 , 14 , 0 , 15 , 0 , 0 , 0 , 0 , 10 }; pplObj *pplObjPrototypes; void pplObjInit(ppl_context *c) { static int initialised=0; // Only ever run this once int i; const int n = PPLOBJ_USER+1; if (initialised) return; pplType *typeObjs = (pplType *)malloc(n * sizeof(pplType)); pplObjPrototypes = (pplObj *)malloc(n * sizeof(pplObj)); if ((typeObjs==NULL)||(pplObjPrototypes==NULL)) ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Out of memory."); pplObjMethodsInit(c); for (i=0; iobjType = PPLOBJ_NUM; in->real = real; in->imag = imag; in->dimensionless = 1; in->flagComplex = in->tempType = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_NUM]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; for (i=0; iexponent[i]=0; return in; } pplObj *pplObjStr(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, char *str) { in->objType = PPLOBJ_ZOM; // In case we get interrupted in->auxil = (void *)str; in->auxilMalloced = auxilMalloced; in->auxilLen = strlen(str)+1; in->objPrototype = &pplObjPrototypes[PPLOBJ_STR]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_STR; return in; } pplObj *pplObjBool(pplObj *in, unsigned char amMalloced, int stat) { int i; in->objType = PPLOBJ_BOOL; in->real = stat; in->auxil = NULL; in->objPrototype = &pplObjPrototypes[PPLOBJ_BOOL]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->auxilMalloced = 0; in->auxilLen = 0; in->amMalloced = amMalloced; in->immutable = 0; in->imag = 0; // Need to set these as booleans use same object comparison logic as numeric values in->dimensionless = 1; in->flagComplex = in->tempType = 0; for (i=0; iexponent[i]=0; return in; } pplObj *pplObjDate(pplObj *in, unsigned char amMalloced, double unixTime) { in->objType = PPLOBJ_DATE; in->real = unixTime; in->auxil = NULL; in->objPrototype = &pplObjPrototypes[PPLOBJ_DATE]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->auxilMalloced = 0; in->auxilLen = 0; in->amMalloced = amMalloced; in->immutable = 0; return in; } pplObj *pplObjColor(pplObj *in, unsigned char amMalloced, int scheme, double c1, double c2, double c3, double c4) { if (c1<0) c1=0; if (c1>1) c1=1; if (c2<0) c2=0; if (c2>1) c2=1; if (c3<0) c3=0; if (c3>1) c3=1; if (c4<0) c4=0; if (c4>1) c4=1; in->objType = PPLOBJ_COL; in->auxil = NULL; in->objPrototype = &pplObjPrototypes[PPLOBJ_COL]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->auxilMalloced = 0; in->auxilLen = 0; in->amMalloced = amMalloced; in->immutable = 0; in->exponent[ 0] = scheme; in->exponent[ 2] = 0; in->exponent[ 8] = c1; in->exponent[ 9] = c2; in->exponent[10] = c3; in->exponent[11] = c4; return in; } pplObj *pplObjDict(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, dict *d) { in->objType = PPLOBJ_ZOM; if (d==NULL) in->auxil = (void *)ppl_dictInit(auxilMalloced); else in->auxil = (void *)d; if (in->auxil==NULL) return NULL; in->auxilMalloced = auxilMalloced; in->auxilLen = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_DICT]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_DICT; return in; } pplObj *pplObjModule(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, unsigned char frozen) { in->objType = PPLOBJ_ZOM; in->auxil = (void *)ppl_dictInit(auxilMalloced); ((dict *)in->auxil)->immutable = frozen; if (in->auxil==NULL) return NULL; in->auxilMalloced = auxilMalloced; in->auxilLen = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_MOD]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = frozen; in->objType = PPLOBJ_MOD; return in; } pplObj *pplObjList(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, list *l) { in->objType = PPLOBJ_ZOM; if (l==NULL) in->auxil = (void *)ppl_listInit(auxilMalloced); else in->auxil = (void *)l; if (in->auxil==NULL) return NULL; in->auxilMalloced = auxilMalloced; in->auxilLen = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_LIST]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_LIST; return in; } pplObj *pplObjVector(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, int size) { int i; pplVector *pv; pplVectorRaw *pvr; in->objType = PPLOBJ_ZOM; if (auxilMalloced) pv = (pplVector *)(in->auxil = malloc (sizeof(pplVector))); else pv = (pplVector *)(in->auxil = ppl_memAlloc(sizeof(pplVector))); if (pv==NULL) return NULL; if (auxilMalloced) pvr = pv->raw = (pplVectorRaw *)malloc (sizeof(pplVectorRaw)); else pvr = pv->raw = (pplVectorRaw *)ppl_memAlloc(sizeof(pplVectorRaw)); if (pvr==NULL) { if (auxilMalloced) free(pv); return NULL; } if ((pvr->v = gsl_vector_calloc(size))==NULL) { if (auxilMalloced) { free(pv); free(pvr); } return NULL; } pvr->refCount = 1; pv ->refCount = 1; pv ->rawm = NULL; pv ->v = pvr->v; in->auxilMalloced = auxilMalloced; in->auxilLen = sizeof(pplMatrix); in->objPrototype = &pplObjPrototypes[PPLOBJ_VEC]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->dimensionless = 1; for (i=0; iexponent[i]=0; in->objType = PPLOBJ_VEC; return in; } pplObj *pplObjMatrix(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, int size1, int size2) { int i; pplMatrix *pm; pplMatrixRaw *pmr; in->objType = PPLOBJ_ZOM; if (auxilMalloced) pm = (pplMatrix *)(in->auxil = malloc (sizeof(pplMatrix))); else pm = (pplMatrix *)(in->auxil = ppl_memAlloc(sizeof(pplMatrix))); if (pm==NULL) return NULL; if (auxilMalloced) pmr = pm->raw = (pplMatrixRaw *)malloc (sizeof(pplMatrixRaw)); else pmr = pm->raw = (pplMatrixRaw *)ppl_memAlloc(sizeof(pplMatrixRaw)); if (pmr==NULL) { if (auxilMalloced) free(pm); return NULL; } if ((pmr->m = gsl_matrix_calloc(size1 , size2))==NULL) { if (auxilMalloced) { free(pm); free(pmr); } return NULL; } pmr->refCount = 1; pm ->refCount = 1; pm ->sliceNext = 0; pm ->m = pmr->m; in->auxilMalloced = auxilMalloced; in->auxilLen = sizeof(pplMatrix); in->objPrototype = &pplObjPrototypes[PPLOBJ_MAT]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->dimensionless = 1; for (i=0; iexponent[i]=0; in->objType = PPLOBJ_MAT; return in; } pplObj *pplObjFile(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, FILE *f, int pipe) { in->objType = PPLOBJ_ZOM; if (auxilMalloced) in->auxil = (void *)malloc (sizeof(pplFile)); else in->auxil = (void *)ppl_memAlloc(sizeof(pplFile)); if (in->auxil==NULL) return NULL; ((pplFile *)in->auxil)->refCount = 1; ((pplFile *)in->auxil)->file = f; ((pplFile *)in->auxil)->open = 1; ((pplFile *)in->auxil)->pipe = pipe; in->auxilMalloced = auxilMalloced; in->auxilLen = sizeof(pplFile); in->objPrototype = &pplObjPrototypes[PPLOBJ_FILE]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_FILE; return in; } pplObj *pplObjFunc(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplFunc *f) { in->objType = PPLOBJ_ZOM; in->auxilLen = sizeof(pplFunc); in->auxil = (void *)f; in->auxilMalloced = auxilMalloced; in->objPrototype = &pplObjPrototypes[PPLOBJ_FUNC]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_FUNC; return in; } pplObj *pplObjType(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplType *t) { in->objType = PPLOBJ_ZOM; in->auxilLen = sizeof(pplType); in->auxil = (void *)t; in->auxilMalloced = auxilMalloced; in->objPrototype = &pplObjPrototypes[PPLOBJ_TYPE]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 1; // Types are always immutable in->objType = PPLOBJ_TYPE; return in; } pplObj *pplObjNull(pplObj *in, unsigned char amMalloced) { in->objType = PPLOBJ_NULL; in->objPrototype = &pplObjPrototypes[PPLOBJ_NULL]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; return in; } pplObj *pplObjException(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, char *str, int errCode) { in->objType = PPLOBJ_ZOM; in->auxil = (void *)str; in->auxilMalloced = auxilMalloced; in->auxilLen = strlen(str)+1; in->real = errCode; in->objPrototype = &pplObjPrototypes[PPLOBJ_EXC]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_EXC; return in; } pplObj *pplObjGlobal(pplObj *in, unsigned char amMalloced) { in->objType = PPLOBJ_GLOB; in->objPrototype = &pplObjPrototypes[PPLOBJ_GLOB]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; return in; } pplObj *pplObjExpression(pplObj *in, unsigned char amMalloced, void *bytecode) { in->objType = PPLOBJ_EXP; in->auxil = bytecode; in->auxilMalloced = 1; in->auxilLen = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_EXP]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 1; return in; } pplObj *pplObjBytecode(pplObj *in, unsigned char amMalloced, void *parserline) { in->objType = PPLOBJ_BYT; in->auxil = parserline; in->auxilMalloced = 1; in->auxilLen = 0; in->objPrototype = &pplObjPrototypes[PPLOBJ_BYT]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 1; return in; } pplObj *pplObjZom(pplObj *in, unsigned char amMalloced) { in->objType = PPLOBJ_ZOM; in->objPrototype = &pplObjPrototypes[PPLOBJ_ZOM]; in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; return in; } pplObj *pplObjUser(pplObj *in, unsigned char amMalloced, unsigned char auxilMalloced, pplObj *prototype) { in->objType = PPLOBJ_ZOM; in->auxil = (void *)ppl_dictInit(auxilMalloced); if (in->auxil==NULL) return NULL; in->auxilMalloced = auxilMalloced; in->auxilLen = 0; in->objPrototype = (pplObj *)malloc(sizeof(pplObj)); if (in->objPrototype==NULL) return NULL; in->objPrototype->refCount = 1; pplObjCpy(in->objPrototype, prototype, 0, 1, 1); in->self_lval = NULL; in->self_dval = NULL; in->self_this = NULL; in->amMalloced = amMalloced; in->immutable = 0; in->objType = PPLOBJ_USER; return in; } pplObj *pplObjCpy(pplObj *out, pplObj *in, unsigned char lval, unsigned char outMalloced, unsigned char useMalloc) { int rc = (out==NULL) ? 1 : out->refCount; int t; if (in==NULL) return NULL; if (out==NULL) { if (outMalloced) out = (pplObj *)malloc (sizeof(pplObj)); else out = (pplObj *)ppl_memAlloc(sizeof(pplObj)); if (out==NULL) return out; } t = in->objType; memcpy(out, in, sizeof(pplObj)); if (lval) { out->self_lval = in; __sync_add_and_fetch(&out->self_lval->refCount,1); } else { out->self_lval = NULL; } out->self_dval = NULL; out->self_this = NULL; out->refCount = rc; out->amMalloced = outMalloced; out->immutable = in->immutable && ((t==PPLOBJ_EXP)||(t==PPLOBJ_BYT)||(t==PPLOBJ_LIST)||(t==PPLOBJ_VEC)||(t==PPLOBJ_MAT)||(t==PPLOBJ_DICT)||(t==PPLOBJ_MOD)||(t==PPLOBJ_USER)||(t==PPLOBJ_FILE)||(t==PPLOBJ_FUNC)||(t==PPLOBJ_TYPE)); switch(in->objType) { case PPLOBJ_STR: case PPLOBJ_EXC: // copy string value if (in->auxil==NULL) { out->auxilMalloced = 0; return out; } if (useMalloc) out->auxil = (void *)malloc (in->auxilLen); else out->auxil = (void *)ppl_memAlloc(in->auxilLen); if (out->auxil==NULL) { out->objType=PPLOBJ_ZOM; return NULL; } memcpy(out->auxil, in->auxil, in->auxilLen); out->auxilMalloced = useMalloc; break; case PPLOBJ_EXP: { // Copying bytecode is difficult. Assume that original will outlive the copy out->auxilMalloced = 0; break; } case PPLOBJ_BYT: { parserLine *item = (parserLine *)out->auxil; if (item!=NULL) __sync_add_and_fetch(&item->refCount,1); break; } case PPLOBJ_USER: { pplObj *p = (pplObj *)malloc(sizeof(pplObj)); // Copy prototype pointer object if (p==NULL) { out->objType=PPLOBJ_ZOM; return NULL; } pplObjCpy(p,out->objPrototype,0,1,1); p->refCount=1; out->objPrototype=p; } case PPLOBJ_DICT: // dictionary -- pass by pointer case PPLOBJ_MOD: __sync_add_and_fetch(&((dict *)(out->auxil))->refCount,1); break; case PPLOBJ_LIST: // list __sync_add_and_fetch(&((list *)(out->auxil))->refCount,1); break; case PPLOBJ_VEC: // vector { pplVector *pv = (pplVector *)out->auxil; __sync_add_and_fetch(&pv->refCount,1); if (pv->raw !=NULL) __sync_add_and_fetch(&pv->raw ->refCount,1); if (pv->rawm!=NULL) __sync_add_and_fetch(&pv->rawm->refCount,1); break; } case PPLOBJ_MAT: // matrix { pplMatrix *pm = (pplMatrix *)out->auxil; __sync_add_and_fetch(&pm->refCount,1); __sync_add_and_fetch(&pm->raw->refCount,1); break; } case PPLOBJ_FILE: // file handle __sync_add_and_fetch(&((pplFile *)(out->auxil))->refCount,1); break; case PPLOBJ_FUNC: // function pointer __sync_add_and_fetch(&((pplFunc *)(out->auxil))->refCount,1); break; case PPLOBJ_TYPE: // data type __sync_add_and_fetch(&((pplType *)(out->auxil))->refCount,1); break; } return out; } pplObj *pplObjDeepCpy(pplObj *out, pplObj *in, int deep, unsigned char outMalloced, unsigned char useMalloc) { int t=in->objType; if (in==NULL) return NULL; if (out==NULL) { if (outMalloced) out = (pplObj *)malloc (sizeof(pplObj)); else out = (pplObj *)ppl_memAlloc(sizeof(pplObj)); if (out==NULL) return out; } switch (t) { case PPLOBJ_DICT: case PPLOBJ_MOD: case PPLOBJ_USER: { pplObj *item; char *key; dict *d; dictIterator *di = ppl_dictIterateInit((dict *)in->auxil); memcpy(out, in, sizeof(pplObj)); out->objType = PPLOBJ_ZOM; out->self_lval = NULL; out->self_dval = NULL; out->self_this = NULL; out->amMalloced = outMalloced; out->auxil = (void *)(d = ppl_dictInit(useMalloc)); if (out->auxil==NULL) return NULL; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { pplObj v; v.refCount=1; if (!deep) pplObjCpy(&v,item,0,useMalloc,useMalloc); else pplObjDeepCpy(&v,item,1,useMalloc,useMalloc); ppl_dictAppendCpy(d,key,&v,sizeof(pplObj)); } out->objType = t; return out; } case PPLOBJ_LIST: { pplObj *item; list *l; listIterator *li = ppl_listIterateInit((list *)in->auxil); memcpy(out, in, sizeof(pplObj)); out->objType = PPLOBJ_ZOM; out->self_lval = NULL; out->self_dval = NULL; out->self_this = NULL; out->amMalloced = outMalloced; out->auxil = (void *)(l = ppl_listInit(useMalloc)); if (out->auxil==NULL) return NULL; while ((item = (pplObj *)ppl_listIterate(&li))!=NULL) { pplObj v; v.refCount=1; if (!deep) pplObjCpy(&v,item,0,useMalloc,useMalloc); else pplObjDeepCpy(&v,item,1,useMalloc,useMalloc); ppl_listAppendCpy(l,&v,sizeof(pplObj)); } out->objType = t; return out; } default: return pplObjCpy(out,in,0,outMalloced,useMalloc); } } pyxplot-0.9.2/src/userspace/pplObjPrint.c0000664000175000017500000003470212026340554017022 0ustar dcf21dcf21// pplObjPrint.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pplObjPrint.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #define GSL_RANGE_CHECK_OFF 1 #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/dict.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/calendars.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsDisp.h" void pplObjPrint(ppl_context *c, pplObj *o, char *oname, char *out, int outlen, int internal, int modIterDepth) { int t; int NSigFigs = c->set->term_current.SignificantFigures; int typeable = c->set->term_current.NumDisplay; if (o==NULL) { strcpy(out,""); return; } t = o->objType; switch (t) { case PPLOBJ_NUM: strncpy(out, ppl_unitsNumericDisplay(c, o, 0, internal?SW_DISPLAY_T:typeable, NSigFigs), outlen); break; case PPLOBJ_STR: if (internal || (typeable==SW_DISPLAY_T)) ppl_strEscapify(o->auxil, out); else strncpy(out, o->auxil, outlen); break; case PPLOBJ_BOOL: if (o->real==0) strncpy(out, "false", outlen); else strncpy(out, "true" , outlen); break; case PPLOBJ_DATE: if (internal || (typeable==SW_DISPLAY_T)) { int status=0; int year, month, day, hour, minute; double second; ppl_fromUnixTime(c, o->real, &year, &month, &day, &hour, &minute, &second, &status, c->errcontext.tempErrStr); snprintf(out,outlen,"time.fromCalendar(%d,%d,%d,%d,%d,%.4f,\"UTC\")",year,month,day,hour,minute,second); } else { int status=0; char timezone[FNAME_LENGTH]; double offset; ppl_calendarTimezoneSet(c, 0, NULL); ppl_calendarTimezoneOffset(c, o->real, timezone, &offset); ppl_dateString(c, out, o->real+offset, NULL, timezone, &status, c->errcontext.tempErrStr); ppl_calendarTimezoneUnset(c); } break; case PPLOBJ_COL: { int i=0,n; int ct=floor(o->exponent[0]+0.01); if (ct == SW_COLSPACE_CMYK) { strncpy(out+i, "cmyk(", outlen-i); n=4; } else if (ct == SW_COLSPACE_RGB) { strncpy(out+i, "rgb(" , outlen-i); n=3; } else if (ct == SW_COLSPACE_HSB) { strncpy(out+i, "hsb(" , outlen-i); n=3; } else { ppl_warning(&c->errcontext, ERR_INTERNAL, "Unknown color space in pplObjPrint."); strncpy(out+i, "ERR(", outlen-i); n=0; } i+=strlen(out+i); if (n>=1) { strcpy(out+i,ppl_numericDisplay(o->exponent[ 8], c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); } if (n>=2) { out[i++]=','; strcpy(out+i,ppl_numericDisplay(o->exponent[ 9], c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); } if (n>=3) { out[i++]=','; strcpy(out+i,ppl_numericDisplay(o->exponent[10], c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); } if (n>=4) { out[i++]=','; strcpy(out+i,ppl_numericDisplay(o->exponent[11], c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); } strncpy(out+i, ")", outlen-i); break; } case PPLOBJ_DICT: { const int expand = (modIterDepth<8); int i=0, first=1, prevMod=0; dictIterator *iter = ppl_dictIterateInit((dict *)o->auxil); char *key; pplObj *item; if (!expand) strcpy(out+i,"{ ... }"); else { out[i++]='{'; while ((item = (pplObj *)ppl_dictIterate(&iter, &key))!=NULL) { if ((item->objType==PPLOBJ_GLOB) || (item->objType==PPLOBJ_ZOM)) continue; // Hide globals and zombies if (!first) { out[i++]=','; if (prevMod) { out[i++]='\n'; } out[i++]=' '; } ppl_strEscapify(key, out+i); i+=strlen(out+i); sprintf(out+i,":"); i+=strlen(out+i); pplObjPrint(c, item, NULL, out+i, outlen-i, 1, modIterDepth+1); i+=strlen(out+i); if (i>outlen-400) { strncpy(out+i,", ...",outlen-i); i+=strlen(out+i); break; } first=0; prevMod = item->objType == PPLOBJ_MOD; } strncpy(out+i,"}",outlen-i); } break; } case PPLOBJ_USER: case PPLOBJ_MOD: { int i=0, k; const int expand = (modIterDepth==0); dictIterator *iter = ppl_dictIterateInit((dict *)o->auxil); char *key; pplObj *item; sprintf(out+i, (t==PPLOBJ_MOD)?"module {":"module instance {"); i+=strlen(out+i); if (!expand) strcpy(out+i," ... }"); else { out[i++]='\n'; while ((item = (pplObj *)ppl_dictIterate(&iter, &key))!=NULL) { int j=i; if ((item->objType==PPLOBJ_GLOB) || (item->objType==PPLOBJ_ZOM)) continue; // Hide globals and zombies for (k=0; k<=modIterDepth; k++) { out[i++]=' '; out[i++]=' '; } strcpy(out+i, key); i+=strlen(out+i); while (ioutlen-400) { strncpy(out+i," ...\n",outlen-i); i+=strlen(out+i); break; } } if (iauxil); pplObj *item; if (!expand) strcpy(out+i,"[ ... ]"); else { out[i++]='['; while ((item = (pplObj *)ppl_listIterate(&iter))!=NULL) { if (!first) { out[i++]=','; if (prevMod) { out[i++]='\n'; } out[i++]=' '; } pplObjPrint(c, item, NULL, out+i, outlen-i, 1, modIterDepth+1); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,", ..."); i+=strlen(out+i); break; } first=0; prevMod = item->objType == PPLOBJ_MOD; } strcpy(out+i,"]"); } break; } case PPLOBJ_VEC: { int i=0, j=0; double real,imag; char *unit; o->real=1; o->imag=0; o->flagComplex=0; unit = ppl_printUnit(c,o,&real,&imag,1,1,SW_DISPLAY_T); if (o->dimensionless) real=1; gsl_vector *v = ((pplVector *)(o->auxil))->v; strcpy(out+i,"vector("); i+=strlen(out+i); for(j=0; jsize; j++) { if (j>0) { out[i++]=','; out[i++]=' '; } strcpy(out+i,ppl_numericDisplay(gsl_vector_get(v,j)*real, c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,", ..."); i+=strlen(out+i); break; } } strcpy(out+i,")"); i+=strlen(out+i); if (!o->dimensionless) sprintf(out+i, "%s", unit); break; } case PPLOBJ_MAT: { int i=0, j=0, k=0; double real,imag; char *unit; o->real=1; o->imag=0; o->flagComplex=0; unit = ppl_printUnit(c,o,&real,&imag,1,1,SW_DISPLAY_T); if (o->dimensionless) real=1; gsl_matrix *m = ((pplMatrix *)(o->auxil))->m; if (internal || (typeable==SW_DISPLAY_T)) { strcpy(out+i,"matrix("); i+=strlen(out+i); for(j=0; jsize1; j++) { if (j>0) { out[i++]=','; out[i++]=' '; } out[i++]='['; for(k=0; ksize2; k++) { if (k>0) { out[i++]=','; out[i++]=' '; } strcpy(out+i,ppl_numericDisplay(gsl_matrix_get(m,j,k)*real, c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,", ..."); i+=strlen(out+i); break; } } strcpy(out+i,"]"); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,", ..."); i+=strlen(out+i); break; } } strcpy(out+i,")"); i+=strlen(out+i); if (!o->dimensionless) sprintf(out+i, "%s", unit); } else { const int unitLine = m->size1/2; for(j=0; jsize1; j++) { strcpy(out+i,"("); i+=strlen(out+i); for(k=0; ksize2; k++) { if (k>0) { out[i++]=','; out[i++]=' '; } strcpy(out+i,ppl_numericDisplay(gsl_matrix_get(m,j,k)*real, c->numdispBuff[0], NSigFigs, (typeable==SW_DISPLAY_L))); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,", ..."); i+=strlen(out+i); break; } } if ((j!=unitLine)||(o->dimensionless)) strcpy (out+i,")\n"); else sprintf(out+i,") %s\n",unit); i+=strlen(out+i); if (i>outlen-400) { strcpy(out+i,"...\n"); i+=strlen(out+i); break; } } } break; } case PPLOBJ_FILE: { strcpy(out, ""); break; } case PPLOBJ_FUNC: { const char *fnname = (oname==NULL)?"function":oname; const pplFunc *f = (pplFunc *)o->auxil; int first = 1, i=0; int indent = 16*(modIterDepth>0) + 2*modIterDepth; for ( ; f!=NULL ; f=f->next , first=0) { const int t = f->functionType; if (!first) { int j; out[i++]='\n'; for (j=0; jdescription); i+=strlen(out+i); break; case PPL_FUNC_USERDEF: { int j=-1, k, l, m; for (k=0; kmaxArgs; k++) if (f->minActive[k] || f->maxActive[k]) j=k; sprintf(out+i,"%s(",fnname); i+=strlen(out+i); for (l=0, m=0; lmaxArgs; l++, m++) { for ( ; f->argList[m]!='\0'; m++) out[i++] = f->argList[m]; out[i++] = ','; } if (f->maxArgs>0) i--; // Remove final comma from list of arguments out[i++] = ')'; for (k=0; k<=j; k++) { out[i++] = '['; if (f->minActive[k]) { sprintf(out+i,"%s", ppl_unitsNumericDisplay(c, f->min+k, 0, 0, 0)); i+=strlen(out+i); } out[i++] = ':'; if (f->maxActive[k]) { sprintf(out+i,"%s", ppl_unitsNumericDisplay(c, f->max+k, 0, 0, 0)); i+=strlen(out+i); } out[i++] = ']'; } if (f->functionPtr==NULL) sprintf(out+i,"="); else sprintf(out+i,"=%s",((pplExpr *)f->functionPtr)->ascii); i+=strlen(out+i); break; } case PPL_FUNC_SPLINE: case PPL_FUNC_INTERP2D: case PPL_FUNC_BMPDATA: { splineDescriptor *s = (splineDescriptor *)f->functionPtr; sprintf(out+i,"%s(x)= [%s interpolation of data from the %sfile '%s']", fnname, s->splineType, (f->functionType == PPL_FUNC_BMPDATA)?"bitmap ":"", s->filename ); i+=strlen(out+i); break; } case PPL_FUNC_HISTOGRAM: { sprintf(out+i,"%s(x)= [histogram of data from the file '%s']", fnname, ((histogramDescriptor *)f->functionPtr)->filename ); i+=strlen(out+i); break; } case PPL_FUNC_FFT: { sprintf(out+i,"%s(x)= [%d-dimensional fft]", fnname, ((FFTDescriptor *)f->functionPtr)->Ndims ); i+=strlen(out+i); break; } case PPL_FUNC_SUBROUTINE: { int l,m; sprintf(out+i,"%s(", fnname); i+=strlen(out+i); for (l=0, m=0; lmaxArgs; l++, m++) { for ( ; f->argList[m]!='\0'; m++) out[i++] = f->argList[m]; out[i++] = ','; } if (f->maxArgs>0) i--; // Remove final comma from list of arguments sprintf(out+i,") = [subroutine]"); i+=strlen(out+i); break; } default: strcpy(out, ""); break; } } break; } case PPLOBJ_TYPE: { int i=0; strcpy(out, "auxil))->id>=0) { strcpy(out+i, ": "); i+=strlen(out+i); strcpy(out+i, pplObjTypeNames[((pplType *)(o->auxil))->id]); i+=strlen(out+i); } strcpy(out+i, ">"); break; } case PPLOBJ_NULL: { strcpy(out, "null"); break; } case PPLOBJ_EXC: { int i=0; strcpy (out , "auxil, outlen-i); i+=strlen(out+i); strncpy(out+i, ">", outlen-i); i+=strlen(out+i); out[outlen-1]='\0'; break; } case PPLOBJ_GLOB: { strcpy(out, ""); break; } case PPLOBJ_ZOM: { strcpy(out, ""); break; } case PPLOBJ_EXP: { strcpy(out, ""); break; } case PPLOBJ_BYT: { strcpy(out, ""); break; } default: strcpy(out, ""); break; } out[outlen-1]='\0'; return; } pyxplot-0.9.2/src/userspace/calendars.c0000664000175000017500000005116412026340554016514 0ustar dcf21dcf21// calendars.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: calendars.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CALENDARS_C 1 #include #include #include #include #include #include #include "userspace/calendars.h" #include "userspace/context.h" #include "settings/settingTypes.h" #include "stringTools/strConstants.h" // Routines for looking up the dates when the transition between the Julian calendar and the Gregorian calendar occurred void ppl_switchOverCalDate(ppl_context *ct, double *LastJulian, double *FirstGregorian) { switch (ct->set->term_current.CalendarIn) { case SW_CALENDAR_GREGORIAN: { *LastJulian = -HUGE_VAL; *FirstGregorian = -HUGE_VAL; return; } case SW_CALENDAR_JULIAN : { *LastJulian = HUGE_VAL; *FirstGregorian = HUGE_VAL; return; } case SW_CALENDAR_BRITISH : { *LastJulian = 17520902.0; *FirstGregorian = 17520914.0; return; } case SW_CALENDAR_FRENCH : { *LastJulian = 15821209.0; *FirstGregorian = 15821220.0; return; } case SW_CALENDAR_CATHOLIC : { *LastJulian = 15821004.0; *FirstGregorian = 15821015.0; return; } case SW_CALENDAR_RUSSIAN : { *LastJulian = 19180131.0; *FirstGregorian = 19180214.0; return; } case SW_CALENDAR_GREEK : { *LastJulian = 19230215.0; *FirstGregorian = 19230301.0; return; } default : ppl_fatal(&ct->errcontext,__FILE__,__LINE__,"Internal Error: Calendar option is set to an illegal setting."); } } double ppl_switchOverJD(ppl_context *ct) { switch (ct->set->term_current.CalendarOut) { case SW_CALENDAR_GREGORIAN: return -HUGE_VAL; case SW_CALENDAR_JULIAN : return HUGE_VAL; case SW_CALENDAR_BRITISH : return 2361222.0; case SW_CALENDAR_FRENCH : return 2299227.0; case SW_CALENDAR_CATHOLIC : return 2299161.0; case SW_CALENDAR_RUSSIAN : return 2421639.0; case SW_CALENDAR_GREEK : return 2423480.0; default : ppl_fatal(&ct->errcontext,__FILE__,__LINE__,"Internal Error: Calendar option is set to an illegal setting."); } return 0; // Never gets here } // Functions for looking up the names of the Nth calendar month and the Nth day of the week char *ppl_getMonthName(ppl_context *ct, int i) { switch (ct->set->term_current.CalendarOut) { case SW_CALENDAR_HEBREW: switch (i) { case 1: return "Tishri"; case 2: return "Heshvan"; case 3: return "Kislev"; case 4: return "Tevet"; case 5: return "Shevat"; case 6: return "Adar"; case 7: return "Veadar"; case 8: return "Nisan"; case 9: return "Iyar"; case 10: return "Sivan"; case 11: return "Tammuz"; case 12: return "Av"; case 13: return "Elul"; default: return "???"; } case SW_CALENDAR_ISLAMIC: switch (i) { case 1: return "Muharram"; case 2: return "Safar"; case 3: return "Rabi'al-Awwal"; case 4: return "Rabi'ath-Thani"; case 5: return "Jumada l-Ula"; case 6: return "Jumada t-Tania"; case 7: return "Rajab"; case 8: return "Sha'ban"; case 9: return "Ramadan"; case 10: return "Shawwal"; case 11: return "Dhu l-Qa'da"; case 12: return "Dhu l-Hijja"; default: return "???"; } default: switch (i) { case 1: return "January"; case 2: return "February"; case 3: return "March"; case 4: return "April"; case 5: return "May"; case 6: return "June"; case 7: return "July"; case 8: return "August"; case 9: return "September"; case 10: return "October"; case 11: return "November"; case 12: return "December"; default: return "???"; } } return "???"; } char *ppl_getWeekDayName(ppl_context *ct, int i) { if (i<0) i+=7; switch (i) { case 0: return "Monday"; case 1: return "Tuesday"; case 2: return "Wednesday"; case 3: return "Thursday"; case 4: return "Friday"; case 5: return "Saturday"; case 6: return "Sunday"; } return "???"; } // Routines for converting between unix times and the Hebrew calendar static int hebrewMonthLengths[6][13] = { {30,29,29,29,30,29, 0,30,29,30,29,30,29}, // Deficient Common Year {30,29,30,29,30,29, 0,30,29,30,29,30,29}, // Regular Common Year {30,30,30,29,30,29, 0,30,29,30,29,30,29}, // Complete Common Year {30,29,29,29,30,30,29,30,29,30,29,30,29}, // Deficient Embolismic Year {30,29,30,29,30,30,29,30,29,30,29,30,29}, // Regular Embolismic Year {30,30,30,29,30,30,29,30,29,30,29,30,29} }; // Complete Embolismic Year void ppl_getHebrewNewYears(ppl_context *ct, int GregYear, int *YearNumbers, double *JDs, int *YearTypes) { int i; long X,C,S,A,a,b,j,D,MONTH=3; double Q, JD, r; for (i=0; i<3; i++) // Return THREE new year numbers and Julian Day numbers, and YearTypes for the first two. { X = GregYear-1+i; C = X/100; S = (3*C-5)/4; A = X + 3760; a = (12*X+12)%19; // Work out the date of the passover in the Hebrew year A b = X%4; Q = -1.904412361576 + 1.554241796621*a + 0.25*b - 0.003177794022*X + S; j = (((long)Q) + 3*X + 5*b + 2 - S)%7; r = Q-((long)Q); if ((j==2)||(j==4)||(j==6) ) D = ((long)Q)+23; else if ((j==1)&&(a> 6)&&(r>=0.632870370)) D = ((long)Q)+24; else if ((j==0)&&(a>11)&&(r>=0.897723765)) D = ((long)Q)+23; else D = ((long)Q)+22; // D is day when 15 Nisan falls after 1st March in the Gregorian year X b = (X/400) - (X/100) + (X/4); // Gregorian calendar JD = 365.0*X - 679004.0 + 2400000.5 + b + floor(30.6001*(MONTH+1)) + D; YearNumbers[i] = A + 1; JDs [i] = JD + 163; // 1 Tishri (New Year) for next year falls 163 days after 15 Nisan a = (A+1)%19; if ((a==0)||(a==3)||(a==6)||(a==8)||(a==11)||(a==14)||(a==17)) YearTypes[i] = 3; else YearTypes[i] = 0; } // We've so far worked out whether years are Common or Embolismic. Now need to work out how many days there will be in each year. for (i=0; i<2; i++) { if (YearTypes[i]==0) YearTypes[i] = JDs[i+1]-JDs[i]-353; else YearTypes[i] = 3 + JDs[i+1]-JDs[i]-383; if ((YearTypes[i]<0)||(YearTypes[i]>6)) YearTypes[i]=0; // Something very bad has happened. } return; } double ppl_hebrewToUnixTime(ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText) { int i; int YearNumbers[3], YearTypes[3]; double JD, DayFraction, JDs[3]; if ((month<1)||(month>13)) { *status=1; sprintf(errText, "Supplied month number should be in the range 1-13."); return 0.0; } if ((year <1) ) { *status=1; sprintf(errText, "Supplied year number must be positive for the Hebrew calendar; the calendar is undefined prior to 4760 BC, corresponding to Hebrew year AM 1."); return 0.0; } ppl_getHebrewNewYears(ct, year-3760, YearNumbers, JDs, YearTypes); JD = JDs[0]; for (i=0; ihebrewMonthLengths[ YearTypes[0] ][ i ]) { *status=1; sprintf(errText, "Supplied day number in the Hebrew month of %s in the year AM %d must be in the range 1-%d.", ppl_getMonthName(ct,month), year, hebrewMonthLengths[ YearTypes[1] ][ i ]); return 0.0; } JD += day-1; JD = 86400.0 * (JD - 2440587.5); DayFraction = fabs(hour)*24*60 + fabs(min)*60 + fabs(sec); return JD + DayFraction; } void ppl_hebrewFromUnixTime(ppl_context *ct, double UT, int *year, int *month, int *day, int *status, char *errText) { long a,c,d,e,f; int i,j; int JulMon, JulYr; int YearNumbers[3], YearTypes[3]; double JDs[3]; double JD = (UT / 86400.0) + 2440587.5; // First work out date in Julian calendar a = JD + 0.5; // Number of whole Julian days. b = Number of centuries since the Council of Nicaea. c = Julian Day number as if century leap years happened. c = a+1524; d = (c-122.1)/365.25; // Number of 365.25 periods, starting the year at the end of February e = 365*d + d/4; // Number of days accounted for by these f = (c-e)/30.6001; // Number of 30.6001 days periods (a.k.a. months) in remainder //JulDay = (int)floor(c-e-(int)(30.6001*f)); JulMon = (int)floor(f-1-12*(f>=14)); JulYr = (int)floor(d-4715-(JulMon>=3)); ppl_getHebrewNewYears(ct, JulYr, YearNumbers, JDs, YearTypes); i = (JD=hebrewMonthLengths[ YearTypes[i] ][ j ]) JD -= hebrewMonthLengths[ YearTypes[i] ][ j ]; else break; if (year != NULL) *year = YearNumbers[i]; if (month!= NULL) *month = j+1; if (day != NULL) *day = ((int)JD+1); return; } // Routines for converting between unix times and the Islamic calendar double ppl_islamicToUnixTime(ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText) { long N,Q,R,A,W,Q1,Q2,G,K,E,J,X,JD; double DayFraction; if ((month<1)||(month>12)) { *status=1; sprintf(errText, "Supplied month number should be in the range 1-12."); return 0.0; } if ((year <1) ) { *status=1; sprintf(errText, "Supplied year number must be positive for the Islamic calendar; the calendar is undefined prior to AD 622 Jul 18, corresponding to AH 1 Muh 1."); return 0.0; } N = day + (long)(29.5001*(month-1)+0.99); Q = year/30; R = year%30; A = (long)((11*R+3)/30); W = 404*Q+354*R+208+A; Q1 = W/1461; Q2 = W%1461; G = 621 + 4*((long)(7*Q+Q1)); K = Q2/365.2422; E = 365.2422*K; J = Q2-E+N-1; X = G+K; if ((J>366) && (X%4==0)) { J-=366; X++; } else if ((J>365) && (X%4 >0)) { J-=365; X++; } JD = 365.25*(X-1) + 1721423 + J - 0.5; JD = 86400.0 * (JD - 2440587.5); DayFraction = fabs(hour)*24*60 + fabs(min)*60 + fabs(sec); return JD + DayFraction; } void ppl_islamicFromUnixTime(ppl_context *ct, double UT, int *year, int *month, int *day, int *status, char *errText) { long a,b,c,d,e,f; int JulDay, JulMon, JulYr; long W,N,A,B,C,C2,D,Q,R,J,K,O,H,JJ,CL,DL,S,m; double C1; double JD = (UT / 86400.0) + 2440587.5; if (JD<1948439.5) { *status=1; sprintf(errText, "Supplied year number must be positive for the Islamic calendar; the calendar is undefined prior to AD 622 Jul 18, corresponding to AH 1 Muh 1."); return; } // First work out date in Julian calendar a = JD + 0.5; // Number of whole Julian days. b = Number of centuries since the Council of Nicaea. c = Julian Day number as if century leap years happened. b=0; c=a+1524; d = (c-122.1)/365.25; // Number of 365.25 periods, starting the year at the end of February e = 365*d + d/4; // Number of days accounted for by these f = (c-e)/30.6001; // Number of 30.6001 days periods (a.k.a. months) in remainder JulDay = (int)floor(c-e-(int)(30.6001*f)); JulMon = (int)floor(f-1-12*(f>=14)); JulYr = (int)floor(d-4715-(JulMon>=3)); //alpha = (JD-1867216.25)/36524.25; // See pages 75-76 of "Astronomical Algorithms", by Jean Meeus //if (JD<2299161) beta = (JD+0.5); //else beta = (JD+0.5) + 1 + alpha - ((long)(alpha/4)); c = (b-122.1)/365.25; d = 365.25*c; e = (b-d)/30.6001; W = 2-(JulYr%4==0); N = ((long)((275*JulMon)/9)) - W*((long)((JulMon+9)/12)) + JulDay - 30; A = JulYr-623; B = A/4; C = A%4; C1 = 365.2501*C; C2 = C1; if (C1-C2>0.5) C2++; D = 1461*B+170+C2; Q = D/10631; R = D%10631; J = R/354; K = R%354; O = (11*J+14)/30; H = 30*Q+J+1; JJ = K-O+N-1; if (JJ>354) { CL = H%30; DL = (11*CL+3)%30; if (DL<19) { JJ-=354; H++; } else if (DL>18) { JJ-=355; H++; } if (JJ==0) { JJ=355; H--; } } S = (JJ-1)/29.5; m = 1+S; d = JJ-29.5*S; if (JJ==355) { m=12; d=30; } if (year !=NULL) *year = (int)H; if (month!=NULL) *month = (int)m; if (day !=NULL) *day = (int)d; return; } // Routines for converting between unix times and calendar dates in Gregorian and Julian calendars double ppl_toUnixTime(ppl_context *ct, int year, int month, int day, int hour, int min, int sec, int *status, char *errText) { double JD, DayFraction, LastJulian, FirstGregorian, ReqDate; int b; if ((year<-1e6)||(year>1e6)||(!gsl_finite(year))) { *status=1; sprintf(errText, "Supplied year is too big."); return 0.0; } if ((day <1)||(day >31)) { *status=1; sprintf(errText, "Supplied day number should be in the range 1-31."); return 0.0; } if ((hour <0)||(hour >23)) { *status=1; sprintf(errText, "Supplied hour number should be in the range 0-23."); return 0.0; } if ((min <0)||(min >59)) { *status=1; sprintf(errText, "Supplied minute number should be in the range 0-59."); return 0.0; } if ((sec <0)||(sec >59)) { *status=1; sprintf(errText, "Supplied second number should be in the range 0-59."); return 0.0; } if (ct->set->term_current.CalendarIn == SW_CALENDAR_HEBREW ) return ppl_hebrewToUnixTime (ct, year, month, day, hour, min, sec, status, errText); else if (ct->set->term_current.CalendarIn == SW_CALENDAR_ISLAMIC) return ppl_islamicToUnixTime(ct, year, month, day, hour, min, sec, status, errText); if ((month<1)||(month>12)) { *status=1; sprintf(errText, "Supplied month number should be in the range 1-12."); return 0.0; } ppl_switchOverCalDate(ct, &LastJulian, &FirstGregorian); ReqDate = 10000.0*year + 100*month + day; if (month<=2) { month+=12; year--; } if (ReqDate <= LastJulian) { b = -2 + ((year+4716)/4) - 1179; } // Julian calendar else if (ReqDate >= FirstGregorian) { b = (year/400) - (year/100) + (year/4); } // Gregorian calendar else { *status=1; sprintf(errText, "The requested date never happened in the %s calendar: it was lost in the transition from the Julian to the Gregorian calendar.", *(char **)ppl_fetchSettingName(&ct->errcontext, ct->set->term_current.CalendarIn, SW_CALENDAR_INT, (void *)SW_CALENDAR_STR, sizeof(char *))); return 0.0; } JD = 365.0*year - 679004.0 + 2400000.5 + b + floor(30.6001*(month+1)) + day; JD = 86400.0 * (JD - 2440587.5); DayFraction = fabs(hour)*3600 + fabs(min)*60 + fabs(sec); return JD + DayFraction; } void ppl_fromUnixTime(ppl_context *ct, double UT, int *year, int *month, int *day, int *hour, int *min, double *sec, int *status, char *errText) { long a,b,c,d,e,f; double DayFraction; int temp; double JD = (UT / 86400.0) + 2440587.5; if (month == NULL) month = &temp; // Dummy placeholder, since we need month later in the calculation if ((JD<-1e8)||(JD>1e8)||(!gsl_finite(JD))) { *status=1; sprintf(errText, "Supplied unix time is too big."); return; } // Work out hours, minutes and seconds DayFraction = (JD+0.5) - floor(JD+0.5); if (hour != NULL) *hour = (int)floor( 24*DayFraction ); if (min != NULL) *min = (int)floor(fmod( 1440*DayFraction , 60)); if (sec != NULL) *sec = fmod(86400*DayFraction , 60) ; // Now work out calendar date if (ct->set->term_current.CalendarOut == SW_CALENDAR_HEBREW ) return ppl_hebrewFromUnixTime (ct, JD, year, month, day, status, errText); else if (ct->set->term_current.CalendarOut == SW_CALENDAR_ISLAMIC) return ppl_islamicFromUnixTime(ct, JD, year, month, day, status, errText); a = JD + 0.5; // Number of whole Julian days. b = Number of centuries since the Council of Nicaea. c = Julian Day number as if century leap years happened. if (a < ppl_switchOverJD(ct)) { b=0; c=a+1524; } // Julian calendar else { b=(a-1867216.25)/36524.25; c=a+b-(b/4)+1525; } // Gregorian calendar d = (c-122.1)/365.25; // Number of 365.25 periods, starting the year at the end of February e = 365*d + d/4; // Number of days accounted for by these f = (c-e)/30.6001; // Number of 30.6001 days periods (a.k.a. months) in remainder if (day != NULL) *day = (int)floor(c-e-(int)(30.6001*f)); *month = (int)floor(f-1-12*(f>=14)); if (year != NULL) *year = (int)floor(d-4715-(*month>=3)); return; } // String representations of dates void ppl_dateString(ppl_context *ct, char *out, double UT, const char *format, const char *timezone, int *status, char *errText) { int j=0,k=0; int year, month, day, hour, min; double sec; if (format==NULL) format="%a %Y %b %d %H:%M:%S %Z"; *status=0; ppl_fromUnixTime(ct, UT, &year, &month, &day, &hour, &min, &sec, status, errText); if (*status) return; // Loop through format string making substitutions for (j=0; format[j]!='\0'; j++) { if (format[j]!='%') { out[k++] = format[j]; continue; } switch (format[j+1]) { case '%': sprintf(out+k, "%%"); break; case 'a': sprintf(out+k, "%s", ppl_getWeekDayName(ct, floor( fmod(UT/3600/24+3 , 7) ))); out[k+3]='\0'; break; case 'A': sprintf(out+k, "%s", ppl_getWeekDayName(ct, floor( fmod(UT/3600/24+3 , 7) ))); break; case 'b': sprintf(out+k, "%s", ppl_getMonthName(ct, month)); out[k+3]='\0'; break; case 'B': sprintf(out+k, "%s", ppl_getMonthName(ct, month)); break; case 'C': sprintf(out+k, "%d", (year/100)+1); break; case 'd': sprintf(out+k, "%d", day); break; case 'H': sprintf(out+k, "%02d", hour); break; case 'I': sprintf(out+k, "%02d", ((hour-1)%12)+1); break; case 'k': sprintf(out+k, "%d", hour); break; case 'l': sprintf(out+k, "%d", ((hour-1)%12)+1); break; case 'm': sprintf(out+k, "%02d", month); break; case 'M': sprintf(out+k, "%02d", min); break; case 'p': sprintf(out+k, "%s", (hour<12)?"am":"pm"); break; case 'S': sprintf(out+k, "%02d", (int)sec); break; case 'y': sprintf(out+k, "%d", year%100); break; case 'Y': sprintf(out+k, "%d", year); break; case 'Z': sprintf(out+k, "%s", timezone); break; default: { *status=1; sprintf(errText,"Format string supplied to convert date to string contains unrecognised substitution token '%%%c'.",format[j+1]); return; } } j++; k += strlen(out+k); } out[k]='\0'; // Null terminate string } void ppl_timeDiffStr(ppl_context *ct, char *out, double UT1, double UT2, const char *format, int *status, char *errText) { int j=0,k=0; long gapYears, gapDays, gapHours, gapMinutes, gapSeconds; gapYears = (UT2 - UT1) / 365 / 3600 / 24; gapDays = (UT2 - UT1) / 3600 / 24; gapHours = (UT2 - UT1) / 3600; gapMinutes = (UT2 - UT1) / 60; gapSeconds = (UT2 - UT1); // Loop through format string making substitutions for (j=0; format[j]!='\0'; j++) { if (format[j]!='%') { out[k++] = format[j]; continue; } switch (format[j+1]) { case '%': sprintf(out+k, "%%"); break; case 'Y': sprintf(out+k, "%ld", gapYears); break; case 'D': sprintf(out+k, "%ld", gapDays); break; case 'd': sprintf(out+k, "%ld", gapDays%365); break; case 'H': sprintf(out+k, "%ld", gapHours); break; case 'h': sprintf(out+k, "%ld", gapHours%24); break; case 'M': sprintf(out+k, "%ld", gapMinutes); break; case 'm': sprintf(out+k, "%ld", gapMinutes%60); break; case 'S': sprintf(out+k, "%ld", gapSeconds); break; case 's': sprintf(out+k, "%ld", gapSeconds%60); break; default: { *status=1; sprintf(errText,"Format string supplied to convert time interval to string contains unrecognised substitution token '%%%c'.",format[j+1]); return; } } j++; k += strlen(out + k); } out[k]='\0'; // Null terminate string return; } void ppl_calendarTimezoneSet(ppl_context *ct, int specified, char *tz) { if (specified) setenv("TZ",tz,1); else setenv("TZ",ct->set->term_current.timezone,1); return; } void ppl_calendarTimezoneUnset(ppl_context *ct) { setenv("TZ","UTC",1); return; } void ppl_calendarTimezoneOffset(ppl_context *ct, double unixTime, char *tzNameOut, double *offset) { struct tm *t; int out=0,i; for (i=0;i<2;i++) { time_t in = (time_t)(unixTime-out); t = localtime(&in); out = (int)t->tm_gmtoff; } if (offset !=NULL) *offset=out; if (tzNameOut!=NULL) strcpy(tzNameOut, t->tm_zone); return; } pyxplot-0.9.2/src/texify.h0000664000175000017500000000204512026340554014075 0ustar dcf21dcf21// texify.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: texify.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _TEXIFY_H #define _TEXIFY_H 1 #include "userspace/context.h" void ppl_texify_string(char *in, char *out, int inlen, int outlen); void ppl_texify_generic(ppl_context *c, char *in, int inlen, int *end, char *out, int outlen, int *mm_in, int *tr_in); #endif pyxplot-0.9.2/src/settings/0000775000175000017500000000000012026340554014253 5ustar dcf21dcf21pyxplot-0.9.2/src/settings/axes_fns.h0000664000175000017500000000313212026340554016231 0ustar dcf21dcf21// axes_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: axes_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLSET_AXES_FNS_H #define _PPLSET_AXES_FNS_H 1 #include "settings/settings.h" #include "userspace/context.h" void pplaxis_destroy (ppl_context *context, pplset_axis *in); void pplaxis_copy (ppl_context *context, pplset_axis *out, const pplset_axis *in); void pplaxis_copyTics (ppl_context *context, pplset_axis *out, const pplset_axis *in); void pplaxis_copyMTics(ppl_context *context, pplset_axis *out, const pplset_axis *in); unsigned char pplaxis_cmpTics (ppl_context *context, const pplset_tics *ta, const pplset_tics *tb, const pplObj *ua, const pplObj *ub, const int la, const int lb); double pplaxis_GetPosition (double xin, pplset_axis *xa, int xrn, unsigned char AllowOffBounds); double pplaxis_InvGetPosition(double xin, pplset_axis *xa); #endif pyxplot-0.9.2/src/settings/papersizes.c0000664000175000017500000001162112026340554016605 0ustar dcf21dcf21// papersizes.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: papersizes.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "settings/papersizes.h" typedef struct PaperSize { char name[32]; double height; double width; } PaperSize; PaperSize PaperSizeList[129] = { {"crown" , 508 , 381 }, {"demy" , 572 , 445 }, {"double_demy" , 889 , 597 }, {"elephant" , 711 , 584 }, {"envelope_dl" , 110 , 220 }, // Wider than it is long {"executive" , 267 , 184 }, {"foolscap" , 330 , 203 }, {"government_letter" , 267 , 203 }, {"international_businesscard", 85.60, 53.98}, {"large_post" , 533 , 419 }, {"letter" , 279 , 216 }, {"legal" , 356 , 216 }, {"ledger" , 432 , 279 }, {"medium" , 584 , 457 }, {"monarch" , 267 , 184 }, {"post" , 489 , 394 }, {"quad_demy" ,1143 , 889 }, {"quarto" , 254 , 203 }, {"royal" , 635 , 508 }, {"statement" , 216 , 140 }, {"tabloid" , 432 , 279 }, {"japanese_shiroku4" , 379 , 264 }, {"japanese_shiroku5" , 262 , 189 }, {"japanese_shiroku6" , 188 , 127 }, {"japanese_kiku4" , 306 , 227 }, {"japanese_kiku5" , 227 , 151 }, {"us_businesscard" , 89 , 51 }, {"END" , 0 , 0 } }; void ppl_PaperSizeInit() { double height , width ; double height2, width2; int pos,i,j; static char *SeriesNames[] = {"a","swedish_e","c","swedish_g","b","swedish_f","swedish_d","swedish_h"}; for(pos=0 ; (strcmp(PaperSizeList[pos].name , "END")!=0) ; pos++); strcpy(PaperSizeList[pos].name , "4A0"); height = sqrt(2)*sqrt(4e6/sqrt(2)); // 4A0 has area four square metres width = sqrt(4e6/sqrt(2)); PaperSizeList[pos].width = width; PaperSizeList[pos].height = height; pos++; strcpy(PaperSizeList[pos].name , "2A0"); height = sqrt(2)*sqrt(2e6/sqrt(2)); // 2A0 has area four square metres width = sqrt(2e6/sqrt(2)); PaperSizeList[pos].width = width; PaperSizeList[pos].height = height; pos++; for (i=0; i<11; i++) { height2 = height/sqrt(2); width2 = width /sqrt(2); sprintf(PaperSizeList[pos].name, "japanese_b%d", i); // Japanese B0 - B11 PaperSizeList[pos].width = (width2 + width )/2; PaperSizeList[pos].height = (height2 + height)/2; pos++; for (j=0; j<8; j++) { sprintf(PaperSizeList[pos].name, "%s%d", SeriesNames[j], i); // Logarithmically-spaced series, including the A, B and C-series. PaperSizeList[pos].height = height2 * pow(2.0, ((float)j/16)); PaperSizeList[pos].width = width2 * pow(2.0, ((float)j/16)); pos++; } height = height2 ; width = width2; } strcpy(PaperSizeList[pos].name, "END"); // Marker of end of papersize list return; } void ppl_PaperSizeByName(char *name, double *height, double *width) { int i=0; while (1) { if (strcmp(PaperSizeList[i].name, "END")==0) // The requested papersize doesn't exist { *height = 0.0; *width = 0.0; return; } if (ppl_strCmpNoCase(PaperSizeList[i].name, name)==0) // We've found the requested papersize { *height = PaperSizeList[i].height; *width = PaperSizeList[i].width; return; } i++; } } void ppl_GetPaperName(char *name, double *height, double *width) { int i=0; while (1) { if (strcmp(PaperSizeList[i].name, "END")==0) // The requested papersize doesn't exist { strcpy(name, "User-defined papersize"); return; } if ((fabs(PaperSizeList[i].height - *height) < 0.5 ) && (fabs(PaperSizeList[i].width - *width) < 0.5 )) // We've found the requested papersize { strcpy(name, PaperSizeList[i].name); return; } i++; } } pyxplot-0.9.2/src/settings/colors.h0000664000175000017500000000300512026340554015723 0ustar dcf21dcf21// colors.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: colors.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _COLORS_H #define _COLORS_H 1 #include "parser/parser.h" #include "userspace/context.h" int ppl_colorFromDict (ppl_context *c, parserOutput *in, parserLine *pl, const int *ptab, int stkbase, int fillColor, int *outcol, int *outcolspace, pplExpr **EXPoutcol, double *outcol1, double *outcol2, double *outcol3, double *outcol4, unsigned char *USEcol, unsigned char *USEcol1234); int ppl_colorFromObj (ppl_context *c, const pplObj *col, int *outcol, int *outcolspace, pplExpr **EXPoutcol, double *outcol1, double *outcol2, double *outcol3, double *outcol4, unsigned char *USEcol, unsigned char *USEcol1234); #endif pyxplot-0.9.2/src/settings/axes.c0000664000175000017500000002012412026340554015356 0ustar dcf21dcf21// axes.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: axes.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _AXES_C 1 #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "coreUtils/errorReport.h" #include "expressions/expCompile_fns.h" #include "pplConstants.h" #include "settings/settingTypes.h" #include "settings/axes_fns.h" #include "settings/settings.h" #include "settings/withWords_fns.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" // ------------------------------------------------------ // Functions for creating and destroying axis descriptors // ------------------------------------------------------ void pplaxis_destroy(ppl_context *context, pplset_axis *in) { int i; if (in->format != NULL) { pplExpr_free( in->format ); in->format = NULL; } if (in->label != NULL) { free ( in->label ); in->label = NULL; } if (in->linkusing != NULL) { pplExpr_free((pplExpr *)in->linkusing); in->linkusing = NULL; } if (in->ticsM.tickList != NULL) { free(in->ticsM.tickList); in->ticsM.tickList = NULL; } if (in->ticsM.tickStrs != NULL) { for (i=0; in->ticsM.tickStrs[i]!=NULL; i++) free(in->ticsM.tickStrs[i]); free(in->ticsM.tickStrs); in->ticsM.tickStrs = NULL; } if (in->tics.tickList != NULL) { free(in->tics.tickList ); in->tics.tickList = NULL; } if (in->tics.tickStrs != NULL) { for (i=0; in->tics.tickStrs[i]!=NULL; i++) free(in->tics.tickStrs[i]); free(in->tics.tickStrs ); in->tics.tickStrs = NULL; } return; } // c->set->axis_default is a safe fallback axis because it contains no malloced strings #define XMALLOC(X) (tmp = malloc(X)); if (tmp==NULL) { ppl_error(&context->errcontext, ERR_MEMORY, -1, -1,"Out of memory"); *out = context->set->axis_default; return; } void pplaxis_copy(ppl_context *context, pplset_axis *out, const pplset_axis *in) { void *tmp; *out = *in; if (in->format != NULL) { out->format = (void *)pplExpr_cpy((pplExpr *)in->format ); } if (in->label != NULL) { out->label = (char *)XMALLOC(strlen(in->label )+1); strcpy(out->label , in->label ); } if (in->linkusing != NULL) { out->linkusing= (void *)pplExpr_cpy((pplExpr *)in->linkusing); } pplaxis_copyTics (context,out,in); pplaxis_copyMTics(context,out,in); return; } void pplaxis_copyTics(ppl_context *context, pplset_axis *out, const pplset_axis *in) { int i=0,j; void *tmp; if (in->tics.tickStrs != NULL) { for (i=0; in->tics.tickStrs[i]!=NULL; i++); out->tics.tickStrs= XMALLOC((i+1)*sizeof(char *)); for (j=0; jtics.tickStrs[j] = XMALLOC(strlen(in->tics.tickStrs[j])+1); strcpy(out->tics.tickStrs[j], in->tics.tickStrs[j]); } out->tics.tickStrs[i] = NULL; } if (in->tics.tickList != NULL) { out->tics.tickList= (double *)XMALLOC((i+1)*sizeof(double)); memcpy(out->tics.tickList, in->tics.tickList, (i+1)*sizeof(double)); // NB: For this to be safe, tics.tickLists MUST have double to correspond to NULL in tics.tickStrs } return; } void pplaxis_copyMTics(ppl_context *context, pplset_axis *out, const pplset_axis *in) { int i=0,j; void *tmp; if (in->ticsM.tickStrs != NULL) { for (i=0; in->ticsM.tickStrs[i]!=NULL; i++); out->ticsM.tickStrs= XMALLOC((i+1)*sizeof(char *)); for (j=0; jticsM.tickStrs[j] = XMALLOC(strlen(in->ticsM.tickStrs[j])+1); strcpy(out->ticsM.tickStrs[j], in->ticsM.tickStrs[j]); } out->ticsM.tickStrs[i] = NULL; } if (in->ticsM.tickList != NULL) { out->ticsM.tickList= (double *)XMALLOC((i+1)*sizeof(double)); memcpy(out->ticsM.tickList, in->ticsM.tickList, (i+1)*sizeof(double)); // NB: For this to be safe, tics.tickLists MUST have double to correspond to NULL in tics.tickStrs } return; } unsigned char pplaxis_cmpTics(ppl_context *context, const pplset_tics *ta, const pplset_tics *tb, const pplObj *ua, const pplObj *ub, const int la, const int lb) { int i,j; if ((ta->tickList==NULL)&&(tb->tickList==NULL)&&(!ta->tickMinSet)&&(!tb->tickMinSet)&&(!ta->tickStepSet)&&(!tb->tickStepSet)&&(!ta->tickMaxSet)&&(!tb->tickMaxSet)) return 1; if (!ppl_unitsDimEqual(ua,ub)) return 0; if ((ta->tickList==NULL)!=(tb->tickList==NULL)) return 0; if (ta->tickList==NULL) { if (la!=lb) return 0; if (ta->tickMinSet!=tb->tickMinSet) return 0; if (ta->tickMaxSet!=tb->tickMaxSet) return 0; if (ta->tickStepSet!=tb->tickStepSet) return 0; if (ta->tickMinSet && (ta->tickMin!=tb->tickMin)) return 0; if (ta->tickMaxSet && (ta->tickMax!=tb->tickMax)) return 0; if (ta->tickStepSet && (ta->tickStep!=tb->tickStep)) return 0; } else { for (i=0; ta->tickStrs[i]!=NULL; i++); for (j=0; tb->tickStrs[j]!=NULL; j++); if (i!=j) return 0; // tick lists have different lengths for (j=0; jtickList[j] != tb->tickList[j]) return 0; if (strcmp(ta->tickStrs[j], tb->tickStrs[j])!=0) return 0; } } return 1; } // Where along this axis, in the range 0 (left) to 1 (right) should the value // xin go? xrn = Region Number for interpolated axes which do not have // monotonically increasing ordinate values. double pplaxis_GetPosition(double xin, pplset_axis *xa, int xrn, unsigned char AllowOffBounds) { int imin, imax, i; if (xa==NULL) return xin; if (xa->AxisLinearInterpolation != NULL) // Axis is linearly interpolated { imin = xa->AxisTurnings[xrn ]; imax = xa->AxisTurnings[xrn+1]; for (i=imin; iAxisLinearInterpolation[i] < xin) && (xa->AxisLinearInterpolation[i+1] >= xin)) || ((xa->AxisLinearInterpolation[i] > xin) && (xa->AxisLinearInterpolation[i+1] <= xin)) ) return (i + (xin-xa->AxisLinearInterpolation[i])/(xa->AxisLinearInterpolation[i+1]-xa->AxisLinearInterpolation[i])) / (AXISLINEARINTERPOLATION_NPOINTS-1); } return GSL_NAN; } if (!AllowOffBounds) { if (xa->MaxFinal > xa->MinFinal) { if ((xinMinFinal) || (xin>xa->MaxFinal)) return GSL_NAN; } else { if ((xin>xa->MinFinal) || (xinMaxFinal)) return GSL_NAN; } } if ((xa->LogFinal==SW_BOOL_TRUE) && (xin <= 0)) return GSL_NAN; if (xa->LogFinal!=SW_BOOL_TRUE) return (xin - xa->MinFinal) / (xa->MaxFinal - xa->MinFinal); // Either linear... else return (log(xin)-log(xa->MinFinal)) / (log(xa->MaxFinal)-log(xa->MinFinal)); // ... or logarithmic } // What is the value of this axis at point xin, in the range 0 (left) to 1 (right)? double pplaxis_InvGetPosition(double xin, pplset_axis *xa) { if (xa->AxisLinearInterpolation != NULL) // Axis is linearly interpolated { int i = floor(xin * (AXISLINEARINTERPOLATION_NPOINTS-1)); double x = xin * (AXISLINEARINTERPOLATION_NPOINTS-1) - i; if (i>=AXISLINEARINTERPOLATION_NPOINTS-1) return xa->AxisLinearInterpolation[AXISLINEARINTERPOLATION_NPOINTS-1]; if (i< 0) return xa->AxisLinearInterpolation[0]; return xa->AxisLinearInterpolation[i]*(1-x) + xa->AxisLinearInterpolation[i+1]*x; } if (xa->LogFinal!=SW_BOOL_TRUE) return xa->MinFinal + xin * (xa->MaxFinal - xa->MinFinal); // Either linear... else return xa->MinFinal * pow(xa->MaxFinal / xa->MinFinal , xin); // ... or logarithmic } pyxplot-0.9.2/src/settings/arrows.c0000664000175000017500000002676212026340554015751 0ustar dcf21dcf21// arrows.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: arrows.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "coreUtils/errorReport.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "settings/arrows_fns.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "pplConstants.h" // ------------------------------------------- // ROUTINES FOR MANIPULATING ARROWS STRUCTURES // ------------------------------------------- #define TBADD(et,pos) ppl_tbAdd(context,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define CMPVAL(X,Y) (ppl_unitsDimEqual(&X,&Y) && ppl_dblEqual(X.real , Y.real)) void pplarrow_add(ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab) { int i; int system_x0, system_y0, system_z0, system_x1, system_y1, system_z1; char *tempstr; pplarrow_object *out; pplarrow_add_get_system(PARSE_INDEX_x0_system , system_x0); pplarrow_add_get_system(PARSE_INDEX_y0_system , system_y0); pplarrow_add_get_system(PARSE_INDEX_z0_system , system_z0); pplarrow_add_get_system(PARSE_INDEX_x1_system , system_x1); pplarrow_add_get_system(PARSE_INDEX_y1_system , system_y1); pplarrow_add_get_system(PARSE_INDEX_z1_system , system_z1); pplarrow_add_check_dimensions(PARSE_INDEX_x0 , system_x0); pplarrow_add_check_dimensions(PARSE_INDEX_y0 , system_y0); pplarrow_add_check_dimensions(PARSE_INDEX_z0 , system_z0); pplarrow_add_check_dimensions(PARSE_INDEX_x1 , system_x1); pplarrow_add_check_dimensions(PARSE_INDEX_y1 , system_y1); pplarrow_add_check_dimensions(PARSE_INDEX_z1 , system_z1); pplarrow_add_check_axis(PARSE_INDEX_x0_axis); pplarrow_add_check_axis(PARSE_INDEX_y0_axis); pplarrow_add_check_axis(PARSE_INDEX_z0_axis); pplarrow_add_check_axis(PARSE_INDEX_x1_axis); pplarrow_add_check_axis(PARSE_INDEX_y1_axis); pplarrow_add_check_axis(PARSE_INDEX_z1_axis); i = (int)round(in->stk[ptab[PARSE_INDEX_arrow_id]].real); while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); if ((*inlist != NULL) && ((*inlist)->id == i)) { out = *inlist; ppl_withWordsDestroy(context, &out->style); } else { out = (pplarrow_object *)malloc(sizeof(pplarrow_object)); if (out == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1, "Out of memory."); return; } out->id = i; out->next = *inlist; *inlist = out; } // Check whether arrow head type has been specified tempstr = (char *)in->stk[ptab[PARSE_INDEX_arrow_style]].auxil; if (in->stk[ptab[PARSE_INDEX_arrow_style]].objType!=PPLOBJ_STR) out->pplarrow_style = SW_ARROWTYPE_HEAD; else out->pplarrow_style = ppl_fetchSettingByName(&context->errcontext, tempstr, SW_ARROWTYPE_INT, SW_ARROWTYPE_STR); // Check what style keywords have been specified in the 'with' clause ppl_withWordsFromDict(context, in, pl, ptab, 0, &out->style); out->system_x0 = system_x0; out->system_y0 = system_y0; out->system_z0 = system_z0; out->system_x1 = system_x1; out->system_y1 = system_y1; out->system_z1 = system_z1; pplarrow_add_get_axis(PARSE_INDEX_x0_axis, out->axis_x0); pplarrow_add_get_axis(PARSE_INDEX_y0_axis, out->axis_y0); pplarrow_add_get_axis(PARSE_INDEX_z0_axis, out->axis_z0); pplarrow_add_get_axis(PARSE_INDEX_x1_axis, out->axis_x1); pplarrow_add_get_axis(PARSE_INDEX_y1_axis, out->axis_y1); pplarrow_add_get_axis(PARSE_INDEX_z1_axis, out->axis_z1); pplarrow_add_copy_coordinate(PARSE_INDEX_x0, system_x0,out->x0); pplarrow_add_copy_coordinate(PARSE_INDEX_y0, system_y0,out->y0); pplarrow_add_copy_coordinate(PARSE_INDEX_z0, system_z0,out->z0); pplarrow_add_copy_coordinate(PARSE_INDEX_x1, system_x1,out->x1); pplarrow_add_copy_coordinate(PARSE_INDEX_y1, system_y1,out->y1); pplarrow_add_copy_coordinate(PARSE_INDEX_z1, system_z1,out->z1); return; } void pplarrow_remove(ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab, int quiet) { int pos; pplarrow_object **first; first = inlist; pos = ptab[PARSE_INDEX_0arrow_list]; if ((in->stk[pos].objType!=PPLOBJ_NUM)||(in->stk[pos].real<=0)) pplarrow_list_destroy(context, inlist); // set noarrow with no number specified means all arrows deleted else { while (in->stk[pos].objType == PPLOBJ_NUM) { int i; pos = (int)round(in->stk[pos].real); if (pos<=0) break; i = (int)round(in->stk[pos+ptab[PARSE_INDEX_arrow_id]].real); inlist = first; while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); if ((*inlist != NULL) && ((*inlist)->id == i)) { pplarrow_object *obj = *inlist; *inlist = (*inlist)->next; ppl_withWordsDestroy(context, &obj->style); free(obj); } else if (!quiet) { sprintf(context->errcontext.tempErrStr,"Arrow number %d is not defined", i); ppl_warning(&context->errcontext, ERR_GENERIC, NULL); } } } return; } void pplarrow_unset(ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab) { int pos; pplarrow_object **first; pplarrow_remove(context, inlist, in, pl, ptab, 1); // First of all, remove any arrows which we are unsetting first = inlist; pos = ptab[PARSE_INDEX_0arrow_list]; if ((in->stk[pos].objType!=PPLOBJ_NUM)||(in->stk[pos].real<=0)) { pplarrow_list_destroy(context, inlist); pplarrow_list_copy(context, inlist, &context->set->pplarrow_list_default); // Check to see whether we are unsetting ALL arrows, and if so, use the copy command } else { while (in->stk[pos].objType == PPLOBJ_NUM) { int i; pplarrow_object *obj; pos = (int)round(in->stk[pos].real); if (pos<=0) break; i = (int)round(in->stk[pos+ptab[PARSE_INDEX_arrow_id]].real); obj = context->set->pplarrow_list_default; while ((obj != NULL) && (obj->id < i)) obj = (obj->next); if ((obj != NULL) && (obj->id == i)) { pplarrow_object *new; inlist = first; while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); new = (pplarrow_object *)malloc(sizeof(pplarrow_object)); if (new == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); return; } *new = *obj; new->next = *inlist; ppl_withWordsCpy(context, &new->style, &obj->style); *inlist = new; } } } return; } unsigned char pplarrow_compare(ppl_context *context, pplarrow_object *a, pplarrow_object *b) { if (a->id!=b->id) return 0; if ( (!CMPVAL(a->x0 , b->x0)) || (!CMPVAL(a->y0 , b->y0)) || (!CMPVAL(a->z0 , b->z0)) ) return 0; if ( (!CMPVAL(a->x1 , b->x1)) || (!CMPVAL(a->y1 , b->y1)) || (!CMPVAL(a->z1 , b->z1)) ) return 0; if ( (a->system_x0!=b->system_x0) || (a->system_y0!=b->system_y0) || (a->system_z0!=b->system_z0) ) return 0; if ( (a->system_x1!=b->system_x1) || (a->system_y1!=b->system_y1) || (a->system_z1!=b->system_z1) ) return 0; if ( (a->axis_x0!=b->axis_x0) || (a->axis_y0!=b->axis_y0) || (a->axis_z0!=b->axis_z0) ) return 0; if ( (a->axis_x1!=b->axis_x1) || (a->axis_y1!=b->axis_y1) || (a->axis_z1!=b->axis_z1) ) return 0; if (!ppl_withWordsCmp(context, &a->style , &b->style)) return 0; return 1; } void pplarrow_list_copy(ppl_context *context, pplarrow_object **out, pplarrow_object **in) { *out = NULL; while (*in != NULL) { *out = (pplarrow_object *)malloc(sizeof(pplarrow_object)); if (*out == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); return; } **out = **in; (*out)->next = NULL; ppl_withWordsCpy(context, &(*out)->style, &(*in)->style); in = &((*in )->next); out = &((*out)->next); } return; } void pplarrow_list_destroy(ppl_context *context, pplarrow_object **inlist) { pplarrow_object *obj, **first; first = inlist; while (*inlist != NULL) { obj = *inlist; *inlist = (*inlist)->next; ppl_withWordsDestroy(context, &obj->style); free(obj); } *first = NULL; return; } void pplarrow_print(ppl_context *context, pplarrow_object *in, char *out) { int i; sprintf(out, "from %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_x0, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i = strlen(out); if (in->system_x0==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_x0); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context,&(in->x0),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_y0, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_y0==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_y0); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context,&(in->y0),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_z0, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_z0==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_z0); i+=strlen(out+i); } sprintf(out+i, " %s ", ppl_unitsNumericDisplay(context,&(in->z0),0,0,0)); i+=strlen(out+i); sprintf(out+i, "to %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_x1, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_x1==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_x1); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context,&(in->x1),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_y1, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_y1==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_y1); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context,&(in->y1),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_z1, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_z1==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_z1); i+=strlen(out+i); } sprintf(out+i, " %s", ppl_unitsNumericDisplay(context,&(in->z1),0,0,0)); i+=strlen(out+i); sprintf(out+i, " with %s ", *(char **)ppl_fetchSettingName(&context->errcontext, in->pplarrow_style, SW_ARROWTYPE_INT, (void *)SW_ARROWTYPE_STR, sizeof(char *))); i+=strlen(out+i); ppl_withWordsPrint(context, &in->style, out+i); return; } pyxplot-0.9.2/src/settings/labels_fns.h0000664000175000017500000000343512026340554016541 0ustar dcf21dcf21// labels_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: labels_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLSET_LABELS_FNS_H #define _PPLSET_LABELS_FNS_H 1 #include "coreUtils/dict.h" #include "settings/labels.h" #include "settings/withWords.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppllabel_add (ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab); void ppllabel_remove (ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab, int quiet); void ppllabel_unset (ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab); unsigned char ppllabel_compare (ppl_context *context, ppllabel_object *a, ppllabel_object *b); void ppllabel_list_copy (ppl_context *context, ppllabel_object **out, ppllabel_object **in); void ppllabel_list_destroy(ppl_context *context, ppllabel_object **inlist); void ppllabel_print (ppl_context *context, ppllabel_object *in, char *out); #endif pyxplot-0.9.2/src/settings/settingsInit.c0000664000175000017500000005155112026340554017112 0ustar dcf21dcf21// settingsInit.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: settingsInit.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _SETTINGSINIT_C 1 int cancellationFlag = 0; #include #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/errorReport.h" #include "coreUtils/dict.h" #include "coreUtils/getPasswd.h" #include "coreUtils/memAlloc.h" #include "mathsTools/dcfmath.h" #include "settings/epsColors.h" #include "pplConstants.h" #include "settings/papersizes.h" #include "settings/settings_fns.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "userspace/pplObj_fns.h" void pplset_makedefault(ppl_context *context) { FILE *LocalePipe; int Nchars,i,gotPaperSize; double PaperWidth, PaperHeight; pplObj tempval; char ConfigFname[FNAME_LENGTH], *ConfigFnamePtr = &ConfigFname[0]; char *PaperSizePtr; char *tz; ppl_settings *s = context->set; pplerr_context *se = &context->errcontext; const int default_cols[] = {COLOR_BLACK, COLOR_RED, COLOR_BLUE, COLOR_MAGENTA, COLOR_CYAN, COLOR_BROWN, COLOR_SALMON, COLOR_GRAY, COLOR_GREEN, COLOR_NAVYBLUE, COLOR_PERIWINKLE, COLOR_PINEGREEN, COLOR_SEAGREEN, COLOR_GREENYELLOW, COLOR_ORANGE, COLOR_CARNATIONPINK, COLOR_PLUM, -1}; // Clear settings memset((void *)s, 0, sizeof(s)); // Default palette for (i=0; default_cols[i]>=0; i++) { s->palette_default [i] = default_cols[i]; s->paletteS_default[i] = SW_COLSPACE_CMYK; s->palette1_default[i] = SW_COLOR_CMYK_C[default_cols[i]]; s->palette2_default[i] = SW_COLOR_CMYK_M[default_cols[i]]; s->palette3_default[i] = SW_COLOR_CMYK_Y[default_cols[i]]; s->palette4_default[i] = SW_COLOR_CMYK_K[default_cols[i]]; } s->palette_default[i] = -1; // Default Terminal Settings, used when these values are not changed by any configuration files s->term_default.backup = SW_ONOFF_OFF; s->term_default.BinOrigin.refCount=1; pplObjNum(&(s->term_default.BinOrigin),0,0.0,0.0); s->term_default.BinOriginAuto = 1; s->term_default.BinWidth.refCount=1; pplObjNum(&(s->term_default.BinWidth),0,0.0,0.0); s->term_default.BinWidth.real = 1.0; s->term_default.BinWidthAuto = 1; s->term_default.CalendarIn = SW_CALENDAR_BRITISH; s->term_default.CalendarOut = SW_CALENDAR_BRITISH; s->term_default.color = SW_ONOFF_ON; s->term_default.ComplexNumbers = SW_ONOFF_OFF; s->term_default.display = SW_ONOFF_ON; s->term_default.dpi = 300.0; s->term_default.ExplicitErrors = SW_ONOFF_ON; s->term_default.landscape = SW_ONOFF_OFF; strcpy(s->term_default.LatexPreamble, ""); s->term_default.multiplot = SW_ONOFF_OFF; s->term_default.NumDisplay = SW_DISPLAY_N; strcpy(s->term_default.output, ""); s->term_default.PaperHeight.refCount=1; pplObjNum(&(s->term_default.PaperHeight),0,0.0,0.0); s->term_default.PaperHeight.real = 297.30178 / 1000; s->term_default.PaperHeight.dimensionless = 0; s->term_default.PaperHeight.exponent[UNIT_LENGTH] = 1; strcpy(s->term_default.PaperName, "a4"); s->term_default.PaperWidth.refCount=1; pplObjNum(&(s->term_default.PaperWidth),0,0.0,0.0); s->term_default.PaperWidth.real = 210.2241 / 1000; s->term_default.PaperWidth.dimensionless = 0; s->term_default.PaperWidth.exponent[UNIT_LENGTH] = 1; s->term_default.RandomSeed = 0; s->term_default.SignificantFigures = 8; s->term_default.TermAntiAlias = SW_ONOFF_ON; s->term_default.TermType = SW_TERMTYPE_X11S; s->term_default.TermEnlarge = SW_ONOFF_OFF; s->term_default.TermInvert = SW_ONOFF_OFF; s->term_default.TermTransparent = SW_ONOFF_OFF; s->term_default.UnitScheme = SW_UNITSCH_SI; s->term_default.UnitDisplayPrefix = SW_ONOFF_ON; s->term_default.UnitDisplayAbbrev = SW_ONOFF_ON; s->term_default.UnitAngleDimless = SW_ONOFF_ON; s->term_default.viewer = SW_VIEWER_GV; strcpy(s->term_default.ViewerCmd, ""); tz = getenv("TZ"); if (tz!=NULL) strncpy(s->term_default.timezone , getenv("TZ"), FNAME_LENGTH); else strncpy(s->term_default.timezone , "", FNAME_LENGTH); s->term_default.timezone[FNAME_LENGTH-1]='\0'; // Default Graph Settings, used when these values are not changed by any configuration files s->graph_default.aspect = 1.0; s->graph_default.zaspect = 1.0; s->graph_default.AutoAspect = SW_ONOFF_ON; s->graph_default.AutoZAspect = SW_ONOFF_ON; s->graph_default.AxesColor = COLOR_BLACK; s->graph_default.AxesCol1234Space = SW_COLSPACE_RGB; s->graph_default.AxesColor1 = 0.0; s->graph_default.AxesColor2 = 0.0; s->graph_default.AxesColor3 = 0.0; s->graph_default.AxesColor4 = 0.0; s->graph_default.AxisUnitStyle = SW_AXISUNITSTY_RATIO; s->graph_default.bar = 1.0; s->graph_default.BoxFrom.refCount=1; pplObjNum(&(s->graph_default.BoxFrom),0,0.0,0.0); s->graph_default.BoxFromAuto = 1; s->graph_default.BoxWidth.refCount=1; pplObjNum(&(s->graph_default.BoxWidth),0,0.0,0.0); s->graph_default.BoxWidthAuto = 1; s->graph_default.c1format = NULL; s->graph_default.c1formatset = 0; strcpy(s->graph_default.c1label, ""); s->graph_default.c1LabelRotate = 0.0; s->graph_default.c1TickLabelRotate = 0.0; s->graph_default.c1TickLabelRotation = SW_TICLABDIR_HORI; s->graph_default.clip = SW_ONOFF_OFF; for (i=0; i<4; i++) { s->graph_default.Clog[i] = SW_BOOL_FALSE; s->graph_default.Cmax[i].refCount=1; pplObjNum(&s->graph_default.Cmax[i],0,0.0,0.0); s->graph_default.Cmaxauto[i] = SW_BOOL_TRUE; s->graph_default.Cmin[i].refCount=1; pplObjNum(&s->graph_default.Cmin[i],0,0.0,0.0); s->graph_default.Cminauto[i] = SW_BOOL_TRUE; s->graph_default.Crenorm[i] = SW_BOOL_TRUE; s->graph_default.Creverse[i] = SW_BOOL_FALSE; } s->graph_default.ColKey = SW_ONOFF_ON; s->graph_default.ColKeyPos = SW_COLKEYPOS_R; s->graph_default.ColMapExpr = NULL; s->graph_default.MaskExpr = NULL; s->graph_default.ContoursLabel = SW_ONOFF_OFF; s->graph_default.ContoursListLen = -1; for (i=0; igraph_default.ContoursList[i] = 0.0; s->graph_default.ContoursN = 12; s->graph_default.ContoursUnit.refCount=1; pplObjNum(&s->graph_default.ContoursUnit,0,0.0,0.0); ppl_withWordsZero(context,&(s->graph_default.dataStyle)); s->graph_default.dataStyle.linespoints = SW_STYLE_POINTS; s->graph_default.FontSize = 1.0; ppl_withWordsZero(context,&(s->graph_default.funcStyle)); s->graph_default.funcStyle.linespoints = SW_STYLE_LINES; s->graph_default.grid = SW_ONOFF_OFF; for (i=0; igraph_default.GridAxisX[i] = 0; for (i=0; igraph_default.GridAxisY[i] = 0; for (i=0; igraph_default.GridAxisZ[i] = 0; s->graph_default.GridAxisX[1] = 1; s->graph_default.GridAxisY[1] = 1; s->graph_default.GridAxisZ[1] = 1; s->graph_default.GridMajColor = COLOR_GREY60; s->graph_default.GridMajCol1234Space = SW_COLSPACE_RGB; s->graph_default.GridMajColor1 = 0; s->graph_default.GridMajColor2 = 0; s->graph_default.GridMajColor3 = 0; s->graph_default.GridMajColor4 = 0; s->graph_default.GridMinColor = COLOR_GREY85; s->graph_default.GridMinCol1234Space = SW_COLSPACE_RGB; s->graph_default.GridMinColor1 = 0; s->graph_default.GridMinColor2 = 0; s->graph_default.GridMinColor3 = 0; s->graph_default.GridMinColor4 = 0; s->graph_default.key = SW_ONOFF_ON; s->graph_default.KeyColumns = 0; s->graph_default.KeyPos = SW_KEYPOS_TR; s->graph_default.KeyXOff.refCount=1; pplObjNum(&(s->graph_default.KeyXOff),0,0.0,0.0); s->graph_default.KeyXOff.real = 0.0; s->graph_default.KeyXOff.dimensionless = 0; s->graph_default.KeyXOff.exponent[UNIT_LENGTH] = 1; s->graph_default.KeyYOff.refCount=1; pplObjNum(&(s->graph_default.KeyYOff),0,0.0,0.0); s->graph_default.KeyYOff.real = 0.0; s->graph_default.KeyYOff.dimensionless = 0; s->graph_default.KeyYOff.exponent[UNIT_LENGTH] = 1; s->graph_default.LineWidth = 1.0; s->graph_default.OriginX.refCount=1; pplObjNum(&(s->graph_default.OriginX),0,0.0,0.0); s->graph_default.OriginX.real = 0.0; s->graph_default.OriginX.dimensionless = 0; s->graph_default.OriginX.exponent[UNIT_LENGTH] = 1; s->graph_default.OriginY.refCount=1; pplObjNum(&(s->graph_default.OriginY),0,0.0,0.0); s->graph_default.OriginY.real = 0.0; s->graph_default.OriginY.dimensionless = 0; s->graph_default.OriginY.exponent[UNIT_LENGTH] = 1; s->graph_default.PointSize = 1.0; s->graph_default.PointLineWidth= 1.0; s->graph_default.projection = SW_PROJ_FLAT; s->graph_default.samples = 250; s->graph_default.SamplesX = 40; s->graph_default.SamplesXAuto = SW_BOOL_FALSE; s->graph_default.SamplesY = 40; s->graph_default.SamplesYAuto = SW_BOOL_FALSE; s->graph_default.Sample2DMethod= SW_SAMPLEMETHOD_NEAREST; s->graph_default.TextColor = COLOR_BLACK; s->graph_default.TextCol1234Space = SW_COLSPACE_RGB; s->graph_default.TextColor1 = 0; s->graph_default.TextColor2 = 0; s->graph_default.TextColor3 = 0; s->graph_default.TextColor4 = 0; s->graph_default.TextHAlign = SW_HALIGN_LEFT; s->graph_default.TextVAlign = SW_VALIGN_BOT; strcpy(s->graph_default.title, ""); s->graph_default.TitleXOff.refCount=1; pplObjNum(&(s->graph_default.TitleXOff),0,0.0,0.0); s->graph_default.TitleXOff.real= 0.0; s->graph_default.TitleXOff.dimensionless = 0; s->graph_default.TitleXOff.exponent[UNIT_LENGTH] = 1; s->graph_default.TitleYOff.refCount=1; pplObjNum(&(s->graph_default.TitleYOff),0,0.0,0.0); s->graph_default.TitleYOff.real= 0.0; s->graph_default.TitleYOff.dimensionless = 0; s->graph_default.TitleYOff.exponent[UNIT_LENGTH] = 1; s->graph_default.Tlog = SW_BOOL_FALSE; s->graph_default.Tmin.refCount=1; pplObjNum(&(s->graph_default.Tmin),0,0.0,0.0); s->graph_default.Tmax.refCount=1; pplObjNum(&(s->graph_default.Tmax),0,0.0,0.0); s->graph_default.Tmin.real = 0.0; s->graph_default.Tmax.real = 1.0; s->graph_default.USE_T_or_uv = 1; s->graph_default.Ulog = SW_BOOL_FALSE; s->graph_default.Umin.refCount=1; pplObjNum(&(s->graph_default.Umin),0,0.0,0.0); s->graph_default.Umax.refCount=1; pplObjNum(&(s->graph_default.Umax),0,0.0,0.0); s->graph_default.Umin.real = 0.0; s->graph_default.Umax.real = 1.0; s->graph_default.Vlog = SW_BOOL_FALSE; s->graph_default.Vmin.refCount=1; pplObjNum(&(s->graph_default.Vmin),0,0.0,0.0); s->graph_default.Vmax.refCount=1; pplObjNum(&(s->graph_default.Vmax),0,0.0,0.0); s->graph_default.Vmin.real = 0.0; s->graph_default.Vmax.real = 1.0; s->graph_default.width.refCount=1; pplObjNum(&(s->graph_default.width),0,0.0,0.0); s->graph_default.width.real = 0.08; // 8cm s->graph_default.width.dimensionless = 0; s->graph_default.width.exponent[UNIT_LENGTH] = 1; s->graph_default.XYview.refCount=1; pplObjNum(&(s->graph_default.XYview),0,0.0,0.0); s->graph_default.XYview.real = 60.0 * M_PI / 180; // 60 degrees s->graph_default.XYview.dimensionless = 0; s->graph_default.XYview.exponent[UNIT_ANGLE] = 1; s->graph_default.YZview.refCount=1; pplObjNum(&(s->graph_default.YZview),0,0.0,0.0); s->graph_default.YZview.real = 30.0 * M_PI / 180; // 30 degrees s->graph_default.YZview.dimensionless = 0; s->graph_default.YZview.exponent[UNIT_ANGLE] = 1; // Default Axis Settings, used whenever a new axis is created s->axis_default.atzero = 0; s->axis_default.enabled = 0; s->axis_default.invisible = 0; s->axis_default.linked = 0; s->axis_default.RangeReversed=0; s->axis_default.topbottom = 0; s->axis_default.ArrowType = SW_AXISDISP_NOARR; s->axis_default.LinkedAxisCanvasID = 0; s->axis_default.LinkedAxisToXYZ = 0; s->axis_default.LinkedAxisToNum = 0; s->axis_default.log = SW_BOOL_FALSE; s->axis_default.MaxSet = SW_BOOL_FALSE; s->axis_default.MinSet = SW_BOOL_FALSE; s->axis_default.MirrorType = SW_AXISMIRROR_AUTO; s->axis_default.TickLabelRotation = SW_TICLABDIR_HORI; s->axis_default.LabelRotate = 0.0; s->axis_default.max = 0.0; s->axis_default.min = 0.0; s->axis_default.TickLabelRotate = 0.0; s->axis_default.format = NULL; s->axis_default.label = NULL; s->axis_default.linkusing = NULL; s->axis_default.unit.refCount=1; pplObjNum(&(s->axis_default.unit),0,0.0,0.0); s->axis_default.tics.tickDir = SW_TICDIR_IN; s->axis_default.tics.logBase = 10; s->axis_default.tics.tickMaxSet = 0; s->axis_default.tics.tickMinSet = 0; s->axis_default.tics.tickStepSet= 0; s->axis_default.tics.tickMax = 0.0; s->axis_default.tics.tickMin = 0.0; s->axis_default.tics.tickStep = 0.0; s->axis_default.tics.tickList = NULL; s->axis_default.tics.tickStrs = NULL; s->axis_default.ticsM = s->axis_default.tics; // Set up C ticks s->graph_default.ticsC = s->axis_default.tics; s->graph_default.ticsCM = s->axis_default.tics; s->graph_default.unitC.refCount=1; pplObjNum(&(s->graph_default.unitC),0,0.0,0.0); // Set up list of input filters tempval.refCount=1; s->filters = ppl_dictInit(1); #ifdef HAVE_FITSIO pplObjStr(&tempval,0,0,FITSHELPER); ppl_dictAppend(s->filters, "*.fits", pplObjCpy(NULL,&tempval,0,1,1)); #endif #ifdef TIMEHELPER pplObjStr(&tempval,0,0,TIMEHELPER); ppl_dictAppend(s->filters, "*.log", pplObjCpy(NULL,&tempval,0,1,1)); #endif #ifdef GUNZIP_COMMAND pplObjStr(&tempval,0,0,GUNZIP_COMMAND); ppl_dictAppend(s->filters, "*.gz", pplObjCpy(NULL,&tempval,0,1,1)); #endif #ifdef WGET_COMMAND pplObjStr(&tempval,0,0,WGET_COMMAND); ppl_dictAppend(s->filters, "http://*", pplObjCpy(NULL,&tempval,0,1,1)); ppl_dictAppend(s->filters, "ftp://*", pplObjCpy(NULL,&tempval,0,1,1)); #endif // Set up empty lists of arrows and labels s->pplarrow_list = s->pplarrow_list_default = NULL; s->ppllabel_list = s->ppllabel_list_default = NULL; // Set up array of plot styles for (i=0; iplot_styles [i])); for (i=0; iplot_styles_default[i])); // Set up current axes. Because default axis contains no malloced strings, we don't need to use AxisCopy() here. for (i=0; iXAxes[i] = s->YAxes[i] = s->ZAxes[i] = s->axis_default; s->XAxes[1].enabled = s->YAxes[1].enabled = s->ZAxes[1].enabled = 1; // By default, only axes 1 are enabled s->XAxes[2].topbottom = s->YAxes[2].topbottom = s->ZAxes[2].topbottom = 1; // By default, axes 2 are opposite axes 1 for (i=0; iXAxesDefault[i] = s->XAxes[i]; s->YAxesDefault[i] = s->YAxes[i]; s->ZAxesDefault[i] = s->ZAxes[i]; } // Setting which affect how we talk to the current interactive session se->session_default.splash = SW_ONOFF_ON; se->session_default.color = SW_ONOFF_ON; se->session_default.color_rep= SW_TERMCOL_GRN; se->session_default.color_wrn= SW_TERMCOL_BRN; se->session_default.color_err= SW_TERMCOL_RED; strcpy(se->session_default.homedir, ppl_unixGetHomeDir(&context->errcontext)); // Estimate the machine precision of the floating point unit we are using ppl_makeMachineEpsilon(); gotPaperSize = 0; // Try and find out the default papersize from PAPERSIZE environment variable if (!gotPaperSize) { if (DEBUG) ppl_log(&context->errcontext,"Querying papersize from $PAPERSIZE"); PaperSizePtr = getenv("PAPERSIZE"); if (PaperSizePtr == NULL) { if (DEBUG) ppl_log(&context->errcontext,"Environment variable $PAPERSIZE not set."); } else { ppl_PaperSizeByName(PaperSizePtr, &PaperHeight, &PaperWidth); if (PaperHeight > 0) { if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Read papersize %s, with dimensions %f x %f", PaperSizePtr, PaperWidth, PaperHeight); ppl_log(&context->errcontext,NULL); } s->term_default.PaperHeight.real = PaperHeight/1000; s->term_default.PaperWidth.real = PaperWidth /1000; ppl_GetPaperName(s->term_default.PaperName, &PaperHeight, &PaperWidth); if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Papersize name: %s", s->term_default.PaperName); ppl_log(&context->errcontext,NULL); } //gotPaperSize = 1; } else { if (DEBUG) ppl_log(&context->errcontext,"$PAPERSIZE returned an unrecognised paper size."); } } } // Try and find out the default papersize from /etc/papersize if (!gotPaperSize) { if (DEBUG) ppl_log(&context->errcontext,"Querying papersize from /etc/papersize."); if ((LocalePipe = fopen("/etc/papersize","r"))==NULL) { if (DEBUG) ppl_log(&context->errcontext,"Failed to open /etc/papersize."); } else { ppl_file_readline(LocalePipe, &ConfigFnamePtr, NULL, FNAME_LENGTH); // Should be a papersize name ppl_PaperSizeByName(ConfigFname, &PaperHeight, &PaperWidth); if (PaperHeight > 0) { if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Read papersize %s, with dimensions %f x %f", ConfigFname, PaperWidth, PaperHeight); ppl_log(&context->errcontext,NULL); } s->term_default.PaperHeight.real = PaperHeight/1000; s->term_default.PaperWidth.real = PaperWidth /1000; ppl_GetPaperName(s->term_default.PaperName, &PaperHeight, &PaperWidth); if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Papersize name: %s", s->term_default.PaperName); ppl_log(&context->errcontext,NULL); } //gotPaperSize = 1; } else { if (DEBUG) ppl_log(&context->errcontext,"/etc/papersize returned an unrecognised papersize."); } fclose(LocalePipe); } } // Try and find out the default papersize from the locale command // Do this using the popen() command rather than direct calls to nl_langinfo(_NL_PAPER_WIDTH), because the latter is gnu-specific if (!gotPaperSize) { if (DEBUG) ppl_log(&context->errcontext,"Querying papersize from the locale command."); if ((LocalePipe = popen("locale -c LC_PAPER 2> /dev/null","r"))==NULL) { if (DEBUG) ppl_log(&context->errcontext,"Failed to open a pipe to the locale command."); } else { ppl_file_readline(LocalePipe, &ConfigFnamePtr, NULL, FNAME_LENGTH); // Should read LC_PAPER ppl_file_readline(LocalePipe, &ConfigFnamePtr, NULL, FNAME_LENGTH); // Should quote the default paper height PaperHeight = ppl_getFloat(ConfigFname, &Nchars); if (Nchars != strlen(ConfigFname)) goto LC_PAPERSIZE_DONE; ppl_file_readline(LocalePipe, &ConfigFnamePtr, NULL, FNAME_LENGTH); // Should quote the default paper width PaperWidth = ppl_getFloat(ConfigFname, &Nchars); if (Nchars != strlen(ConfigFname)) goto LC_PAPERSIZE_DONE; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Read papersize %f x %f", PaperWidth, PaperHeight); ppl_log(&context->errcontext,NULL); } s->term_default.PaperHeight.real = PaperHeight/1000; s->term_default.PaperWidth.real = PaperWidth /1000; if (0) { LC_PAPERSIZE_DONE: if (DEBUG) ppl_log(&context->errcontext,"Failed to read papersize from the locale command."); } pclose(LocalePipe); ppl_GetPaperName(s->term_default.PaperName, &PaperHeight, &PaperWidth); if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Papersize name: %s", s->term_default.PaperName); ppl_log(&context->errcontext,NULL); } //gotPaperSize = 1; } } // Copy Default Settings to Current Settings s->term_current = s->term_default; s->graph_current = s->graph_default; for (i=0; ipalette_current [i] = s->palette_default [i]; s->paletteS_current[i] = s->paletteS_default[i]; s->palette1_current[i] = s->palette1_default[i]; s->palette2_current[i] = s->palette2_default[i]; s->palette3_current[i] = s->palette3_default[i]; s->palette4_current[i] = s->palette4_default[i]; } return; } pyxplot-0.9.2/src/settings/withWords_fns.h0000664000175000017500000000336312026340554017271 0ustar dcf21dcf21// withWords_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: withWords_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _WITHWORDS_FNS_H #define _WITHWORDS_FNS_H 1 #include "withWords.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_withWordsZero (ppl_context *context, withWords *a); void ppl_withWordsFromDict(ppl_context *context, parserOutput *in, parserLine *pl, const int *ptab, int stkbase, withWords *out); int ppl_withWordsCmp (ppl_context *context, const withWords *a, const withWords *b); int ppl_withWordsCmp_zero(ppl_context *context, const withWords *a); void ppl_withWordsMerge (ppl_context *context, withWords *out, const withWords *a, const withWords *b, const withWords *c, const withWords *d, const withWords *e, const unsigned char ExpandStyles); void ppl_withWordsPrint (ppl_context *context, const withWords *defn, char *out); void ppl_withWordsDestroy (ppl_context *context, withWords *a); void ppl_withWordsCpy (ppl_context *context, withWords *out, const withWords *in); #endif pyxplot-0.9.2/src/settings/settings_fns.h0000664000175000017500000000176612026340554017144 0ustar dcf21dcf21// settings_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: settings_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _SETTINGS_FNS_H #define _SETTINGS_FNS_H 1 #include "settings/settings.h" #include "userspace/context.h" // Variable initialisation functions void pplset_makedefault(ppl_context *context); #endif pyxplot-0.9.2/src/settings/labels.h0000664000175000017500000000237712026340554015677 0ustar dcf21dcf21// labels.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: labels.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLSET_LABELS_H #define _PPLSET_LABELS_H 1 #include "settings/withWords.h" #include "userspace/pplObj.h" typedef struct ppllabel_object { int id; pplObj x ,y ,z; int system_x,system_y,system_z; int axis_x ,axis_y ,axis_z; char *text; double fontsize; int fontsizeSet; withWords style; double rotation, gap; int HAlign, VAlign; struct ppllabel_object *next; } ppllabel_object; #endif pyxplot-0.9.2/src/settings/settingTypes.h0000664000175000017500000002305012026340554017126 0ustar dcf21dcf21// settingTypes.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: settingTypes.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _SETTINGTYPES_H #define _SETTINGTYPES_H 1 // Boolean Switches #define SW_BOOL_TRUE 10001 #define SW_BOOL_FALSE 10002 #ifndef _SETTINGTYPES_C extern char *SW_BOOL_STR[]; extern int SW_BOOL_ACL[]; extern int SW_BOOL_INT[]; #endif // On/Off Switches #define SW_ONOFF_ON 10011 #define SW_ONOFF_OFF 10012 #ifndef _SETTINGTYPES_C extern char *SW_ONOFF_STR[]; extern int SW_ONOFF_ACL[]; extern int SW_ONOFF_INT[]; #endif // Postscript viewers #define SW_VIEWER_GV 10020 #define SW_VIEWER_GGV 10021 #define SW_VIEWER_NULL 10022 #define SW_VIEWER_CUSTOM 10023 // Color spaces #define SW_COLSPACE_RGB 10031 #define SW_COLSPACE_HSB 10032 #define SW_COLSPACE_CMYK 10033 #ifndef _SETTINGTYPES_C extern char *SW_COLSPACE_STR[]; extern int SW_COLSPACE_ACL[]; extern int SW_COLSPACE_INT[]; #endif // Plot Style Switches #define SW_STYLE_POINTS 10101 #define SW_STYLE_LINES 10102 #define SW_STYLE_LINESPOINTS 10103 #define SW_STYLE_XERRORBARS 10104 #define SW_STYLE_YERRORBARS 10105 #define SW_STYLE_ZERRORBARS 10106 #define SW_STYLE_XYERRORBARS 10107 #define SW_STYLE_XZERRORBARS 10108 #define SW_STYLE_YZERRORBARS 10109 #define SW_STYLE_XYZERRORBARS 10110 #define SW_STYLE_XERRORRANGE 10111 #define SW_STYLE_YERRORRANGE 10112 #define SW_STYLE_ZERRORRANGE 10113 #define SW_STYLE_XYERRORRANGE 10114 #define SW_STYLE_XZERRORRANGE 10115 #define SW_STYLE_YZERRORRANGE 10116 #define SW_STYLE_XYZERRORRANGE 10117 #define SW_STYLE_FILLEDREGION 10118 #define SW_STYLE_YERRORSHADED 10119 #define SW_STYLE_UPPERLIMITS 10120 #define SW_STYLE_LOWERLIMITS 10121 #define SW_STYLE_DOTS 10122 #define SW_STYLE_IMPULSES 10123 #define SW_STYLE_BOXES 10124 #define SW_STYLE_WBOXES 10125 #define SW_STYLE_STEPS 10126 #define SW_STYLE_FSTEPS 10127 #define SW_STYLE_HISTEPS 10128 #define SW_STYLE_STARS 10129 #define SW_STYLE_ARROWS_HEAD 10130 #define SW_STYLE_ARROWS_NOHEAD 10131 #define SW_STYLE_ARROWS_TWOHEAD 10132 #define SW_STYLE_SURFACE 10133 #define SW_STYLE_COLORMAP 10134 #define SW_STYLE_CONTOURMAP 10135 #ifndef _SETTINGTYPES_C extern char *SW_STYLE_STR[]; extern int SW_STYLE_ACL[]; extern int SW_STYLE_INT[]; #endif // Systems in which coordinates can be specified in 'set arrow' and 'set label' #define SW_SYSTEM_FIRST 10201 #define SW_SYSTEM_SECOND 10202 #define SW_SYSTEM_PAGE 10203 #define SW_SYSTEM_GRAPH 10204 #define SW_SYSTEM_AXISN 10205 #ifndef _SETTINGTYPES_C extern char *SW_SYSTEM_STR[]; extern int SW_SYSTEM_ACL[]; extern int SW_SYSTEM_INT[]; #endif // Arrow types understood by the 'set arrow' command #define SW_ARROWTYPE_HEAD 10301 #define SW_ARROWTYPE_NOHEAD 10302 #define SW_ARROWTYPE_TWOWAY 10303 #ifndef _SETTINGTYPES_C extern char *SW_ARROWTYPE_STR[]; extern int SW_ARROWTYPE_ACL[]; extern int SW_ARROWTYPE_INT[]; #endif // Bitmap types understood by the 'image' command #define SW_BITMAP_BMP 10401 #define SW_BITMAP_GIF 10402 #define SW_BITMAP_JPG 10403 #define SW_BITMAP_PNG 10404 #ifndef _SETTINGTYPES_C extern char *SW_BITMAP_STR[]; extern int SW_BITMAP_ACL[]; extern int SW_BITMAP_INT[]; #endif // Axis unit styles #define SW_AXISUNITSTY_BRACKET 10501 #define SW_AXISUNITSTY_RATIO 10502 #define SW_AXISUNITSTY_SQUARE 10503 #ifndef _SETTINGTYPES_C extern char *SW_AXISUNITSTY_STR[]; extern int SW_AXISUNITSTY_ACL[]; extern int SW_AXISUNITSTY_INT[]; #endif // Terminal Type Switches #define SW_TERMTYPE_X11S 13001 #define SW_TERMTYPE_X11M 13002 #define SW_TERMTYPE_X11P 13003 #define SW_TERMTYPE_PS 13004 #define SW_TERMTYPE_EPS 13005 #define SW_TERMTYPE_PDF 13006 #define SW_TERMTYPE_PNG 13007 #define SW_TERMTYPE_JPG 13008 #define SW_TERMTYPE_GIF 13009 #define SW_TERMTYPE_BMP 13010 #define SW_TERMTYPE_TIF 13011 #define SW_TERMTYPE_SVG 13012 #ifndef _SETTINGTYPES_C extern char *SW_TERMTYPE_STR[]; extern int SW_TERMTYPE_ACL[]; extern int SW_TERMTYPE_INT[]; #endif // Key Position Switches #define SW_KEYPOS_TR 14001 #define SW_KEYPOS_TM 14002 #define SW_KEYPOS_TL 14003 #define SW_KEYPOS_MR 14004 #define SW_KEYPOS_MM 14005 #define SW_KEYPOS_ML 14006 #define SW_KEYPOS_BR 14007 #define SW_KEYPOS_BM 14008 #define SW_KEYPOS_BL 14009 #define SW_KEYPOS_ABOVE 14010 #define SW_KEYPOS_BELOW 14011 #define SW_KEYPOS_OUTSIDE 14012 #ifndef _SETTINGTYPES_C extern char *SW_KEYPOS_STR[]; extern int SW_KEYPOS_ACL[]; extern int SW_KEYPOS_INT[]; #endif // Color key position switches #define SW_COLKEYPOS_T 14101 #define SW_COLKEYPOS_B 14102 #define SW_COLKEYPOS_L 14103 #define SW_COLKEYPOS_R 14104 #ifndef _SETTINGTYPES_C extern char *SW_COLKEYPOS_STR[]; extern int SW_COLKEYPOS_ACL[]; extern int SW_COLKEYPOS_INT[]; #endif // Tick Direction Switches #define SW_TICDIR_IN 15001 #define SW_TICDIR_OUT 15002 #define SW_TICDIR_BOTH 15003 #ifndef _SETTINGTYPES_C extern char *SW_TICDIR_STR[]; extern int SW_TICDIR_ACL[]; extern int SW_TICDIR_INT[]; #endif // Tick Label Text Direction Switches #define SW_TICLABDIR_HORI 15011 #define SW_TICLABDIR_VERT 15012 #define SW_TICLABDIR_ROT 15013 #ifndef _SETTINGTYPES_C extern char *SW_TICLABDIR_STR[]; extern int SW_TICLABDIR_ACL[]; extern int SW_TICLABDIR_INT[]; #endif // Axis Display Schemes #define SW_AXISDISP_NOARR 15021 #define SW_AXISDISP_ARROW 15022 #define SW_AXISDISP_TWOAR 15024 #define SW_AXISDISP_BACKA 15026 #ifndef _SETTINGTYPES_C extern char *SW_AXISDISP_STR[]; extern int SW_AXISDISP_ACL[]; extern int SW_AXISDISP_INT[]; #endif // Axis Display Mirroring Schemes #define SW_AXISMIRROR_AUTO 15031 #define SW_AXISMIRROR_MIRROR 15032 #define SW_AXISMIRROR_NOMIRROR 15033 #define SW_AXISMIRROR_FULLMIRROR 15034 #ifndef _SETTINGTYPES_C extern char *SW_AXISMIRROR_STR[]; extern int SW_AXISMIRROR_ACL[]; extern int SW_AXISMIRROR_INT[]; #endif // Graph Projection Schemes #define SW_PROJ_FLAT 15041 #define SW_PROJ_GNOM 15042 #ifndef _SETTINGTYPES_C extern char *SW_PROJ_STR[]; extern int SW_PROJ_ACL[]; extern int SW_PROJ_INT[]; #endif // 2D Sampling Methods #define SW_SAMPLEMETHOD_NEAREST 15061 #define SW_SAMPLEMETHOD_INVSQ 15062 #define SW_SAMPLEMETHOD_ML 15063 #ifndef _SETTINGTYPES_C extern char *SW_SAMPLEMETHOD_STR[]; extern int SW_SAMPLEMETHOD_ACL[]; extern int SW_SAMPLEMETHOD_INT[]; #endif // Text Horizontal Alignment #define SW_HALIGN_LEFT 16001 #define SW_HALIGN_CENT 16002 #define SW_HALIGN_RIGHT 16003 #ifndef _SETTINGTYPES_C extern char *SW_HALIGN_STR[]; extern int SW_HALIGN_ACL[]; extern int SW_HALIGN_INT[]; #endif // Text Vertical Alignment #define SW_VALIGN_TOP 16011 #define SW_VALIGN_CENT 16012 #define SW_VALIGN_BOT 16013 #ifndef _SETTINGTYPES_C extern char *SW_VALIGN_STR[]; extern int SW_VALIGN_ACL[]; extern int SW_VALIGN_INT[]; #endif // Colors for displaying on terminals #define SW_TERMCOL_NOR 17001 #define SW_TERMCOL_RED 17002 #define SW_TERMCOL_GRN 17003 #define SW_TERMCOL_BRN 17004 #define SW_TERMCOL_BLU 17005 #define SW_TERMCOL_MAG 17006 #define SW_TERMCOL_CYN 17007 #define SW_TERMCOL_WHT 17008 #ifndef _SETTINGTYPES_C extern char *SW_TERMCOL_STR[]; extern int SW_TERMCOL_ACL[]; extern int SW_TERMCOL_INT[]; extern char *SW_TERMCOL_TXT[]; #endif // Schemes in which units can be displayed #define SW_UNITSCH_SI 18001 #define SW_UNITSCH_CGS 18002 #define SW_UNITSCH_ANC 18003 #define SW_UNITSCH_IMP 18004 #define SW_UNITSCH_US 18005 #define SW_UNITSCH_PLK 18006 #ifndef _SETTINGTYPES_C extern char *SW_UNITSCH_STR[]; extern int SW_UNITSCH_ACL[]; extern int SW_UNITSCH_INT[]; #endif // Schemes in which we can display numeric results #define SW_DISPLAY_N 18050 #define SW_DISPLAY_T 18051 #define SW_DISPLAY_L 18052 #ifndef _SETTINGTYPES_C extern char *SW_DISPLAY_STR[]; extern int SW_DISPLAY_ACL[]; extern int SW_DISPLAY_INT[]; #endif // Calendars which we can use #define SW_CALENDAR_GREGORIAN 19001 #define SW_CALENDAR_JULIAN 19002 #define SW_CALENDAR_BRITISH 19003 #define SW_CALENDAR_FRENCH 19004 #define SW_CALENDAR_CATHOLIC 19005 #define SW_CALENDAR_RUSSIAN 19006 #define SW_CALENDAR_GREEK 19007 #define SW_CALENDAR_HEBREW 19020 #define SW_CALENDAR_ISLAMIC 19021 #ifndef _SETTINGTYPES_C extern char *SW_CALENDAR_STR[]; extern int SW_CALENDAR_ACL[]; extern int SW_CALENDAR_INT[]; #endif // Positions for the labels on piecharts #define SW_PIEKEYPOS_AUTO 19101 #define SW_PIEKEYPOS_INSIDE 19102 #define SW_PIEKEYPOS_KEY 19103 #define SW_PIEKEYPOS_OUTSIDE 19104 #ifndef _SETTINGTYPES_C extern char *SW_PIEKEYPOS_STR[]; extern int SW_PIEKEYPOS_ACL[]; extern int SW_PIEKEYPOS_INT[]; #endif #include "coreUtils/errorReport.h" void *ppl_fetchSettingName (pplerr_context *context, int id, int *id_list, void *name_list, const int name_list_size); int ppl_fetchSettingByName (pplerr_context *context, char *name, int *id_list, char **name_list); #endif pyxplot-0.9.2/src/settings/settingTypes.c0000664000175000017500000003014712026340554017126 0ustar dcf21dcf21// settingTypes.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: settingTypes.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _SETTINGTYPES_C 1 #include #include #include #include "stringTools/asciidouble.h" #include "coreUtils/errorReport.h" #include "settings/settingTypes.h" char *SW_BOOL_STR[] = {"true" , "false" }; int SW_BOOL_ACL[] = {1 , 1 }; int SW_BOOL_INT[] = {SW_BOOL_TRUE , SW_BOOL_FALSE , -1}; char *SW_ONOFF_STR[] = {"on" , "off" }; int SW_ONOFF_ACL[] = {2 , 2 }; int SW_ONOFF_INT[] = {SW_ONOFF_ON , SW_ONOFF_OFF , -1}; char *SW_COLSPACE_STR[] = {"rgb" , "hsb" , "cmyk" }; int SW_COLSPACE_ACL[] = {1 , 1 , 1 }; int SW_COLSPACE_INT[] = {SW_COLSPACE_RGB , SW_COLSPACE_HSB , SW_COLSPACE_CMYK , -1}; char *SW_STYLE_STR[] = {"points" , "lines" , "linesPoints" , "xErrorBars" , "yErrorBars" , "zErrorBars" , "xyErrorBars" , "xzErrorBars" , "yzErrorBars" , "xyzErrorBars" , "xErrorRange" , "yErrorRange" , "zErrorRange" , "xyErrorRange" , "xzErrorRange" , "yzErrorRange" , "xyzErrorRange" , "filledRegion" , "YErrorShaded" , "upperLimits" , "lowerLimits" , "dots" , "impulses" , "boxes" , "wboxes" , "steps" , "fsteps" , "histeps" , "stars" , "arrows_head" , "arrows_nohead" , "arrows_twohead" , "surface" , "colormap" , "contourmap" }; int SW_STYLE_ACL[] = {1 , 1 , 6 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 7 , 7 , 7 , 8 , 8 , 8 , 9 , 3 , 7 , 1 , 2 , 1 , 1 , 1 , 1 , 2 , 2 , 2 , 3 , 1 , 7 , 8 , 2 , 3 , 3 , -1}; int SW_STYLE_INT[] = {SW_STYLE_POINTS , SW_STYLE_LINES , SW_STYLE_LINESPOINTS , SW_STYLE_XERRORBARS , SW_STYLE_YERRORBARS , SW_STYLE_ZERRORBARS , SW_STYLE_XYERRORBARS , SW_STYLE_XZERRORBARS , SW_STYLE_YZERRORBARS , SW_STYLE_XYZERRORBARS , SW_STYLE_XERRORRANGE , SW_STYLE_YERRORRANGE , SW_STYLE_ZERRORRANGE , SW_STYLE_XYERRORRANGE , SW_STYLE_XZERRORRANGE , SW_STYLE_YZERRORRANGE , SW_STYLE_XYZERRORRANGE , SW_STYLE_FILLEDREGION , SW_STYLE_YERRORSHADED , SW_STYLE_UPPERLIMITS , SW_STYLE_LOWERLIMITS , SW_STYLE_DOTS , SW_STYLE_IMPULSES , SW_STYLE_BOXES , SW_STYLE_WBOXES , SW_STYLE_STEPS , SW_STYLE_FSTEPS , SW_STYLE_HISTEPS , SW_STYLE_STARS, SW_STYLE_ARROWS_HEAD , SW_STYLE_ARROWS_NOHEAD , SW_STYLE_ARROWS_TWOHEAD , SW_STYLE_SURFACE , SW_STYLE_COLORMAP , SW_STYLE_CONTOURMAP , -1}; char *SW_SYSTEM_STR[] = {"first" , "second" , "page" , "graph" , "axis" }; int SW_SYSTEM_ACL[] = {1 , 1 , 1 , 1 , 1 }; int SW_SYSTEM_INT[] = {SW_SYSTEM_FIRST , SW_SYSTEM_SECOND , SW_SYSTEM_PAGE , SW_SYSTEM_GRAPH , SW_SYSTEM_AXISN , -1}; char *SW_ARROWTYPE_STR[] = {"head" , "nohead" , "twoway" }; int SW_ARROWTYPE_ACL[] = {1 , 1 , 1 }; int SW_ARROWTYPE_INT[] = {SW_ARROWTYPE_HEAD , SW_ARROWTYPE_NOHEAD , SW_ARROWTYPE_TWOWAY , -1}; char *SW_BITMAP_STR[] = {"bmp" , "gif" , "jpeg" , "png" }; int SW_BITMAP_ACL[] = {1 , 1 , 1 , 1 }; int SW_BITMAP_INT[] = {SW_BITMAP_BMP, SW_BITMAP_GIF, SW_BITMAP_JPG, SW_BITMAP_PNG, -1}; char *SW_AXISUNITSTY_STR[] = {"bracketed" , "ratio" , "squareBracketed" }; int SW_AXISUNITSTY_ACL[] = {1 , 1 , 1 }; int SW_AXISUNITSTY_INT[] = {SW_AXISUNITSTY_BRACKET, SW_AXISUNITSTY_RATIO, SW_AXISUNITSTY_SQUARE, -1}; char *SW_TERMTYPE_STR[] = {"X11_singleWindow", "X11_multiWindow" , "X11_persist" , "ps" , "eps" , "pdf" , "png" , "jpg" , "gif" , "bmp" , "tif" , "svg" }; int SW_TERMTYPE_ACL[] = {1 , 5 , 5 , 1 , 1 , 2 , 2 , 1 , 1 , 1 , 1 , 1 }; int SW_TERMTYPE_INT[] = {SW_TERMTYPE_X11S , SW_TERMTYPE_X11M , SW_TERMTYPE_X11P , SW_TERMTYPE_PS , SW_TERMTYPE_EPS , SW_TERMTYPE_PDF , SW_TERMTYPE_PNG , SW_TERMTYPE_JPG , SW_TERMTYPE_GIF , SW_TERMTYPE_BMP, SW_TERMTYPE_TIF , SW_TERMTYPE_SVG , -1}; char *SW_KEYPOS_STR[] = {"top right" , "top xcenter" , "top left" , "ycenter right" , "ycenter xcenter" , "ycenter left" , "bottom right" , "bottom xcenter" , "bottom left" , "above" , "below" , "outside" }; int SW_KEYPOS_ACL[] = {5 , 5 , 5 , 9 , 9 , 9 , 8 , 8 , 8 , 1 , 2 , 1 }; int SW_KEYPOS_INT[] = {SW_KEYPOS_TR , SW_KEYPOS_TM , SW_KEYPOS_TL , SW_KEYPOS_MR , SW_KEYPOS_MM , SW_KEYPOS_ML , SW_KEYPOS_BR , SW_KEYPOS_BM , SW_KEYPOS_BL , SW_KEYPOS_ABOVE , SW_KEYPOS_BELOW , SW_KEYPOS_OUTSIDE , -1}; char *SW_COLKEYPOS_STR[] = {"top" , "bottom" , "left" , "right" }; int SW_COLKEYPOS_ACL[] = {1 , 1 , 1 , 1 }; int SW_COLKEYPOS_INT[] = {SW_COLKEYPOS_T , SW_COLKEYPOS_B , SW_COLKEYPOS_L , SW_COLKEYPOS_R , -1}; char *SW_TICDIR_STR[] = {"inwards" , "outwards" , "both" }; int SW_TICDIR_ACL[] = {1 , 1 , 1 }; int SW_TICDIR_INT[] = {SW_TICDIR_IN , SW_TICDIR_OUT , SW_TICDIR_BOTH , -1}; char *SW_TICLABDIR_STR[] = {"horizontal" , "vertical" , "rotate" }; int SW_TICLABDIR_ACL[] = {1 , 1 , 1 }; int SW_TICLABDIR_INT[] = {SW_TICLABDIR_HORI , SW_TICLABDIR_VERT , SW_TICLABDIR_ROT , -1}; char *SW_AXISDISP_STR[] = {"noarrow" , "arrow" , "twoWayArrow" , "reverseArrow" }; int SW_AXISDISP_ACL[] = {1 , 1 , 1 , 1 }; int SW_AXISDISP_INT[] = {SW_AXISDISP_NOARR , SW_AXISDISP_ARROW , SW_AXISDISP_TWOAR , SW_AXISDISP_BACKA , -1}; char *SW_AXISMIRROR_STR[] = {"autoMirrored" , "mirrored" , "noMirror" , "fullMirrored" }; int SW_AXISMIRROR_ACL[] = {1 , 1 , 1 , 1 }; int SW_AXISMIRROR_INT[] = {SW_AXISMIRROR_AUTO , SW_AXISMIRROR_MIRROR , SW_AXISMIRROR_NOMIRROR , SW_AXISMIRROR_FULLMIRROR , -1}; char *SW_PROJ_STR[] = {"flat" , "gnomonic" }; int SW_PROJ_ACL[] = {1 , 1 }; int SW_PROJ_INT[] = {SW_PROJ_FLAT , SW_PROJ_GNOM , -1}; char *SW_SAMPLEMETHOD_STR[] = {"nearestNeighbor" , "inverseSquare" , "monaghanLattanzio" }; int SW_SAMPLEMETHOD_ACL[] = {1 , 1 , 1 }; int SW_SAMPLEMETHOD_INT[] = {SW_SAMPLEMETHOD_NEAREST, SW_SAMPLEMETHOD_INVSQ , SW_SAMPLEMETHOD_ML , -1}; char *SW_HALIGN_STR[] = {"left" , "center" , "right" }; int SW_HALIGN_ACL[] = {1 , 1 , 1 }; int SW_HALIGN_INT[] = {SW_HALIGN_LEFT , SW_HALIGN_CENT , SW_HALIGN_RIGHT , -1}; char *SW_VALIGN_STR[] = {"top" , "center" , "bottom" }; int SW_VALIGN_ACL[] = {1 , 1 , 1 }; int SW_VALIGN_INT[] = {SW_VALIGN_TOP , SW_VALIGN_CENT , SW_VALIGN_BOT , -1}; char *SW_TERMCOL_STR[] = {"normal" , "red" , "green" , "amber" , "blue" , "magenta" , "cyan" , "white" }; int SW_TERMCOL_ACL[] = {1 , 1 , 1 , 2 , 1 , 1 , 1 , 1 }; int SW_TERMCOL_INT[] = {SW_TERMCOL_NOR , SW_TERMCOL_RED , SW_TERMCOL_GRN , SW_TERMCOL_BRN , SW_TERMCOL_BLU , SW_TERMCOL_MAG , SW_TERMCOL_CYN , SW_TERMCOL_WHT , -1}; char *SW_TERMCOL_TXT[] = {"\x1b[0m" , "\x1b[01;31m" , "\x1b[01;32m" , "\x1b[01;33m" , "\x1b[01;34m" , "\x1b[01;35m" , "\x1b[01;36m" , "\x1b[01;37m" }; char *SW_UNITSCH_STR[] = {"si" , "cgs" , "ancient" , "imperial" , "USCustomary" , "planck" }; int SW_UNITSCH_INT[] = {SW_UNITSCH_SI , SW_UNITSCH_CGS , SW_UNITSCH_ANC , SW_UNITSCH_IMP , SW_UNITSCH_US , SW_UNITSCH_PLK , -1}; int SW_UNITSCH_ACL[] = {1 , 1 , 1 , 1 , 1 , 1 , -1}; char *SW_DISPLAY_STR[] = {"natural" , "typeable" , "latex" }; int SW_DISPLAY_ACL[] = {1 , 1 , 1 }; int SW_DISPLAY_INT[] = {SW_DISPLAY_N , SW_DISPLAY_T , SW_DISPLAY_L , -1}; char *SW_CALENDAR_STR[] = {"Gregorian" , "Julian" , "British" , "French" , "Papal" , "Russian" , "Greek" , "Hebrew" , "Islamic" }; int SW_CALENDAR_INT[] = {SW_CALENDAR_GREGORIAN, SW_CALENDAR_JULIAN, SW_CALENDAR_BRITISH, SW_CALENDAR_FRENCH, SW_CALENDAR_CATHOLIC, SW_CALENDAR_RUSSIAN, SW_CALENDAR_GREEK, SW_CALENDAR_HEBREW, SW_CALENDAR_ISLAMIC, -1}; int SW_CALENDAR_ACL[] = {1 , 1 , 1 , 1 , 1 , 1 , 5 , 1 , 1 , -1}; char *SW_PIEKEYPOS_STR[] = {"auto" , "inside" , "key" , "outside" }; int SW_PIEKEYPOS_INT[] = {SW_PIEKEYPOS_AUTO, SW_PIEKEYPOS_INSIDE, SW_PIEKEYPOS_KEY, SW_PIEKEYPOS_OUTSIDE, -1}; int SW_PIEKEYPOS_ACL[] = {1 , 1 , 1 , 1 , -1}; void *ppl_fetchSettingName(pplerr_context *context, int id, int *id_list, void *name_list, const int name_list_size) { int first; static int latch=0; static char *dummyout = ""; first = *id_list; while(1) { if (*id_list == id) return name_list; if (*id_list == -1) { if (latch==1) return dummyout; // Prevent recursive calling latch=1; sprintf(context->tempErrStr, "Setting with illegal value %d; should have had a value of type %d.", id, first); ppl_fatal(context,__FILE__, __LINE__, context->tempErrStr); } id_list++; name_list+=name_list_size; } if (latch==1) return dummyout; latch=1; sprintf(context->tempErrStr, "Setting has illegal value %d.", id); ppl_fatal(context,__FILE__, __LINE__, context->tempErrStr); return NULL; } int ppl_fetchSettingByName(pplerr_context *context, char *name, int *id_list, char **name_list) { while(1) { if (*id_list == -1) return -1; if (ppl_strCmpNoCase(name, *name_list) == 0) return *id_list; id_list++; name_list++; } return -1; } pyxplot-0.9.2/src/settings/colors.c0000664000175000017500000001615612026340554015731 0ustar dcf21dcf21// colors.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: colors.c 1271 2012-07-18 23:51:56Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/colors.h" #include "settings/epsColors.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjCmp.h" #include "pplConstants.h" int ppl_colorFromDict (ppl_context *c, parserOutput *in, parserLine *pl, const int *ptab, int stkbase, int fillColor, int *outcol, int *outcolspace, pplExpr **EXPoutcol, double *outcol1, double *outcol2, double *outcol3, double *outcol4, unsigned char *USEcol, unsigned char *USEcol1234) { int pos = ptab[ fillColor ? PARSE_INDEX_fillcolor : PARSE_INDEX_color]; pplObj *col = &in->stk[stkbase+pos]; int s; if (pos<0) return 0; s = ppl_colorFromObj(c, col, outcol, outcolspace, EXPoutcol, outcol1, outcol2, outcol3, outcol4, USEcol, USEcol1234); if (s) ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, NULL); return s; } int ppl_colorFromObj (ppl_context *c, const pplObj *col, int *outcol, int *outcolspace, pplExpr **EXPoutcol, double *outcol1, double *outcol2, double *outcol3, double *outcol4, unsigned char *USEcol, unsigned char *USEcol1234) { switch (col->objType) { case PPLOBJ_ZOM: // no color specified return 0; case PPLOBJ_NUM: // color specified as palette index { int j,k1,k2,palette_index1,palette_index2; double w1,w2; for (j=1; jset->palette_current[j]==-1) break; k1 = (int)floor(col->real); if (k1 > INT_MAX-8) k1=INT_MAX-8; if (k1 < INT_MIN+8) k1=INT_MIN+8; k2 = k1+1; // Mix color indexes k1 and k2 w2 = col->real - k1; // weights for two colors if (w2<=0) w2=0; if (w2>=1) w2=1; w1 = 1-w2; palette_index1 = (k1-1)%j; while (palette_index1 < 0) palette_index1+=j; palette_index2 = (k2-1)%j; while (palette_index2 < 0) palette_index2+=j; { double r1,g1,b1,r2,g2,b2; double i11,i12,i13,i14,i21,i22,i23,i24; int s1,s2; if (c->set->palette_current[palette_index1]>0) { s1 = SW_COLSPACE_CMYK; i11 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index1], SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)); i12 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index1], SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)); i13 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index1], SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)); i14 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index1], SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)); } else { s1 = c->set->paletteS_current[palette_index1]; i11 = c->set->palette1_current[palette_index1]; i12 = c->set->palette2_current[palette_index1]; i13 = c->set->palette3_current[palette_index1]; i14 = c->set->palette4_current[palette_index1]; } if (c->set->palette_current[palette_index2]>0) { s2 = SW_COLSPACE_CMYK; i21 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index2], SW_COLOR_INT, (void *)SW_COLOR_CMYK_C, sizeof(double)); i22 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index2], SW_COLOR_INT, (void *)SW_COLOR_CMYK_M, sizeof(double)); i23 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index2], SW_COLOR_INT, (void *)SW_COLOR_CMYK_Y, sizeof(double)); i24 = *(double *)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[palette_index2], SW_COLOR_INT, (void *)SW_COLOR_CMYK_K, sizeof(double)); } else { s2 = c->set->paletteS_current[palette_index2]; i21 = c->set->palette1_current[palette_index2]; i22 = c->set->palette2_current[palette_index2]; i23 = c->set->palette3_current[palette_index2]; i24 = c->set->palette4_current[palette_index2]; } if (s1==SW_COLSPACE_RGB ) { r1=i11; g1=i12; b1=i13; } else if (s1==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(i11,i12,i13,i14,&r1,&g1,&b1); else pplcol_HSBtoRGB (i11,i12,i13,&r1,&g1,&b1); if (s2==SW_COLSPACE_RGB ) { r2=i21; g2=i22; b2=i23; } else if (s2==SW_COLSPACE_CMYK) pplcol_CMYKtoRGB(i21,i22,i23,i24,&r2,&g2,&b2); else pplcol_HSBtoRGB (i21,i22,i23,&r2,&g2,&b2); *outcol = 0; *outcolspace = SW_COLSPACE_CMYK; pplcol_RGBtoCMYK( r1*w1 + r2*w2 , g1*w1 + g2*w2 , b1*w1 + b2*w2 , outcol1, outcol2, outcol3, outcol4); if (USEcol !=NULL) *USEcol = 0; if (USEcol1234!=NULL) *USEcol1234 = 1; } return 0; } case PPLOBJ_COL: // color specified as a color object { *outcol = (int)round(col->exponent[2]); *outcolspace = (int)round(col->exponent[0]); *outcol1 = col->exponent[ 8]; *outcol2 = col->exponent[ 9]; *outcol3 = col->exponent[10]; *outcol4 = col->exponent[11]; if (USEcol !=NULL) *USEcol = (*outcol >0); if (USEcol1234!=NULL) *USEcol1234 = (*outcol==0); return 0; } case PPLOBJ_EXP: // color expressed as an expression via %C { if (EXPoutcol == NULL) { sprintf(c->errcontext.tempErrStr, "Colour specified as expression via %%C token, but no pointer given for output of this expression."); return 1; } if (*EXPoutcol == NULL) pplExpr_free(*EXPoutcol); *EXPoutcol = (pplExpr *)col->auxil; (*EXPoutcol)->refCount++; if (USEcol !=NULL) *USEcol = 0; if (USEcol1234!=NULL) *USEcol1234 = 0; return 0; } default: { sprintf(c->errcontext.tempErrStr, "Colour specified as wrong type of object (type %d).", col->objType); return 1; } } return 1; } pyxplot-0.9.2/src/settings/withWords.h0000664000175000017500000000346112026340554016422 0ustar dcf21dcf21// withWords.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: withWords.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _WITHWORDS_H #define _WITHWORDS_H 1 #include "expressions/expCompile.h" typedef struct withWords { int color, fillcolor, linespoints, linetype, pointtype, style; // Core style settings which can be placed after the 'with' modifier double linewidth, pointlinewidth, pointsize; int Col1234Space, FillCol1234Space; double color1, color2, color3, color4; // Alternatives to the color and fillcolor settings, RGB settings double fillcolor1, fillcolor2, fillcolor3, fillcolor4; pplExpr *EXPlinetype, *EXPlinewidth, *EXPpointlinewidth, *EXPpointsize, *EXPpointtype; // Alternatives to the above, where expressions are evaluated per use, e.g. $4 pplExpr *EXPcolor, *EXPfillcolor; unsigned char USEcolor, USEfillcolor, USElinespoints, USElinetype, USElinewidth, USEpointlinewidth, USEpointsize, USEpointtype, USEstyle, USEcolor1234, USEfillcolor1234; // Set to 1 to indicate settings to be used int AUTOcolor, AUTOlinetype, AUTOpointtype; } withWords; #endif pyxplot-0.9.2/src/settings/settings.h0000664000175000017500000001355412026340554016274 0ustar dcf21dcf21// settings.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: settings.h 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _SETTINGS_H #define _SETTINGS_H 1 #include "stringTools/strConstants.h" #include "coreUtils/dict.h" #include "pplConstants.h" #include "userspace/pplObj.h" #include "settings/withWords.h" #ifndef _SETTINGSINIT_C extern int cancellationFlag; #endif // Setting structures typedef struct pplset_terminal { int backup, CalendarIn, CalendarOut, color, ComplexNumbers, display, ExplicitErrors, landscape, multiplot, NumDisplay, SignificantFigures, TermAntiAlias, TermType, TermEnlarge, TermInvert, TermTransparent, UnitScheme, UnitDisplayPrefix, UnitDisplayAbbrev, UnitAngleDimless, viewer; long int RandomSeed; double dpi; unsigned char BinOriginAuto, BinWidthAuto; pplObj BinOrigin, BinWidth, PaperHeight, PaperWidth; char output[FNAME_LENGTH]; char PaperName[FNAME_LENGTH]; char LatexPreamble[FNAME_LENGTH]; char ViewerCmd[FNAME_LENGTH]; char timezone[FNAME_LENGTH]; } pplset_terminal; typedef struct pplset_tics { int logBase, tickDir; unsigned char tickMaxSet, tickMinSet, tickStepSet; double tickMax, tickMin, tickStep; double *tickList; char **tickStrs; } pplset_tics; typedef struct pplset_graph { int AutoAspect, AutoZAspect, AxesColor, AxesCol1234Space, AxisUnitStyle, clip, Clog[4], Cminauto[4], Cmaxauto[4], Crenorm[4], Creverse[4], ColKey, ColKeyPos, ContoursLabel, ContoursListLen, ContoursN, grid, GridMajColor, GridMajCol1234Space, GridMinColor, GridMinCol1234Space, key, KeyColumns, KeyPos, samples, SamplesX, SamplesXAuto, SamplesY, SamplesYAuto, Sample2DMethod, TextColor, TextCol1234Space, TextHAlign, TextVAlign, Tlog, Ulog, Vlog; double AxesColor1, AxesColor2, AxesColor3, AxesColor4, GridMajColor1, GridMajColor2, GridMajColor3, GridMajColor4, GridMinColor1, GridMinColor2, GridMinColor3, GridMinColor4, TextColor1, TextColor2, TextColor3, TextColor4; double aspect, zaspect, bar, ContoursList[MAX_CONTOURS], FontSize, LineWidth, PointSize, PointLineWidth, projection; unsigned char GridAxisX[MAX_AXES], GridAxisY[MAX_AXES], GridAxisZ[MAX_AXES]; unsigned char BoxFromAuto, BoxWidthAuto, USE_T_or_uv; pplObj BoxFrom, BoxWidth, Cmin[4], Cmax[4], ContoursUnit, KeyXOff, KeyYOff, OriginX, OriginY, TitleXOff, TitleYOff, Tmin, Tmax, Umin, Umax, Vmin, Vmax, width, XYview, YZview; char title[FNAME_LENGTH]; void *ColMapExpr, *MaskExpr; char c1label[FNAME_LENGTH], c1formatset; void *c1format; double c1LabelRotate, c1TickLabelRotate; int c1TickLabelRotation; withWords dataStyle, funcStyle; pplset_tics ticsCM, ticsC; pplObj unitC; } pplset_graph; typedef struct pplset_axis { unsigned char atzero, enabled, invisible, linked, RangeReversed, topbottom; int ArrowType, LinkedAxisCanvasID, LinkedAxisToXYZ, LinkedAxisToNum, log, MaxSet, MinSet, MirrorType, TickLabelRotation; double LabelRotate, max, min, TickLabelRotate; char *label; void *linkusing; void *format; pplset_tics ticsM, tics; pplObj unit; // Temporary data fields which are used when rendering an axis to postscript int AxisValueTurnings; double *AxisLinearInterpolation; int *AxisTurnings; unsigned char CrossedAtZero; unsigned char MinUsedSet, MaxUsedSet, DataUnitSet, RangeFinalised, FinalActive; double PhysicalLengthMajor, PhysicalLengthMinor; int xyz, axis_n, canvas_id, FirstTextID; double MinUsed, MaxUsed, MinFinal, MaxFinal, *OrdinateRaster; double HardMin, HardMax; // Contains ranges set via plot [foo:bar] unsigned char HardMinSet, HardMaxSet, HardAutoMinSet, HardAutoMaxSet, HardUnitSet, Mode0BackPropagated; int OrdinateRasterLen, LogFinal; pplObj HardUnit, DataUnit; char *FinalAxisLabel; unsigned char TickListFinalised; double *TickListPositions, *MTickListPositions; char **TickListStrings , **MTickListStrings; } pplset_axis; #include "settings/arrows.h" #include "settings/labels.h" // Complete set of session settings typedef struct ppl_settings_struc { pplset_terminal term_default; pplset_terminal term_current; pplset_graph graph_default; pplset_graph graph_current; int palette_current[PALETTE_LENGTH], paletteS_current[PALETTE_LENGTH]; double palette1_current[PALETTE_LENGTH], palette2_current[PALETTE_LENGTH], palette3_current[PALETTE_LENGTH], palette4_current[PALETTE_LENGTH]; int palette_default[PALETTE_LENGTH], paletteS_default[PALETTE_LENGTH]; double palette1_default[PALETTE_LENGTH], palette2_default[PALETTE_LENGTH], palette3_default[PALETTE_LENGTH], palette4_default[PALETTE_LENGTH]; withWords plot_styles[MAX_PLOTSTYLES], plot_styles_default[MAX_PLOTSTYLES]; pplset_axis axis_default; pplset_axis XAxes[MAX_AXES], XAxesDefault[MAX_AXES]; pplset_axis YAxes[MAX_AXES], YAxesDefault[MAX_AXES]; pplset_axis ZAxes[MAX_AXES], ZAxesDefault[MAX_AXES]; dict *filters; pplarrow_object *pplarrow_list, *pplarrow_list_default; ppllabel_object *ppllabel_list, *ppllabel_list_default; } ppl_settings; #endif pyxplot-0.9.2/src/settings/papersizes.h0000664000175000017500000000200012026340554016601 0ustar dcf21dcf21// papersizes.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: papersizes.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PAPERSIZES_H #define _PAPERSIZES_H 1 void ppl_PaperSizeInit (); void ppl_PaperSizeByName(char *name, double *height, double *width); void ppl_GetPaperName (char *name, double *height, double *width); #endif pyxplot-0.9.2/src/settings/arrows.h0000664000175000017500000000237312026340554015746 0ustar dcf21dcf21// arrows.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: arrows.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLSET_ARROWS_H #define _PPLSET_ARROWS_H 1 #include "settings/withWords.h" #include "userspace/pplObj.h" typedef struct pplarrow_object { int id; pplObj x0 ,y0 ,z0 ,x1 ,y1 ,z1; int system_x0,system_y0,system_z0,system_x1,system_y1,system_z1; int axis_x0 ,axis_y0 ,axis_z0 ,axis_x1 ,axis_y1 ,axis_z1; int pplarrow_style; withWords style; struct pplarrow_object *next; } pplarrow_object; #endif pyxplot-0.9.2/src/settings/arrows_fns.h0000664000175000017500000000753612026340554016622 0ustar dcf21dcf21// arrows_fns.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: arrows_fns.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PPLSET_ARROWS_FNS_H #define _PPLSET_ARROWS_FNS_H 1 #include "coreUtils/dict.h" #include "parser/parser.h" #include "settings/arrows.h" #include "userspace/context.h" #include "userspace/unitsDisp.h" void pplarrow_add (ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab); void pplarrow_remove (ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab, int quiet); void pplarrow_unset (ppl_context *context, pplarrow_object **inlist, parserOutput *in, parserLine *pl, const int *ptab); unsigned char pplarrow_compare (ppl_context *context, pplarrow_object *a, pplarrow_object *b); void pplarrow_list_copy (ppl_context *context, pplarrow_object **out, pplarrow_object **in); void pplarrow_list_destroy(ppl_context *context, pplarrow_object **inlist); void pplarrow_print (ppl_context *context, pplarrow_object *in, char *out); #define pplarrow_add_get_system(X,Y) \ { \ pplObj *o = &in->stk[ptab[X]]; /* e.g. x0_system */ \ if (o->objType != PPLOBJ_STR) Y = SW_SYSTEM_FIRST; \ else Y = ppl_fetchSettingByName(&context->errcontext, (char *)o->auxil, SW_SYSTEM_INT, SW_SYSTEM_STR); \ } #define pplarrow_add_get_axis(X,Y) \ { \ pplObj *o = &in->stk[ptab[X]]; /* e.g. x0_axis */ \ if (o->objType != PPLOBJ_NUM) Y = 0; \ else Y = (int)round(o->real); \ } #define pplarrow_add_check_axis(X) \ { \ pplObj *o = &in->stk[ptab[X]]; /* e.g. x0_axis */ \ if (o->objType == PPLOBJ_NUM) \ { \ int i = (int)round(o->real); \ if ((i<0)||(i>=MAX_AXES)) \ { \ sprintf(context->errStat.errBuff, "Axis number %d is out of range; axis numbers must be in the range 0 - %d", i, MAX_AXES-1); \ TBADD(ERR_RANGE, in->stkCharPos[ptab[X]]); \ return; \ } \ } \ } #define pplarrow_add_check_dimensions(X,Y) \ { \ pplObj *o = &in->stk[ptab[X]]; /* e.g. x0 */ \ if (o->objType == PPLOBJ_NUM) \ { \ int i; \ if ((Y == SW_SYSTEM_GRAPH) || (Y == SW_SYSTEM_PAGE)) \ if (!o->dimensionless) \ for (i=0; iexponent[i] != (i==UNIT_LENGTH)) \ { \ sprintf(context->errStat.errBuff, "Coordinates specified in the graph and page systems must have dimensions of length. Received coordinate with dimensions of <%s>.", ppl_printUnit(context, o, NULL, NULL, 0, 1, 0)); \ TBADD(ERR_UNIT, in->stkCharPos[ptab[X]]); \ } \ if (!gsl_finite(o->real)) \ { \ sprintf(context->errStat.errBuff, "Coordinates specified are not finite."); \ TBADD(ERR_NUMERICAL, in->stkCharPos[ptab[X]]); \ } \ } \ } #define pplarrow_add_copy_coordinate(X,Y,Z) \ { \ pplObj *o = &in->stk[ptab[X]] , tempobj; /* e.g. x0 */ \ if (o->objType != PPLOBJ_NUM) { o = &tempobj; pplObjNum(&tempobj,0,0,0); } \ if ((Y == SW_SYSTEM_GRAPH) || (Y == SW_SYSTEM_PAGE)) \ if (o->dimensionless) { o->dimensionless=0; o->exponent[UNIT_LENGTH]=1; o->real /= 100; } \ Z = *o; \ } #endif pyxplot-0.9.2/src/settings/textConstants.h0000664000175000017500000000226112026340554017306 0ustar dcf21dcf21// textConstants.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: textConstants.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _TEXTCONSTANTS_H #define _TEXTCONSTANTS_H 1 extern char ppltxt_version[]; extern char ppltxt_help[]; extern char ppltxt_welcome[]; extern char ppltxt_invalid[]; extern char ppltxt_valid_set_options[]; extern char ppltxt_set_noword[]; extern char ppltxt_unset_noword[]; extern char ppltxt_set[]; extern char ppltxt_unset[]; extern char ppltxt_show[]; void ppltxt_init (); #endif pyxplot-0.9.2/src/settings/withWords.c0000664000175000017500000005056712026340554016426 0ustar dcf21dcf21// withWords.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: withWords.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _PPL_SETTINGS_C 1 #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "pplConstants.h" #include "coreUtils/errorReport.h" #include "expressions/expCompile_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/colors.h" #include "settings/epsColors.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/withWords_fns.h" #include "userspace/context.h" #include "userspace/pplObj.h" // ----------------------------------------------- // ROUTINES FOR MANIPULATING WITH_WORDS STRUCTURES // ----------------------------------------------- void ppl_withWordsZero(ppl_context *context, withWords *a) { a->color = a->fillcolor = a->linespoints = a->linetype = a->pointtype = a->style = a->Col1234Space = a->FillCol1234Space = 0; a->linewidth = a->pointlinewidth = a->pointsize = 1.0; a->color1 = a->color2 = a->color3 = a->color4 = a->fillcolor1 = a->fillcolor2 = a->fillcolor3 = a->fillcolor4 = 0.0; a->EXPlinetype = a->EXPlinewidth = a->EXPpointlinewidth = a->EXPpointsize = a->EXPpointtype = NULL; a->EXPcolor = a->EXPfillcolor = NULL; a->USEcolor = a->USEfillcolor = a->USElinespoints = a->USElinetype = a->USElinewidth = a->USEpointlinewidth = a->USEpointsize = a->USEpointtype = a->USEstyle = a->USEcolor1234 = a->USEfillcolor1234 = 0; a->AUTOcolor = a->AUTOlinetype = a->AUTOpointtype = 0; return; } void ppl_withWordsFromDict(ppl_context *context, parserOutput *in, parserLine *pl, const int *ptab, int stkbase, withWords *out) { pplObj *stk = in->stk + stkbase; int tempint, i, pos, got; double tempdbl; char *tempstr; pplExpr *tempexp; ppl_withWordsZero(context, out); // read color names ppl_colorFromDict(context, in, pl, ptab, stkbase, 0, &out->color, &out->Col1234Space, &out->EXPcolor, &out->color1, &out->color2, &out->color3, &out->color4, &out->USEcolor, &out->USEcolor1234); ppl_colorFromDict(context, in, pl, ptab, stkbase, 1, &out->fillcolor, &out->FillCol1234Space, &out->EXPfillcolor, &out->fillcolor1, &out->fillcolor2, &out->fillcolor3, &out->fillcolor4, &out->USEfillcolor, &out->USEfillcolor1234); // Other settings pos = ptab[PARSE_INDEX_linetype ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempint = (int)round(stk[pos].real); out->linetype = tempint; out->USElinetype = 1; } pos = ptab[PARSE_INDEX_linetype ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_EXP); if (got) { tempexp = (pplExpr *)stk[pos].auxil; out->EXPlinetype = tempexp; tempexp->refCount++; } pos = ptab[PARSE_INDEX_linewidth ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempdbl = stk[pos].real; out->linewidth = tempdbl; out->USElinewidth = 1; } pos = ptab[PARSE_INDEX_linewidth ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_EXP); if (got) { tempexp = (pplExpr *)stk[pos].auxil; out->EXPlinewidth = tempexp; tempexp->refCount++; } pos = ptab[PARSE_INDEX_pointsize ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempdbl = stk[pos].real; out->pointsize = tempdbl; out->USEpointsize = 1; } pos = ptab[PARSE_INDEX_pointsize ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_EXP); if (got) { tempexp = (pplExpr *)stk[pos].auxil; out->EXPpointsize = tempexp; tempexp->refCount++; } pos = ptab[PARSE_INDEX_pointtype ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempint = (int)round(stk[pos].real); out->pointtype = tempint; out->USEpointtype = 1; } pos = ptab[PARSE_INDEX_pointtype ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_EXP); if (got) { tempexp = (pplExpr *)stk[pos].auxil; out->EXPpointtype = tempexp; tempexp->refCount++; } pos = ptab[PARSE_INDEX_style_number ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempint = (int)round(stk[pos].real); out->style = tempint; out->USEstyle = 1; } pos = ptab[PARSE_INDEX_pointlinewidth]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_NUM); if (got) { tempdbl = stk[pos].real; out->pointlinewidth = tempdbl; out->USEpointlinewidth = 1; } pos = ptab[PARSE_INDEX_pointlinewidth]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_EXP); if (got) { tempexp = (pplExpr *)stk[pos].auxil; out->EXPpointlinewidth = tempexp; tempexp->refCount++; } pos = ptab[PARSE_INDEX_style ]; got = (pos>=0) && (stk[pos].objType==PPLOBJ_STR); if (got) { tempstr = (char *)stk[pos].auxil; i = ppl_fetchSettingByName(&context->errcontext, tempstr, SW_STYLE_INT, SW_STYLE_STR); out->linespoints = i; out->USElinespoints = 1; } return; } int ppl_withWordsCmp_zero(ppl_context *context, const withWords *a) { if (a->EXPlinetype != NULL) return 0; if (a->EXPlinewidth != NULL) return 0; if (a->EXPpointlinewidth != NULL) return 0; if (a->EXPpointsize != NULL) return 0; if (a->EXPpointtype != NULL) return 0; if (a->EXPcolor != NULL) return 0; if (a->EXPfillcolor != NULL) return 0; if (a->USEcolor) return 0; if (a->USEfillcolor) return 0; if (a->USElinespoints) return 0; if (a->USElinetype) return 0; if (a->USElinewidth) return 0; if (a->USEpointlinewidth) return 0; if (a->USEpointsize) return 0; if (a->USEpointtype) return 0; if (a->USEstyle) return 0; if (a->USEcolor1234) return 0; if (a->USEfillcolor1234) return 0; return 1; } int ppl_withWordsCmp(ppl_context *context, const withWords *a, const withWords *b) { // Check that the range of items which are defined in both structures are the same if ((a->EXPcolor ==NULL) != (b->EXPcolor ==NULL) ) return 0; if ((a->EXPfillcolor ==NULL) != (b->EXPfillcolor ==NULL) ) return 0; if ( (a->USElinespoints != b->USElinespoints )) return 0; if ((a->EXPlinetype ==NULL) != (b->EXPlinetype ==NULL) ) return 0; if ((a->EXPlinetype ==NULL) && (a->USElinetype != b->USElinetype )) return 0; if ((a->EXPlinewidth ==NULL) != (b->EXPlinewidth ==NULL) ) return 0; if ((a->EXPlinewidth ==NULL) && (a->USElinewidth != b->USElinewidth )) return 0; if ((a->EXPpointlinewidth==NULL) != (b->EXPpointlinewidth==NULL) ) return 0; if ((a->EXPpointlinewidth==NULL) && (a->USEpointlinewidth != b->USEpointlinewidth)) return 0; if ((a->EXPpointsize ==NULL) != (b->EXPpointsize ==NULL) ) return 0; if ((a->EXPpointsize ==NULL) && (a->USEpointsize != b->USEpointsize )) return 0; if ((a->EXPpointtype ==NULL) != (b->EXPpointtype ==NULL) ) return 0; if ((a->EXPpointtype ==NULL) && (a->USEpointtype != b->USEpointtype )) return 0; if ( (a->USEstyle != b->USEstyle )) return 0; // Check that the actual values are the same in both structures if (a->EXPcolor != NULL) { if ((strcmp(a->EXPcolor->ascii,b->EXPcolor->ascii)!=0)) return 0; if (a->Col1234Space!=b->Col1234Space) return 0; } else if ((a->USEcolor1234 ) && ((a->color1!=b->color1)||(a->color2!=b->color2)||(a->color3!=b->color3)||(a->color4!=b->color4)||(a->Col1234Space!=b->Col1234Space))) return 0; else if ((a->USEcolor ) && ((a->color !=b->color ))) return 0; if (a->EXPfillcolor != NULL) { if ((strcmp(a->EXPfillcolor->ascii,b->EXPfillcolor->ascii)!=0)) return 0; if (a->FillCol1234Space!=b->FillCol1234Space) return 0; } else if ((a->USEfillcolor1234 ) && ((a->fillcolor1!=b->fillcolor1)||(a->fillcolor2!=b->fillcolor2)||(a->fillcolor3!=b->fillcolor3)||(a->fillcolor4!=b->fillcolor4)||(a->FillCol1234Space!=b->FillCol1234Space))) return 0; else if ((a->USEfillcolor ) && ((a->fillcolor !=b->fillcolor ))) return 0; if ((a->USElinespoints ) && ((a->linespoints !=b->linespoints ))) return 0; if ((a->EXPlinetype !=NULL) && ((strcmp(a->EXPlinetype->ascii ,b->EXPlinetype->ascii )!=0))) return 0; else if ((a->USElinetype ) && ((a->linetype !=b->linetype ))) return 0; if ((a->EXPlinewidth !=NULL) && ((strcmp(a->EXPlinewidth->ascii ,b->EXPlinewidth->ascii )!=0))) return 0; else if ((a->USElinewidth ) && ((a->linewidth !=b->linewidth ))) return 0; if ((a->EXPpointlinewidth!=NULL) && ((strcmp(a->EXPpointlinewidth->ascii,b->EXPpointlinewidth->ascii)!=0))) return 0; else if ((a->USEpointlinewidth ) && ((a->pointlinewidth!=b->pointlinewidth))) return 0; if ((a->EXPpointsize !=NULL) && ((strcmp(a->EXPpointsize->ascii ,b->EXPpointsize->ascii )!=0))) return 0; else if ((a->USEpointsize ) && ((a->pointsize !=b->pointsize ))) return 0; if ((a->EXPpointtype !=NULL) && ((strcmp(a->EXPpointtype->ascii ,b->EXPpointtype->ascii )!=0))) return 0; else if ((a->USEpointtype ) && ((a->pointtype !=b->pointtype ))) return 0; if ((a->USEstyle ) && ((a->style !=b->style ))) return 0; return 1; // We have not found any differences } // a has highest priority; e has lowest priority void ppl_withWordsMerge(ppl_context *context, withWords *out, const withWords *a, const withWords *b, const withWords *c, const withWords *d, const withWords *e, const unsigned char ExpandStyles) { int i; const withWords *InputArray[25] = {a,b,c,d,e}; unsigned char BlockStyleSubstitution[25] = {0,0,0,0,0}; const withWords *x; ppl_withWordsZero(context,out); for (i=4; i>=0; i--) { if (i>24) { ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, "Iteration depth exceeded whilst substituting plot styles. Infinite plot style loop suspected."); return; } // i can reach 24 when recursion happens x = InputArray[i]; if (x == NULL) continue; if ((x->USEstyle) && (!BlockStyleSubstitution[i])) // Substitute for numbered plot styles { if (ExpandStyles) { BlockStyleSubstitution[i ] = 1; // Only do this once, to avoid infinite loop BlockStyleSubstitution[i+1] = 0; // Allow recursive substitutions InputArray[i+1] = &(context->set->plot_styles[ x->style ]); i+=2; // Recurse continue; } else { out->style = x->style; out->USEstyle = 1; } } if (x->USEcolor1234 ) { out->color1 = x->color1; out->color2 = x->color2; out->color3 = x->color3; out->color4 = x->color4; out->Col1234Space = x->Col1234Space; out->USEcolor1234 = 1; out->USEcolor = 0; pplExpr_free(out->EXPcolor); out->EXPcolor = NULL; out->AUTOcolor = x->AUTOcolor; } if (x->USEcolor ) { out->color = x->color; out->USEcolor = 1; out->USEcolor1234 = 0; pplExpr_free(out->EXPcolor); out->EXPcolor = NULL; out->AUTOcolor = x->AUTOcolor; } if (x->EXPcolor !=NULL) { pplExpr_free(out->EXPcolor); out->EXPcolor = x->EXPcolor; out->EXPcolor->refCount++; out->USEcolor = 0; out->USEcolor1234 = 0; out->AUTOcolor = x->AUTOcolor; } if (x->USEfillcolor1234 ) { out->fillcolor1 = x->fillcolor1; out->fillcolor2 = x->fillcolor2; out->fillcolor3 = x->fillcolor3; out->fillcolor4 = x->fillcolor4; out->FillCol1234Space = x->FillCol1234Space; out->USEfillcolor1234 = 1; out->USEfillcolor = 0; pplExpr_free(out->EXPfillcolor); out->EXPfillcolor = NULL; } if (x->USEfillcolor ) { out->fillcolor = x->fillcolor; out->USEfillcolor = 1; out->USEfillcolor1234 = 0; pplExpr_free(out->EXPfillcolor); out->EXPfillcolor = NULL; } if (x->EXPfillcolor !=NULL) { pplExpr_free(out->EXPfillcolor); out->EXPfillcolor = x->EXPfillcolor; out->EXPfillcolor->refCount++; out->USEfillcolor = 0; out->USEfillcolor1234 = 0; } if (x->USElinespoints ) { out->linespoints = x->linespoints; out->USElinespoints = 1; } if (x->USElinetype ) { out->linetype = x->linetype; out->USElinetype = 1; pplExpr_free(out->EXPlinetype); out->EXPlinetype = NULL; out->AUTOlinetype = x->AUTOlinetype; } if (x->EXPlinetype !=NULL) { pplExpr_free(out->EXPlinetype); out->EXPlinetype = x->EXPlinetype; out->EXPlinetype->refCount++; } if (x->USElinewidth ) { out->linewidth = x->linewidth; out->USElinewidth = 1; pplExpr_free(out->EXPlinewidth); out->EXPlinewidth = NULL; } if (x->EXPlinewidth !=NULL) { pplExpr_free(out->EXPlinewidth); out->EXPlinewidth = x->EXPlinewidth; out->EXPlinewidth->refCount++; out->USElinewidth = 0; } if (x->USEpointlinewidth ) { out->pointlinewidth = x->pointlinewidth; out->USEpointlinewidth = 1; pplExpr_free(out->EXPpointlinewidth); out->EXPpointlinewidth = NULL; } if (x->EXPpointlinewidth!=NULL) { pplExpr_free(out->EXPpointlinewidth); out->EXPpointlinewidth = x->EXPpointlinewidth; out->EXPpointlinewidth->refCount++; out->USEpointlinewidth = 0; } if (x->USEpointsize ) { out->pointsize = x->pointsize; out->USEpointsize = 1; pplExpr_free(out->EXPpointsize); out->EXPpointsize = NULL; } if (x->EXPpointsize !=NULL) { pplExpr_free(out->EXPpointsize); out->EXPpointsize = x->EXPpointsize; out->EXPpointsize->refCount++; out->USEpointsize = 0; } if (x->USEpointtype ) { out->pointtype = x->pointtype; out->USEpointtype = 1; pplExpr_free(out->EXPpointtype); out->EXPpointtype = NULL; out->AUTOpointtype = x->AUTOpointtype; } if (x->EXPpointtype !=NULL) { pplExpr_free(out->EXPpointtype); out->EXPpointtype = x->EXPpointtype; out->EXPpointtype->refCount++; } } return; } #define NUMDISP(X) ppl_numericDisplay(X,context->numdispBuff[0],context->set->term_current.SignificantFigures,(context->set->term_current.NumDisplay==SW_DISPLAY_L)) #define S_RGB(X,Y) (char *)ppl_numericDisplay(X,context->numdispBuff[Y],context->set->term_current.SignificantFigures,(context->set->term_current.NumDisplay==SW_DISPLAY_L)) void ppl_withWordsPrint(ppl_context *context, const withWords *defn, char *out) { int i=0; out[i]='\0'; if (defn->USElinespoints) { sprintf(out+i, "%s ", *(char **)ppl_fetchSettingName(&context->errcontext,defn->linespoints, SW_STYLE_INT , (void *)SW_STYLE_STR , sizeof(char *))); i += strlen(out+i); } if (defn->EXPcolor!=NULL) { sprintf(out+i, "color %s", defn->EXPcolor->ascii); } else if (defn->USEcolor1234) { if (defn->Col1234Space==SW_COLSPACE_RGB ) sprintf(out+i, "color rgb(%s,%s,%s) ", S_RGB(defn->color1,0), S_RGB(defn->color2,1), S_RGB(defn->color3,2)); else if (defn->Col1234Space==SW_COLSPACE_HSB ) sprintf(out+i, "color hsb(%s,%s,%s) ", S_RGB(defn->color1,0), S_RGB(defn->color2,1), S_RGB(defn->color3,2)); else if (defn->Col1234Space==SW_COLSPACE_CMYK) sprintf(out+i, "color cmyk(%s,%s,%s,%s) ", S_RGB(defn->color1,0), S_RGB(defn->color2,1), S_RGB(defn->color3,2), S_RGB(defn->color4,3)); } else if (defn->USEcolor) { sprintf(out+i, "color %s ", *(char **)ppl_fetchSettingName(&context->errcontext,defn->color , SW_COLOR_INT, (void *)SW_COLOR_STR, sizeof(char *))); } i += strlen(out+i); if (defn->EXPfillcolor!=NULL) { sprintf(out+i, "fillcolor %s", defn->EXPfillcolor->ascii); } else if (defn->USEfillcolor1234) { if (defn->FillCol1234Space==SW_COLSPACE_RGB ) sprintf(out+i, "fillcolor rgb(%s,%s,%s) ", S_RGB(defn->fillcolor1,0), S_RGB(defn->fillcolor2,1), S_RGB(defn->fillcolor3,2)); else if (defn->FillCol1234Space==SW_COLSPACE_HSB ) sprintf(out+i, "fillcolor hsb(%s,%s,%s) ", S_RGB(defn->fillcolor1,0), S_RGB(defn->fillcolor2,1), S_RGB(defn->fillcolor3,2)); else if (defn->FillCol1234Space==SW_COLSPACE_CMYK) sprintf(out+i, "fillcolor cmyk(%s,%s,%s,%s) ", S_RGB(defn->fillcolor1,0), S_RGB(defn->fillcolor2,1), S_RGB(defn->fillcolor3,2), S_RGB(defn->fillcolor4,2)); } else if (defn->USEfillcolor) { sprintf(out+i, "fillcolor %s ", *(char **)ppl_fetchSettingName(&context->errcontext,defn->fillcolor , SW_COLOR_INT, (void *)SW_COLOR_STR, sizeof(char *))); } i += strlen(out+i); if (defn->EXPlinetype!=NULL) { sprintf(out+i, "linetype %s " , defn->EXPlinetype->ascii); i += strlen(out+i); } else if (defn->USElinetype) { sprintf(out+i, "linetype %d " , defn->linetype); i += strlen(out+i); } if (defn->EXPlinewidth!=NULL) { sprintf(out+i, "linewidth %s " , defn->EXPlinewidth->ascii); i += strlen(out+i); } else if (defn->USElinewidth) { sprintf(out+i, "linewidth %s " , NUMDISP(defn->linewidth)); i += strlen(out+i); } if (defn->EXPpointlinewidth!=NULL) { sprintf(out+i, "pointlinewidth %s " , defn->EXPpointlinewidth->ascii); i += strlen(out+i); } else if (defn->USEpointlinewidth) { sprintf(out+i, "pointlinewidth %s " , NUMDISP(defn->pointlinewidth)); i += strlen(out+i); } if (defn->EXPpointsize!=NULL) { sprintf(out+i, "pointsize %s " , defn->EXPpointsize->ascii); i += strlen(out+i); } else if (defn->USEpointsize) { sprintf(out+i, "pointsize %s " , NUMDISP(defn->pointsize)); i += strlen(out+i); } if (defn->EXPpointtype!=NULL) { sprintf(out+i, "pointtype %s " , defn->EXPpointtype->ascii); i += strlen(out+i); } else if (defn->USEpointtype) { sprintf(out+i, "pointtype %d " , defn->pointtype); i += strlen(out+i); } if (defn->USEstyle) { sprintf(out+i, "style %d " , defn->style); i += strlen(out+i); } out[i]='\0'; return; } void ppl_withWordsDestroy(ppl_context *context, withWords *a) { if (a->EXPlinetype != NULL) { pplExpr_free(a->EXPlinetype ); a->EXPlinetype = NULL; } if (a->EXPlinewidth != NULL) { pplExpr_free(a->EXPlinewidth ); a->EXPlinewidth = NULL; } if (a->EXPpointlinewidth != NULL) { pplExpr_free(a->EXPpointlinewidth); a->EXPpointlinewidth = NULL; } if (a->EXPpointsize != NULL) { pplExpr_free(a->EXPpointsize ); a->EXPpointsize = NULL; } if (a->EXPpointtype != NULL) { pplExpr_free(a->EXPpointtype ); a->EXPpointtype = NULL; } if (a->EXPcolor != NULL) { pplExpr_free(a->EXPcolor ); a->EXPcolor = NULL; } if (a->EXPfillcolor != NULL) { pplExpr_free(a->EXPfillcolor ); a->EXPfillcolor = NULL; } return; } void ppl_withWordsCpy(ppl_context *context, withWords *out, const withWords *in) { *out = *in; if (in->EXPlinetype != NULL) { out->EXPlinetype = in->EXPlinetype ; out->EXPlinetype ->refCount++; } if (in->EXPlinewidth != NULL) { out->EXPlinewidth = in->EXPlinewidth ; out->EXPlinewidth ->refCount++; } if (in->EXPpointlinewidth!= NULL) { out->EXPpointlinewidth= in->EXPpointlinewidth; out->EXPpointlinewidth->refCount++; } if (in->EXPpointsize != NULL) { out->EXPpointsize = in->EXPpointsize ; out->EXPpointsize ->refCount++; } if (in->EXPpointtype != NULL) { out->EXPpointtype = in->EXPpointtype ; out->EXPpointtype ->refCount++; } if (in->EXPcolor != NULL) { out->EXPcolor = in->EXPcolor ; out->EXPcolor ->refCount++; } if (in->EXPfillcolor != NULL) { out->EXPfillcolor = in->EXPfillcolor ; out->EXPfillcolor ->refCount++; } return; } pyxplot-0.9.2/src/settings/labels.c0000664000175000017500000003111712026340554015664 0ustar dcf21dcf21// labels.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: labels.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include "coreUtils/dict.h" #include "coreUtils/list.h" #include "coreUtils/errorReport.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settingTypes.h" #include "settings/arrows_fns.h" #include "settings/labels_fns.h" #include "settings/settings.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "pplConstants.h" // ------------------------------------------- // ROUTINES FOR MANIPULATING LABELS STRUCTURES // ------------------------------------------- #define TBADD(et,pos) ppl_tbAdd(context,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define CMPVAL(X,Y) (ppl_unitsDimEqual(&X,&Y) && ppl_dblEqual(X.real , Y.real)) void ppllabel_add(ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab) { int i, system_x, system_y, system_z, gotTempstr, gotGap, gotAng; char *tempstr, *label; double gap, ang; ppllabel_object *out; pplarrow_add_get_system(PARSE_INDEX_x_system , system_x); pplarrow_add_get_system(PARSE_INDEX_y_system , system_y); pplarrow_add_get_system(PARSE_INDEX_z_system , system_z); pplarrow_add_check_dimensions(PARSE_INDEX_x , system_x); pplarrow_add_check_dimensions(PARSE_INDEX_y , system_y); pplarrow_add_check_dimensions(PARSE_INDEX_z , system_z); pplarrow_add_check_axis(PARSE_INDEX_x_axis); pplarrow_add_check_axis(PARSE_INDEX_y_axis); pplarrow_add_check_axis(PARSE_INDEX_z_axis); tempstr = (char *)in->stk[ptab[PARSE_INDEX_label_text]].auxil; // Read label text label = (char *)malloc(strlen(tempstr)+1); if (label == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1, "Out of memory"); return; } strcpy(label, tempstr); ang = in->stk[ptab[PARSE_INDEX_rotation]].real; // Check for rotation modifier gotAng = (in->stk[ptab[PARSE_INDEX_rotation]].objType == PPLOBJ_NUM); gap = in->stk[ptab[PARSE_INDEX_gap]].real; // Check for gap modifier gotGap = (in->stk[ptab[PARSE_INDEX_gap]].objType == PPLOBJ_NUM); // Look up ID number of the label we are adding and find appropriate place for it in label list i = (int)round(in->stk[ptab[PARSE_INDEX_label_id]].real); while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); if ((*inlist != NULL) && ((*inlist)->id == i)) { out = *inlist; ppl_withWordsDestroy(context, &out->style); } else { out = (ppllabel_object *)malloc(sizeof(ppllabel_object)); if (out == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1, "Out of memory"); return; } out->id = i; out->next = *inlist; *inlist = out; } // Check for halign or valign modifiers tempstr = (char *)in->stk[ptab[PARSE_INDEX_halign]].auxil; gotTempstr = (in->stk[ptab[PARSE_INDEX_halign]].objType == PPLOBJ_STR); if (gotTempstr) out->HAlign = ppl_fetchSettingByName(&context->errcontext, tempstr, SW_HALIGN_INT, SW_HALIGN_STR); else out->HAlign = context->set->graph_current.TextHAlign; tempstr = (char *)in->stk[ptab[PARSE_INDEX_valign]].auxil; gotTempstr = (in->stk[ptab[PARSE_INDEX_valign]].objType == PPLOBJ_STR); if (gotTempstr) out->VAlign = ppl_fetchSettingByName(&context->errcontext, tempstr, SW_VALIGN_INT, SW_VALIGN_STR); else out->VAlign = context->set->graph_current.TextVAlign; if (gotAng) out->rotation = ang; else out->rotation = 0.0; if (gotGap) out->gap = gap; else out->gap = 0.0; // See if fontsize is specified out->fontsizeSet = (in->stk[ptab[PARSE_INDEX_fontsize]].objType==PPLOBJ_NUM); if (out->fontsizeSet) { double f = in->stk[ptab[PARSE_INDEX_fontsize]].real; if (f < 0) { f=1; ppl_error(&context->errcontext,ERR_MEMORY, -1, -1, "Fontsize specified in 'set fontsize' command was less than zero."); return; } if (!gsl_finite(f)) { f=1; ppl_error(&context->errcontext,ERR_MEMORY, -1, -1, "Fontsize specified in 'set fontsize' command was not finite."); return; } out->fontsize = f; } ppl_withWordsFromDict(context, in, pl, ptab, 0, &out->style); out->text = label; out->system_x = system_x; out->system_y = system_y; out->system_z = system_z; pplarrow_add_get_axis(PARSE_INDEX_x_axis, out->axis_x); pplarrow_add_get_axis(PARSE_INDEX_y_axis, out->axis_y); pplarrow_add_get_axis(PARSE_INDEX_z_axis, out->axis_z); pplarrow_add_copy_coordinate(PARSE_INDEX_x, system_x, out->x); pplarrow_add_copy_coordinate(PARSE_INDEX_y, system_y, out->y); pplarrow_add_copy_coordinate(PARSE_INDEX_z, system_z, out->z); return; } void ppllabel_remove(ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab, int quiet) { int pos; ppllabel_object **first; first = inlist; pos = ptab[PARSE_INDEX_0label_list]; if ((in->stk[pos].objType!=PPLOBJ_NUM)||(in->stk[pos].real<=0)) ppllabel_list_destroy(context, inlist); // set noarrow with no number specified means all arrows deleted else { while (in->stk[pos].objType == PPLOBJ_NUM) { int i; pos = (int)round(in->stk[pos].real); if (pos<=0) break; i = (int)round(in->stk[pos+ptab[PARSE_INDEX_label_id]].real); inlist = first; while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); if ((*inlist != NULL) && ((*inlist)->id == i)) { ppllabel_object *obj = *inlist; *inlist = (*inlist)->next; ppl_withWordsDestroy(context, &obj->style); free(obj->text); free(obj); } else if (!quiet) { sprintf(context->errcontext.tempErrStr,"Label number %d is not defined", i); ppl_warning(&context->errcontext, ERR_GENERIC, NULL); } } } return; } void ppllabel_unset(ppl_context *context, ppllabel_object **inlist, parserOutput *in, parserLine *pl, const int *ptab) { int pos; ppllabel_object **first; ppllabel_remove(context, inlist, in, pl, ptab, 1); // First of all, remove any arrows which we are unsetting first = inlist; pos = ptab[PARSE_INDEX_0label_list]; if ((in->stk[pos].objType!=PPLOBJ_NUM)||(in->stk[pos].real<=0)) { ppllabel_list_destroy(context, inlist); ppllabel_list_copy(context, inlist, &context->set->ppllabel_list_default); // Check to see whether we are unsetting ALL arrows, and if so, use the copy command } else { while (in->stk[pos].objType == PPLOBJ_NUM) { int i; ppllabel_object *obj; pos = (int)round(in->stk[pos].real); if (pos<=0) break; i = (int)round(in->stk[pos+ptab[PARSE_INDEX_label_id]].real); obj = context->set->ppllabel_list_default; while ((obj != NULL) && (obj->id < i)) obj = (obj->next); if ((obj != NULL) && (obj->id == i)) { ppllabel_object *new; inlist = first; while ((*inlist != NULL) && ((*inlist)->id < i)) inlist = &((*inlist)->next); new = (ppllabel_object *)malloc(sizeof(ppllabel_object)); if (new == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); return; } *new = *obj; new->next = *inlist; new->text = (char *)malloc(strlen(obj->text)+1); if (new->text == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); free(new); return; } strcpy(new->text, obj->text); ppl_withWordsCpy(context, &new->style, &obj->style); *inlist = new; } } } return; } unsigned char ppllabel_compare(ppl_context *context, ppllabel_object *a, ppllabel_object *b) { if (a->id!=b->id) return 0; if ( (!CMPVAL(a->x , b->x)) || (!CMPVAL(a->y , b->y)) || (!CMPVAL(a->z , b->z)) ) return 0; if ( (a->system_x!=b->system_x) || (a->system_y!=b->system_y) || (a->system_z!=b->system_z) ) return 0; if ( (a->axis_x!=b->axis_x) || (a->axis_y!=b->axis_y) || (a->axis_z!=b->axis_z) ) return 0; if ( (a->fontsizeSet!=b->fontsizeSet) || ((a->fontsizeSet)&&(a->fontsize!=b->fontsize)) ) return 0; if (!ppl_withWordsCmp(context, &a->style , &b->style)) return 0; if (strcmp(a->text , b->text)!=0) return 0; return 1; } void ppllabel_list_copy(ppl_context *context, ppllabel_object **out, ppllabel_object **in) { *out = NULL; while (*in != NULL) { *out = (ppllabel_object *)malloc(sizeof(ppllabel_object)); if (*out == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); return; } **out = **in; (*out)->next = NULL; (*out)->text = (char *)malloc(strlen((*in)->text)+1); if ((*out)->text == NULL) { ppl_error(&context->errcontext,ERR_MEMORY, -1, -1,"Out of memory"); free(*out); *out=NULL; return; } strcpy((*out)->text, (*in)->text); ppl_withWordsCpy(context, &(*out)->style, &(*in)->style); in = &((*in )->next); out = &((*out)->next); } return; } void ppllabel_list_destroy(ppl_context *context, ppllabel_object **inlist) { ppllabel_object *obj, **first; first = inlist; while (*inlist != NULL) { obj = *inlist; *inlist = (*inlist)->next; ppl_withWordsDestroy(context, &obj->style); free(obj->text); free(obj); } *first = NULL; return; } void ppllabel_print(ppl_context *context, ppllabel_object *in, char *out) { int i; ppl_strEscapify(in->text, out); i = strlen(out); sprintf(out+i, " at %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_x, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_x==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_x); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context, &(in->x),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_y, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_y==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_y); i+=strlen(out+i); } sprintf(out+i, " %s,", ppl_unitsNumericDisplay(context, &(in->y),0,0,0)); i+=strlen(out+i); sprintf(out+i, " %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->system_z, SW_SYSTEM_INT, (void *)SW_SYSTEM_STR, sizeof(char *))); i+=strlen(out+i); if (in->system_z==SW_SYSTEM_AXISN) { sprintf(out+i, " %d",in->axis_z); i+=strlen(out+i); } sprintf(out+i, " %s", ppl_unitsNumericDisplay(context, &(in->z),0,0,0)); i+=strlen(out+i); if (in->rotation!=0.0) { sprintf(out+i, " rotate %s", ppl_numericDisplay( in->rotation *180/M_PI , context->numdispBuff[0], context->set->term_current.SignificantFigures, (context->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i+=strlen(out+i); } if (in->HAlign>0) { sprintf(out+i, " halign %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->HAlign, SW_HALIGN_INT, (void *)SW_HALIGN_STR, sizeof(char *))); i+=strlen(out+i); } if (in->VAlign>0) { sprintf(out+i, " valign %s", *(char **)ppl_fetchSettingName(&context->errcontext, in->VAlign, SW_VALIGN_INT, (void *)SW_VALIGN_STR, sizeof(char *))); i+=strlen(out+i); } if (in->gap!=0.0) { sprintf(out+i, " gap %s", ppl_numericDisplay( in->gap * 100 , context->numdispBuff[0], context->set->term_current.SignificantFigures, (context->set->term_current.NumDisplay==SW_DISPLAY_L)) ); i+=strlen(out+i); } ppl_withWordsPrint(context, &in->style, out+i+6); if ((strlen(out+i+6)>0)||in->fontsizeSet) { sprintf(out+i, " with"); out[i+5]=' '; } else { out[i]='\0'; } i+=strlen(out+i); if (in->fontsizeSet) { sprintf(out+i, " fontsize %s", ppl_numericDisplay(in->fontsize, context->numdispBuff[0], context->set->term_current.SignificantFigures, (context->set->term_current.NumDisplay==SW_DISPLAY_L))); i+=strlen(out+i); } return; } pyxplot-0.9.2/src/settings/textConstants.c0000664000175000017500000001437412026340554017311 0ustar dcf21dcf21// textConstants.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: textConstants.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "settings/textConstants.h" #include "pplConstants.h" // Contains text messages which pyxplot displays char ppltxt_version [SSTR_LENGTH]; char ppltxt_version_underline [SSTR_LENGTH]; char ppltxt_help [LSTR_LENGTH]; char ppltxt_welcome [LSTR_LENGTH]; char ppltxt_invalid [LSTR_LENGTH]; char ppltxt_valid_set_options [LSTR_LENGTH]; char ppltxt_set_noword [LSTR_LENGTH]; char ppltxt_unset_noword [LSTR_LENGTH]; char ppltxt_set [LSTR_LENGTH]; char ppltxt_unset [LSTR_LENGTH]; char ppltxt_show [LSTR_LENGTH]; void ppltxt_init() { sprintf(ppltxt_version, "Pyxplot %s", VERSION); sprintf(ppltxt_help , "%s\n\ %s\n\ \n\ Usage: pyxplot \n\ -h, --help: Display this help.\n\ -v, --version: Display version number.\n\ -q, --quiet: Turn off initial welcome message.\n\ -V, --verbose: Turn on initial welcome message.\n\ -c, --color: Use colored highlighting of output.\n\ -m, --monochrome: Turn off colored highlighting.\n\ \n\ A brief introduction to Pyxplot can be obtained by typing 'man pyxplot'; the\n\ full Users' Guide can be found in the file:\n\ %s%spyxplot.pdf\n\ \n\ Extensive documentation is also available at , which\n\ also provides contact information for bug reports.\n", ppltxt_version, ppl_strUnderline(ppltxt_version, ppltxt_version_underline), DOCDIR, PATHLINK); sprintf(ppltxt_welcome, "\n\ _ _ PYXPLOT\n\ _ __ _ ___ ___ __ | | ___ | |_ Version %s\n\ | '_ \\| | | \\ \\/ / '_ \\| |/ _ \\| __| %s\n\ | |_) | |_| |> <| |_) | | (_) | |_\n\ | .__/ \\__, /_/\\_\\ .__/|_|\\___/ \\__| Copyright (C) 2006-2012 Dominic Ford\n\ |_| |___/ |_| 2008-2012 Ross Church\n\ \n\ For documentation and more information, see .\n\ ", VERSION, DATE); sprintf(ppltxt_invalid, "\n\ %%s\n\ /|\\ \n\ |\n\ Error: Unrecognised command.\n\ "); sprintf(ppltxt_valid_set_options, "\n\ 'arrow', 'autoscale', 'axescolor', 'axis', 'axisunitstyle', 'backup', 'bar',\n\ 'binorigin', 'binwidth', 'boxfrom', 'boxwidth', 'c1format', 'c1label',\n\ 'calendar', 'clip', 'colmap', 'colkey', 'contours', 'crange', 'data style',\n\ 'display', 'filter', 'fontsize', 'function style', 'grid', 'gridmajcolor',\n\ 'gridmincolor', 'key', 'keycolumns', 'label', 'linearscale', 'linewidth',\n\ 'logscale', 'multiplot', 'noarrow', 'noaxis', 'nobackup', 'nodisplay',\n\ 'nogrid', 'nokey', 'nolabel', 'nologscale', 'nomultiplot', 'nostyle',\n\ 'notitle', 'no[xyz]format', 'no[xyz]tics', 'numerics', 'origin',\n\ 'output', 'palette', 'papersize', 'pointlinewidth', 'pointsize', 'preamble',\n\ 'samples', 'seed', 'size', 'size noratio', 'size ratio', 'size square',\n\ 'style', 'terminal', 'textcolor', 'texthalign', 'textvalign', 'title',\n\ 'trange', 'unit', 'urange', 'view', 'viewer', 'vrange', 'width',\n\ '[xyz]format', '[xyz]label', '[xyz]range', '[xyz]tics'\n\ "); sprintf(ppltxt_set_noword, "\n\ Set options which Pyxplot recognises are: [] = choose one, <> = optional\n\ %s\n\ ", ppltxt_valid_set_options); sprintf(ppltxt_unset_noword, "\n\ Unset options which Pyxplot recognises are: [] = choose one, <> = optional\n\ \n\ 'arrow', 'autoscale', 'axescolor', 'axis', 'axisunitstyle', 'backup', 'bar',\n\ 'binorigin', 'binwidth', 'boxfrom', 'boxwidth', 'c1format', 'c1label',\n\ 'calendar', 'clip', 'colmap', 'colkey', 'contours', 'crange', 'data style',\n\ 'display', 'filter', 'fontsize', 'function style', 'grid', 'gridmajcolor',\n\ 'gridmincolor', 'key', 'keycolumns', 'label', 'linewidth', 'logscale',\n\ 'multiplot', 'noarrow', 'noaxis', 'nobackup', 'nodisplay', 'nogrid', 'nokey',\n\ 'nolabel', 'nologscale', 'nomultiplot', 'notitle', 'no[xyz]tics',\n\ 'numerics', 'origin', 'output', 'palette', 'papersize', 'pointlinewidth',\n\ 'pointsize', 'preamble', 'samples', 'size', 'style', 'terminal', 'textcolor',\n\ 'texthalign', 'textvalign', 'title', 'trange', 'unit', 'urange', 'view',\n\ 'viewer', 'vrange', 'width', '[xyz]format', '[xyz]label',\n\ '[xyz]range', '[xyz]tics'\n\ "); sprintf(ppltxt_set, "\n\ Error: Invalid set option '%%s'.\n\ \n\ %s", ppltxt_set_noword); sprintf(ppltxt_unset, "\n\ Error: Invalid unset option '%%s'.\n\ \n\ %s", ppltxt_unset_noword); sprintf(ppltxt_show, "\n\ Valid 'show' options are:\n\ \n\ 'all', 'arrows', 'axes', 'functions', 'settings', 'labels', 'linestyles',\n\ 'units', 'userfunctions', 'variables'\n\ \n\ or any of the following set options:\n\ 'arrow', 'autoscale', 'axescolor', 'axis', 'axisunitstyle', 'backup', 'bar',\n\ 'binorigin', 'binwidth', 'boxfrom', 'boxwidth', 'c1format', 'c1label',\n\ 'calendar', 'clip', 'colmap', 'colkey', 'contours', 'crange', 'data style',\n\ 'display', 'filter', 'fontsize', 'function style', 'grid', 'gridmajcolor',\n\ 'gridmincolor', 'key', 'keycolumns', 'label', 'linearscale', 'linewidth',\n\ 'logscale', 'multiplot', 'numerics', 'origin', 'output', 'palette',\n\ 'papersize', 'pointlinewidth', 'pointsize', 'preamble', 'samples', 'seed',\n\ 'size', 'size noratio', 'size ratio', 'size square', 'style', 'terminal',\n\ 'textcolor', 'texthalign', 'textvalign', 'title', 'trange', 'unit', 'urange',\n\ 'view', 'viewer', 'vrange', 'width', '[xyz]format', '[xyz]label',\n\ '[xyz]range', '[xyz]tics'\n\ "); } pyxplot-0.9.2/src/pyxplot.h0000664000175000017500000000177212026340554014312 0ustar dcf21dcf21// pyxplot.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: pyxplot.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _PYXPLOT_H #define _PYXPLOT_H 1 #ifndef _PYXPLOT_C #include extern sigjmp_buf ppl_sigjmpToMain; extern sigjmp_buf *ppl_sigjmpFromSigInt; #endif void ppl_sigIntHandle(int signo); #endif pyxplot-0.9.2/src/datafile.c0000664000175000017500000022063312026340554014336 0ustar dcf21dcf21// datafile.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: datafile.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _DATAFILE_C 1 #include #include #include #include #include #include #include #include #include #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "expressions/dollarOp.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "mathsTools/dcfmath.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjCmp.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" #include "children.h" #include "datafile.h" #include "datafile_rasters.h" #include "pplConstants.h" dataBlock *ppldata_NewDataBlock(const int Ncolumns_real, const int Ncolumns_obj, const int memContext, const int length) { dataBlock *output; int blockLength = 1 + DATAFILE_DATABLOCK_BYTES / ((sizeof(double)+sizeof(long int))*Ncolumns_real + (sizeof(pplObj)+sizeof(long int))*Ncolumns_obj); // automatic length if (length>0) blockLength=length; // overriden when manually specified length > 0 output = (dataBlock *)ppl_memAlloc_incontext(sizeof(dataBlock), memContext); if (output==NULL) return NULL; output->data_real = (double *) ppl_memAlloc_incontext(blockLength * Ncolumns_real * sizeof(double ), memContext); output->data_obj = (pplObj *) ppl_memAlloc_incontext(blockLength * Ncolumns_obj * sizeof(pplObj ), memContext); output->text = (char **) ppl_memAlloc_incontext(blockLength * sizeof(char * ), memContext); output->fileLine_real = (long int *) ppl_memAlloc_incontext(blockLength * Ncolumns_real * sizeof(long int ), memContext); output->fileLine_obj = (long int *) ppl_memAlloc_incontext(blockLength * Ncolumns_obj * sizeof(long int ), memContext); output->split = (unsigned char *)ppl_memAlloc_incontext(blockLength * sizeof(unsigned char), memContext); output->blockLength = blockLength; output->blockPosition = 0; output->next = NULL; output->prev = NULL; if ((output->data_real==NULL)||(output->text==NULL)||(output->fileLine_real==NULL)||(output->fileLine_obj==NULL)||(output->split==NULL)) return NULL; return output; } dataTable *ppldata_NewDataTable(const int Ncolumns_real, const int Ncolumns_obj, const int memContext, const int length) { dataTable *output; int i; output = (dataTable *)ppl_memAlloc_incontext(sizeof(dataTable), memContext); if (output==NULL) return NULL; output->Ncolumns_real = Ncolumns_real; output->Ncolumns_obj = Ncolumns_obj; output->Nrows = 0; output->memContext = memContext; output->firstEntries = (pplObj *)ppl_memAlloc_incontext(Ncolumns_real*sizeof(pplObj), memContext); if (output->firstEntries==NULL) return NULL; for (i=0;ifirstEntries + i,0,0,0); output->first = ppldata_NewDataBlock(Ncolumns_real, Ncolumns_obj, memContext, length); output->current = output->first; if (output->first==NULL) return NULL; return output; } rawDataBlock *ppldata_NewRawDataBlock(const int memContext) { rawDataBlock *output; int blockLength = 1 + DATAFILE_DATABLOCK_BYTES / (sizeof(char *)+sizeof(long int)); output = (rawDataBlock *)ppl_memAlloc_incontext(sizeof(rawDataBlock), memContext); if (output==NULL) return NULL; output->text = (char **) ppl_memAlloc_incontext(blockLength * sizeof(char * ), memContext); output->fileLine = (long int *)ppl_memAlloc_incontext(blockLength * sizeof(long int ), memContext); output->blockLength = blockLength; output->blockPosition = 0; output->next = NULL; output->prev = NULL; if ((output->text==NULL)||(output->fileLine==NULL)) return NULL; return output; } rawDataTable *ppldata_NewRawDataTable(const int memContext) { rawDataTable *output; output = (rawDataTable *)ppl_memAlloc_incontext(sizeof(rawDataTable), memContext); if (output==NULL) return NULL; output->Nrows = 0; output->memContext = memContext; output->first = ppldata_NewRawDataBlock(memContext); output->current = output->first; if (output->first==NULL) return NULL; return output; } int ppldata_DataTable_AddRow(dataTable *i) { if (i==NULL) return 1; if (i->current==NULL) return 1; i->Nrows++; if (i->current->blockPosition < (i->current->blockLength-1)) { i->current->blockPosition++; return 0; } i->current->next = ppldata_NewDataBlock(i->Ncolumns_real, i->Ncolumns_obj, i->memContext, -1); if (i->current==NULL) return 1; i->current->blockPosition = i->current->blockLength; i->current->next->prev = i->current; i->current = i->current->next; return 0; } int ppldata_RawDataTable_AddRow(rawDataTable *i) { if (i==NULL) return 1; if (i->current==NULL) return 1; i->Nrows++; if (i->current->blockPosition < (i->current->blockLength-1)) { i->current->blockPosition++; return 0; } i->current->next = ppldata_NewRawDataBlock(i->memContext); if (i->current==NULL) return 1; i->current->blockPosition = i->current->blockLength; i->current->next->prev = i->current; i->current = i->current->next; if (i->current==NULL) return 1; return 0; } void ppldata_DataTable_List(ppl_context *c, dataTable *i) { dataBlock *blk; pplObj v; int j,k,Ncolumns; if (i==NULL) { printf("\n"); return; } printf("Table size: %d x %ld\n", i->Ncolumns_real, i->Nrows); printf("Memory context: %d\n", i->memContext); blk = i->first; Ncolumns = i->Ncolumns_real; while (blk != NULL) { for (j=0; jblockPosition; j++) { if (blk->split[j]) printf("\n\n"); for (k=0; kfirstEntries[k]; v.real = blk->data_real[j*Ncolumns + k]; v.imag = 0.0; v.flagComplex = 0; printf("%15s [line %6ld] ",ppl_unitsNumericDisplay(c, &v, 0, 0, 0), blk->fileLine_real[j*Ncolumns + k] ); } if (blk->text[j] != NULL) printf("Label: <%s>",blk->text[j]); printf("\n"); } blk=blk->next; } } // on error, returns NULL with error message in errtext. FILE *ppldata_LaunchCoProcess(ppl_context *c, char *filename, int wildcardMatchNumber, char *filenameOut, char *errtext) { FILE *infile; dictIterator *dictIter; char *filter, *filterArgs, **argList; int i,j,k; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); // Implement the magic filename '' to refer to the last used filename if (filename[0]=='\0') filename = c->dollarStat.lastFilename; else { strncpy(c->dollarStat.lastFilename, filename, FNAME_LENGTH); c->dollarStat.lastFilename[FNAME_LENGTH-1]='\0'; } // glob filename { int i, done=0, C; wordexp_t wordExp; glob_t globData; char fName[FNAME_LENGTH]; { int j,k; for (j=k=0; ((filename[j]!='\0')&&(kerrcontext, errtext); return NULL; }; for (i=0; ierrcontext, errtext); return NULL; } if (C>=globData.gl_pathc) { C-=globData.gl_pathc; globfree(&globData); continue; } filename = (char *)ppl_memAlloc(strlen(globData.gl_pathv[C])+1); if (filename==NULL) { sprintf(errtext, "Out of memory (00)."); globfree(&globData); wordfree(&wordExp); return NULL; } strcpy(filename, globData.gl_pathv[C]); globfree(&globData); done=1; break; } wordfree(&wordExp); if (!done) { if (wildcardMatchNumber==0) sprintf(errtext, "Could not open file '%s'.", fName); else sprintf(errtext, "glob produced too few hits."); if (DEBUG) ppl_log(&c->errcontext, errtext); return NULL; } if (filenameOut!=NULL) { strncpy(filenameOut, filename, FNAME_LENGTH); filenameOut[FNAME_LENGTH-1]='\0'; } } // Check whether we have a specified coprocessor to work on this filetype dictIter = ppl_dictIterateInit(c->set->filters); while (dictIter != NULL) { char *dkey=NULL; if (ppl_strWildcardTest(filename, dictIter->key)) { filter = (char *)((pplObj *)dictIter->data)->auxil; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Using input filter '%s'.", filter); ppl_log(&c->errcontext, NULL); } filterArgs = (char *)ppl_memAlloc(strlen(filter)+1); argList = (char **)ppl_memAlloc((strlen(filter)/2+1)*sizeof(char *)); if ((filterArgs==NULL)||(argList==NULL)) { sprintf(errtext,"Out of memory (01)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return NULL; }; strcpy(filterArgs, filter); for (i=j=k=0; filterArgs[i]!='\0'; i++) { if ((k==0) && (filterArgs[i]> ' ')) { k=1; argList[j++] = filterArgs+i; } else if ((k==1) && (filterArgs[i]<=' ')) { k=0; filterArgs[i] = '\0'; } } argList[j++] = filename; argList[j++] = NULL; pplcsp_forkInputFilter(c, argList, &i); // Fork process for input filter, and runned piped output through the standard IO library using fdopen() sigprocmask(SIG_UNBLOCK, &sigs, NULL); if ((infile = fdopen(i, "r")) == NULL) { sprintf(errtext,"Could not open connection to input filter '%s'.",argList[0]); if (DEBUG) ppl_log(&c->errcontext, errtext); return NULL; }; return infile; } ppl_dictIterate(&dictIter, &dkey); } // If not, then we just open the file and return a file-handle to it if ((infile = fopen(filename, "r")) == NULL) { sprintf(errtext,"Could not open input file '%s'.",filename); if (DEBUG) ppl_log(&c->errcontext, errtext); return NULL; }; return infile; } void ppldata_UsingConvert(ppl_context *c, pplExpr *input, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int iterDepth) { double dbl=0; int i=-1; int l=strlen(input->ascii); int namedColumn=0; *status=0; ppl_dollarOp_config(c, columns_str, columns_val, Ncols, filename, file_linenumber, file_linenumbers, linenumber_count, block_count, index_number, usingRowCol, input->ascii, colHeads, NcolHeads, colUnits, NcolUnits); while ((l>0)&&(input->ascii[l]>='\0')&&(input->ascii[l]<=' ')) l--; if (ppl_validFloat(input->ascii,&i)&&(i>l)) // using 1:2 -- number is column number -- "1" means "the contents of column 1", i.e. "$1". { dbl = ppl_getFloat(input->ascii,NULL); if ((dbl>-4)&&(dblascii)==0) { dbl=i+1.01; namedColumn=1; break; } } // using ColumnName c->dollarStat.warntxt[0]='\0'; if (namedColumn) // Clean up these cases { c->stackPtr++; // Function below assumes it is over-writing the top item on the stack ppl_dollarOp_fetchColByNum(c, input, 0, (int)round(dbl)); } else { int lOp=0; ppl_expEval(c, input, &lOp, 1, iterDepth+1); } if ((c->errStat.status) || (c->dollarStat.warntxt[0]!='\0')) { int errp = c->errStat.errPosExpr, prefix=0; char *errt = NULL; if (errp<0) errp=0; if (c->dollarStat.warntxt[0]!='\0') { errt=c->dollarStat.warntxt; prefix=0; } else if (c->errStat.errMsgExpr[0]!='\0') errt=c->errStat.errMsgExpr; else if (c->errStat.errMsgCmd [0]!='\0') errt=c->errStat.errMsgCmd; else errt="Fail occured."; if (prefix) sprintf(errtext, "%s:%ld: Could not evaluate expression <%s>. The error, encountered at character position %d, was: '%s'", filename, file_linenumber, input->ascii, errp, errt); else strcpy(errtext, errt); ppl_tbClear(c); *status=1; } ppl_dollarOp_deconfig(c); // Disable dollar operator return; } #define COUNTERR_BEGIN if (*errCount> 0) { (*errCount)--; #define COUNTERR_END if (*errCount==0) { sprintf(c->errcontext.tempErrStr, "%s:%ld: Too many errors: no more errors will be shown.",filename,file_linenumber); \ ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(errtext,"Stack forward reference detected."); ppl_warning(&c->errcontext,ERR_STACKED,errtext); FAIL; } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } #define FAIL { COUNTERR_BEGIN; ppl_warning(&c->errcontext, ERR_STACKED, errtext); COUNTERR_END; *status = 1; *discontinuity = 1; if (DEBUG) ppl_log(&c->errcontext, errtext); return; } void ppldata_ApplyUsingList(ppl_context *c, dataTable *out, pplExpr **usingExprs, pplExpr *labelExpr, pplExpr *selectExpr, int continuity, int *discontinuity, char **columns_str, pplObj *columns_val, int Ncols, char *filename, long file_linenumber, long *file_linenumbers, long linenumber_count, long block_count, long index_number, int usingRowCol, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int *errCount, int iterDepth) { ppl_context *context = c; const int stkLevelOld = c->stackPtr; const int nUsing = out->Ncolumns_real + out->Ncolumns_obj; char **labOut = &out->current->text[out->current->blockPosition]; const int memContext = out->memContext; int i; #define stkObj (&c->stack[c->stackPtr-1]) *status = 0; *labOut = NULL; // select criterion if (selectExpr != NULL) { int fail = 0; pplExpr *ex = selectExpr; ppldata_UsingConvert(c, ex, columns_str, columns_val, Ncols, filename, file_linenumber, file_linenumbers, linenumber_count, block_count, index_number, usingRowCol, colHeads, NcolHeads, colUnits, NcolUnits, &fail, errtext, iterDepth); if (fail) { STACK_CLEAN; FAIL; } CAST_TO_BOOL(stkObj); if (stkObj->real == 0) { STACK_CLEAN; *discontinuity=(continuity==DATAFILE_DISCONTINUOUS); *status=0; return; } STACK_CLEAN; } // label if (labelExpr != NULL) { int fail = 0; char *labIn = NULL; pplExpr *ex = labelExpr; ppldata_UsingConvert(c, ex, columns_str, columns_val, Ncols, filename, file_linenumber, file_linenumbers, linenumber_count, block_count, index_number, usingRowCol, colHeads, NcolHeads, colUnits, NcolUnits, &fail, errtext, iterDepth); if (fail) { STACK_CLEAN; FAIL; } if (stkObj->objType!=PPLOBJ_STR) { sprintf(errtext, "%s:%ld: Label expression '%s' did not evaluate to a string, but to type <%s>.", filename, file_linenumber, ex->ascii, pplObjTypeNames[stkObj->objType]); STACK_CLEAN; FAIL; } labIn = (char *)stkObj->auxil; *labOut = (char *)ppl_memAlloc_incontext(strlen(labIn)+1, memContext); if (*labOut!=NULL) strcpy(*labOut, labIn); STACK_CLEAN; } // using expressions for (i=0; i=out->Ncolumns_real; const int idx = outObj ? (i-out->Ncolumns_real) : i; pplExpr *ex = usingExprs[i]; ppldata_UsingConvert(c, ex, columns_str, columns_val, Ncols, filename, file_linenumber, file_linenumbers, linenumber_count, block_count, index_number, usingRowCol, colHeads, NcolHeads, colUnits, NcolUnits, &fail, errtext, iterDepth); if (fail) { STACK_CLEAN; FAIL; } if (!outObj) { if ((stkObj->objType!=PPLOBJ_NUM)&&(stkObj->objType!=PPLOBJ_BOOL)&&(stkObj->objType!=PPLOBJ_DATE)) { sprintf(errtext, "%s:%ld: Data item calculated from expression '%s' was not a number, but had type <%s>.", filename, file_linenumber, ex->ascii, pplObjTypeNames[stkObj->objType]); STACK_CLEAN; FAIL; } if ((stkObj->objType==PPLOBJ_NUM) && (stkObj->flagComplex)) { sprintf(errtext, "%s:%ld: Data item calculated from expression '%s' was a complex number.", filename, file_linenumber, ex->ascii); STACK_CLEAN; FAIL; } if (out->Nrows==0) { out->firstEntries[i] = *stkObj; out->firstEntries[i].refCount = 1; // no memory leak here, as all allowed types have no auxilary data out->firstEntries[i].amMalloced = 0; } else { if (out->firstEntries[i].objType != stkObj->objType) { sprintf(errtext, "%s:%ld: Data item calculated from expression '%s' has inconsistent types, including <%s> and <%s>.", filename, file_linenumber, ex->ascii, pplObjTypeNames[out->firstEntries[i].objType], pplObjTypeNames[stkObj->objType]); STACK_CLEAN; FAIL; } if ( (out->firstEntries[i].objType==PPLOBJ_NUM) && (!ppl_unitsDimEqual(&out->firstEntries[i], stkObj)) ) { sprintf(errtext, "%s:%ld: Data item calculated from expression '%s' has inconsistent physical units, including <%s> and <%s>.", filename, file_linenumber, ex->ascii, ppl_printUnit(c, &out->firstEntries[i], NULL, NULL, 0, 1, 0), ppl_printUnit(c, stkObj, NULL, NULL, 1, 1, 0)); STACK_CLEAN; FAIL; } } out->current->data_real[idx + out->current->blockPosition * out->Ncolumns_real] = stkObj->real; } else { pplObj *oo = &out->current->data_obj[idx + out->current->blockPosition * out->Ncolumns_obj]; oo->refCount = 1; pplObjCpy(oo,stkObj,0,0,1); } STACK_CLEAN; } out->current->split[out->current->blockPosition] = *discontinuity; i = ppldata_DataTable_AddRow(out); if (i) { sprintf(errtext, "%s:%ld: Out of memory storing data table.", filename, file_linenumber); *errCount=-1; FAIL; } *discontinuity = 0; return; } void ppldata_RotateRawData(ppl_context *c, rawDataTable **in, dataTable *out, pplExpr **usingExprs, pplExpr *labelExpr, pplExpr *selectExpr, int continuity, char *filename, long block_count, long index_number, char **colHeads, int NcolHeads, pplObj *colUnits, int NcolUnits, int *status, char *errtext, int *errCount, int iterDepth) { int i; long linenumber_count = 0; int discontinuity = 1; int contextRaw = (*in )->memContext; unsigned char hadspace[MAX_DATACOLS]; unsigned char hadcomma[MAX_DATACOLS]; for (i=0; ifirst; char *rowData[MAX_DATACOLS]; long file_linenumber[MAX_DATACOLS]; while ((blk!=NULL)&&(NcolsblockPosition)&&(Ncolstext[i]; if (s==NULL) { rowData[Ncols]=" "; file_linenumber[Ncols]=-1; Ncols++; } else { int caught=0, p=0; for ( ; (s[p]!='\0') ; p++) { if (s[p]<=' ') { hadspace[Ncols] = 1; } else if (s[p]==',') { p++; while ((s[p]!='\0')&&(s[p]<=' ')) { p++; } caught=1; hadspace[Ncols] = hadcomma[Ncols] = 1; } else { if (hadspace[Ncols] && !hadcomma[Ncols]) { caught=1; } hadspace[Ncols] = hadcomma[Ncols] = 0; } if (caught) break; } blk->text[i] += p; if (!caught) { rowData[Ncols]=" "; file_linenumber[Ncols]=-1; Ncols++; } else { rowData [Ncols] = blk->text [i]; file_linenumber[Ncols] = blk->fileLine[i]; Ncols++; gotData = 1; } } } blk = blk->next; } if (!gotData) break; ppldata_ApplyUsingList(c, out, usingExprs, labelExpr, selectExpr, continuity, &discontinuity, rowData, NULL, Ncols, filename, file_linenumber[0], file_linenumber, linenumber_count, block_count, index_number, DATAFILE_ROW, colHeads, NcolHeads, colUnits, NcolUnits, status, errtext, errCount, iterDepth); linenumber_count++; } ppl_memAlloc_Free(contextRaw); *in = ppldata_NewRawDataTable(contextRaw); return; } // Routines for sorting data tables typedef struct ppldata_sorter { double *data_real; pplObj *data_obj; char *text; long *fileLine_real; long *fileLine_obj; unsigned char split; } ppldata_sorter; static int ppldata_sort_sortCol; static int ppldata_sort_cmp(const void *xv, const void *yv) { ppldata_sorter *x = (ppldata_sorter *)xv; ppldata_sorter *y = (ppldata_sorter *)yv; return pplObjCmpQuiet( (void *)&x->data_obj[ppldata_sort_sortCol] , (void *)&y->data_obj[ppldata_sort_sortCol] ); } dataTable *ppldata_sort(ppl_context *c, dataTable *in, int sortCol, int ignoreContinuity) { int i,io,Nc,Nd,Nr; long ji,jo; dataBlock *blk; ppldata_sorter *sorter; dataTable *output; if (in==NULL) return NULL; Nc = in->Ncolumns_obj; Nd = in->Ncolumns_real; Nr = in->Nrows; sorter = (ppldata_sorter *)malloc(Nr * sizeof(ppldata_sorter)); if (sorter==NULL) return NULL; // Transfer data from DataTable into a DataTable_sorter array which is in a format qsort() can sort blk = in->first; jo=0; while (blk != NULL) { long ji; for (ji=0; jiblockPosition; ji++, jo++) { sorter[jo].data_real = &(blk->data_real [Nd*ji]); sorter[jo].data_obj = &(blk->data_obj [Nc*ji]); sorter[jo].text = blk->text [ ji]; sorter[jo].fileLine_real = &(blk->fileLine_real[Nc*ji]); sorter[jo].fileLine_obj = &(blk->fileLine_obj [Nc*ji]); if (ignoreContinuity) sorter[jo].split = 0; else sorter[jo].split = blk->split[ji]; } blk=blk->next; } // Sort the DataTable_sorter array ppldata_sort_sortCol = sortCol - in->Ncolumns_real; for (i=0,io=0; io<=jo; io++) if ((io==jo) || sorter[io].split) { qsort((void *)(sorter+i), io-i, sizeof(ppldata_sorter), ppldata_sort_cmp); sorter[i].split = (i!=0); for (ji=i+1; jimemContext, Nr); if (output!=NULL) { const int sc = sortCol - in->Ncolumns_real; int i, io; long jo; for (i=0,io=0; ifirstEntries [io++] = in->firstEntries[i]; for (jo=0; jofirst->data_real [(io++)+ Nc *jo] = sorter[jo].data_real[i]; for (jo=0; jofirst->data_obj [(io++)+(Nd-1)*jo] = sorter[jo].data_obj [i]; for (jo=0; jofirst->text [ jo] = sorter[jo].text; for (jo=0; jofirst->fileLine_real[(io++)+ Nc *jo] = sorter[jo].fileLine_real[i]; for (jo=0; jofirst->fileLine_obj [(io++)+(Nd-1)*jo] = sorter[jo].fileLine_obj [i]; for (jo=0; jofirst->split [ jo] = sorter[jo].split; output->Nrows = Nr; output->first->blockPosition = Nr; } free(sorter); return output; } static char *ppldata_fetchFromSpool(parserLine **dataSpool) { char *out; if ((dataSpool==NULL)||(*dataSpool==NULL)) return NULL; out = (*dataSpool)->linetxt; *dataSpool = (*dataSpool)->next; return out; } int ppldata_autoUsingList(ppl_context *c, pplExpr **usingExprs, int Ncols, char *errtext) { int i; for (i=0; ierrStat.status) { ppl_tbClear(c); sprintf(errtext, "Out of memory (03)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return 1; } usingExprs[i] = pplExpr_tmpcpy(exptmp); pplExpr_free(exptmp); if (usingExprs[i]==NULL) { sprintf(errtext, "Out of memory (04)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return 1; } } return 0; } void ppldata_fromFile(ppl_context *c, dataTable **out, char *filename, int wildcardMatchNumber, char *filenameOut, parserLine **dataSpool, int indexNo, pplExpr **usingExprs, int autoUsingExprs, int Ncols, int NusingObjs, pplExpr *labelExpr, pplExpr *selectExpr, pplExpr *sortBy, int usingRowCol, long *everyList, int continuity, int persistent, int *status, char *errtext, int *errCount, int iterDepth) { int readFromCommandLine=0, discontinuity=0, hadwhitespace, hadcomma, oneColumnInput=1; int contextOutput, contextRough, contextRaw; char lineNumberStr[32]; const long linestep=everyList[0], blockstep=everyList[1], linefirst=everyList[2], blockfirst=everyList[3], linelast=everyList[4], blocklast=everyList[5]; long index_number = 0; long linenumber_count = 0; long linenumber_stepcnt = 0; long block_count = 0; long block_stepcnt = 0; long prev_blanklines = 10; long file_linenumber = 0; long itemsOnLine; FILE *filtered_input=NULL; char linebuffer[LSTR_LENGTH], *lineptr=linebuffer, *linebufferPtr=&linebuffer[0], *cptr; int i, j, k, l, m; char **columnHeadings = NULL; int NcolumnHeadings = 0; char **rowHeadings = NULL; int NrowHeadings = 0; pplObj *columnUnits = NULL; int NcolumnUnits = 0; pplObj *rowUnits = NULL; int NrowUnits = 0; char *colData[MAX_DATACOLS]; rawDataTable *rawDataTab = NULL; // Init if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Opening datafile '%s'.", filename); ppl_log(&c->errcontext,NULL); } if (Ncols < 0) { // If number of columns unspecified, assume two autoUsingExprs=1; if ((*status=ppldata_autoUsingList(c, usingExprs, Ncols=2, errtext))) return; } if (Ncols != 2) oneColumnInput=0; // Only have special handling for one-column datafiles when looking for two columns // If sortBy is not null, add it to using list if (sortBy != NULL) { usingExprs[Ncols] = sortBy; NusingObjs++; Ncols++; } // Open requested datafile if (strcmp(filename, "-" )==0) { if (wildcardMatchNumber>0) { *status=1; return; } filtered_input=stdin; if (DEBUG) ppl_log(&c->errcontext,"Reading from stdin."); } else if (strcmp(filename, "--")==0) { if (wildcardMatchNumber>0) { *status=1; return; } readFromCommandLine=1; if (DEBUG) ppl_log(&c->errcontext,"Reading from command line."); } else { filtered_input = ppldata_LaunchCoProcess(c, filename, wildcardMatchNumber, filenameOut, errtext); if (filtered_input==NULL) { *status=1; return; } } #define FCLOSE_FI { if ((!readFromCommandLine) && (filtered_input!=stdin)) fclose(filtered_input); } // Keep a record of the memory context we're going to output into, and then make a scratchpad context contextOutput = persistent ? 0 : ppl_memAlloc_GetMemContext(); contextRough = ppl_memAlloc_DescendIntoNewContext(); // Rough mallocs inside this subroutine happen in this context contextRaw = ppl_memAlloc_DescendIntoNewContext(); // Raw data goes into here when plotting with rows *out = ppldata_NewDataTable(Ncols-NusingObjs, NusingObjs, contextOutput, -1); if (*out == NULL) { strcpy(errtext, "Out of memory whilst trying to allocate data table to read data from file."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } if (usingRowCol == DATAFILE_ROW) { rawDataTab = ppldata_NewRawDataTable(contextRaw); if (rawDataTab == NULL) { strcpy(errtext, "Out of memory whilst trying to allocate data table to read data from file."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } } // Read input file, line by line while (readFromCommandLine || ( (!ferror(filtered_input)) && (!feof(filtered_input)) )) { if (cancellationFlag) break; if (!readFromCommandLine) ppl_file_readline(filtered_input, &linebufferPtr, NULL, LSTR_LENGTH); else lineptr = ppldata_fetchFromSpool(dataSpool); if (readFromCommandLine && (lineptr==NULL )) break; // End of file reached if (readFromCommandLine && (strcmp(ppl_strStrip(lineptr, linebuffer),"END")==0)) break; file_linenumber++; ppl_strStrip(lineptr, linebuffer); for (j=0; ((linebuffer[j]!='\0')&&(linebuffer[j]<=' ')); j++); if (linebuffer[j]=='\0') // We have a blank line { if (prev_blanklines>1) continue; // A very long gap in the datafile prev_blanklines++; if (prev_blanklines==1) { block_count++; // First newline gives us a new block block_stepcnt = ((block_stepcnt-1) % blockstep); discontinuity=1; // We want to break the line here linenumber_count=0; // Zero linecounter within block linenumber_stepcnt=0; } else { index_number++; // Second newline gives us a new index block_count=0; // Zero block counter block_stepcnt=0; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Index %ld begins on line %ld of datafile.", index_number, file_linenumber); ppl_log(&c->errcontext, NULL); } if ((indexNo>=0) && (index_number>indexNo)) break; // We'll never find any more data once we've gone past the specified index } continue; } // Ignore comment lines if (linebuffer[j]=='#') { for (i=j+1; ((linebuffer[i]!='\0')&&(linebuffer[i]<=' ')); i++); if ((strncmp(linebuffer+i, "Columns:", 8)==0) && (usingRowCol == DATAFILE_COL)) // '# Columns:' means we have a list of column headings { i+=8; if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Reading column headings as specified on line %ld of datafile",file_linenumber); ppl_log(&c->errcontext,NULL); } while ((linebuffer[i]!='\0')&&(linebuffer[i]<=' ')) i++; itemsOnLine = 0; hadwhitespace = 1; for (j=i; linebuffer[j]!='\0'; j++) { if (linebuffer[j]<=' ') { hadwhitespace = 1; } else if (hadwhitespace) { itemsOnLine++; hadwhitespace = 0; } } cptr = (char *)ppl_memAlloc_incontext(j-i+1 , contextRough); strcpy(cptr, linebuffer+i); columnHeadings = (char **)ppl_memAlloc_incontext(itemsOnLine*sizeof(char *), contextRough); NcolumnHeadings = itemsOnLine; if ((cptr==NULL)||(columnHeadings==NULL)) { strcpy(errtext, "Out of memory (05)."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } itemsOnLine = 0; hadwhitespace = 1; for (j=0; cptr[j]!='\0'; j++) { if (cptr[j]<=' ') { cptr[j]='\0'; hadwhitespace = 1; } else if (hadwhitespace) { columnHeadings[itemsOnLine] = cptr+j; itemsOnLine++; hadwhitespace = 0; } } if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Total of %ld column headings read.",itemsOnLine); ppl_log(&c->errcontext,NULL); for (k=0; kerrcontext.tempErrStr,"Column heading %d: %s",k,columnHeadings[k]); ppl_log(&c->errcontext,NULL); } } } else if ((strncmp(linebuffer+i, "Rows:", 5)==0) && (usingRowCol == DATAFILE_ROW)) // '# Rows:' means we have a list of row headings { i+=5; if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Reading row headings as specified on line %ld of datafile",file_linenumber); ppl_log(&c->errcontext,NULL); } while ((linebuffer[i]!='\0')&&(linebuffer[i]<=' ')) i++; itemsOnLine = 0; hadwhitespace = 1; for (j=i; linebuffer[j]!='\0'; j++) { if (linebuffer[j]<=' ') { hadwhitespace = 1; } else if (hadwhitespace) { itemsOnLine++; hadwhitespace = 0; } } cptr = (char *)ppl_memAlloc_incontext(j-i+1 , contextRough); strcpy(cptr, linebuffer+i); rowHeadings = (char **)ppl_memAlloc_incontext(itemsOnLine*sizeof(char *), contextRough); NrowHeadings = itemsOnLine; if ((cptr==NULL)||(rowHeadings==NULL)) { strcpy(errtext, "Out of memory (06)."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } itemsOnLine = 0; hadwhitespace = 1; for (j=0; cptr[j]!='\0'; j++) { if (cptr[j]<=' ') { cptr[j]='\0'; hadwhitespace = 1; } else if (hadwhitespace) { rowHeadings[itemsOnLine] = cptr+j; itemsOnLine++; hadwhitespace = 0; } } if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Total of %ld row headings read.",itemsOnLine); ppl_log(&c->errcontext,NULL); for (k=0; kerrcontext.tempErrStr,"Row heading %d: %s",k,rowHeadings[k]); ppl_log(&c->errcontext,NULL); } } } else if (strncmp(linebuffer+i, "ColumnUnits:", 12)==0) // '# ColumnUnits:' means we have a list of column units { i+=12; if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Reading column units as specified on line %ld of datafile",file_linenumber); ppl_log(&c->errcontext,NULL); } while ((linebuffer[i]!='\0')&&(linebuffer[i]<=' ')) i++; itemsOnLine = 0; hadwhitespace = 1; for (j=i; linebuffer[j]!='\0'; j++) { if (linebuffer[j]<=' ') { hadwhitespace = 1; } else if (hadwhitespace) { itemsOnLine++; hadwhitespace = 0; } } cptr = (char *)ppl_memAlloc_incontext(j-i+2 , contextRough); strncpy(cptr, linebuffer+i, j-i+2); columnUnits = (pplObj *)ppl_memAlloc_incontext(itemsOnLine*sizeof(pplObj), contextRough); NcolumnUnits = itemsOnLine; if ((cptr==NULL)||(columnUnits==NULL)) { strcpy(errtext, "Out of memory (07)."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } itemsOnLine = 0; hadwhitespace = 1; for (k=0; cptr[k]!='\0'; k++) { if (cptr[k]<=' ') { continue; } else { for (l=0; cptr[k+l]>' '; l++); cptr[k+l]='\0'; m=-1; columnUnits[itemsOnLine].refCount = 1; pplObjNum(columnUnits+itemsOnLine,0,1,0); ppl_unitsStringEvaluate(c, cptr+k, columnUnits+itemsOnLine, &l, &m, errtext); if (m>=0) { pplObjNum(columnUnits+itemsOnLine,0,1,0); COUNTERR_BEGIN; sprintf(c->errcontext.tempErrStr,"%s:%ld:%d: %s",filename,file_linenumber,i+k,errtext); ppl_warning(&c->errcontext,ERR_STACKED,NULL); COUNTERR_END; } itemsOnLine++; k+=l; } } if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Total of %ld column units read.",itemsOnLine); ppl_log(&c->errcontext,NULL); for (k=0; kerrcontext.tempErrStr,"Column unit %d: %s",k,ppl_unitsNumericDisplay(c,columnUnits+k,0,0,0)); ppl_log(&c->errcontext,NULL); } } } else if (strncmp(linebuffer+i, "RowUnits:", 9)==0) // '# RowUnits:' means we have a list of row units { i+=9; if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Reading row units as specified on line %ld of datafile",file_linenumber); ppl_log(&c->errcontext,NULL); } while ((linebuffer[i]!='\0')&&(linebuffer[i]<=' ')) i++; itemsOnLine = 0; hadwhitespace = 1; for (j=i; linebuffer[j]!='\0'; j++) { if (linebuffer[j]<=' ') { hadwhitespace = 1; } else if (hadwhitespace) { itemsOnLine++; hadwhitespace = 0; } } cptr = (char *)ppl_memAlloc_incontext(j-i+2 , contextRough); strncpy(cptr, linebuffer+i, j-i+2); rowUnits = (pplObj *)ppl_memAlloc_incontext(itemsOnLine*sizeof(pplObj), contextRough); NrowUnits = itemsOnLine; if ((cptr==NULL)||(rowUnits==NULL)) { strcpy(errtext, "Out of memory (08)."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } itemsOnLine = 0; hadwhitespace = 1; for (k=0; cptr[k]!='\0'; k++) { if (cptr[k]<=' ') { continue; } else { for (l=0; cptr[k+l]>' '; l++); cptr[k+l]='\0'; m=-1; rowUnits[itemsOnLine].refCount = 1; pplObjNum(rowUnits+itemsOnLine,0,1,0); ppl_unitsStringEvaluate(c, cptr+k, rowUnits+itemsOnLine, &l, &m, errtext); if (m>=0) { pplObjNum(rowUnits+itemsOnLine,0,1,0); COUNTERR_BEGIN; sprintf(c->errcontext.tempErrStr,"%s:%ld:%d: %s",filename,file_linenumber,i+k,errtext); ppl_warning(&c->errcontext,ERR_STACKED,NULL); COUNTERR_END; } itemsOnLine++; k+=l; } } if (DEBUG) { sprintf(c->errcontext.tempErrStr,"Total of %ld row units read.",itemsOnLine); ppl_log(&c->errcontext,NULL); for (k=0; kerrcontext.tempErrStr,"Row unit %d: %s",k,ppl_unitsNumericDisplay(c,rowUnits+k,0,0,0)); ppl_log(&c->errcontext,NULL); } } } continue; // Ignore comment lines } prev_blanklines=0; // If we're in an index we're ignoring, don't do anything with this line if ((indexNo>=0) && (index_number != indexNo)) continue; // If we're in a block that we're ignoring, don't do anything with this line if ((block_stepcnt!=0) || ((blockfirst>=0)&&(block_count=0)&&(block_count>blocklast))) continue; // Fetch this line if linenumber is within range, or if we are using rows and we need everything if (usingRowCol == DATAFILE_ROW) // Store the whole line into a raw text spool { if (discontinuity) ppldata_RotateRawData(c, &rawDataTab, *out, usingExprs, labelExpr, selectExpr, continuity, filename, block_count, index_number, rowHeadings, NrowHeadings, rowUnits, NrowUnits, status, errtext, errCount, iterDepth); if (*status) { FCLOSE_FI; return; } cptr = rawDataTab->current->text[rawDataTab->current->blockPosition] = (char *)ppl_memAlloc_incontext(strlen(linebuffer)+1, contextRaw); if (cptr==NULL) { strcpy(errtext, "Out of memory whilst placing data into text spool."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } strcpy(cptr, linebuffer); rawDataTab->current->fileLine[rawDataTab->current->blockPosition] = file_linenumber; if (ppldata_RawDataTable_AddRow(rawDataTab)) { strcpy(errtext, "Out of memory whilst placing data into text spool."); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); FCLOSE_FI; return; } discontinuity = 0; } else if ((linenumber_stepcnt==0) && ((linefirst<0)||(linenumber_count>=linefirst)) && ((linelast<0)||(linenumber_count<=linelast))) { // Count the number of data items on this line itemsOnLine = 0; hadwhitespace = 1; hadcomma = 0; for (i=0; linebuffer[i]!='\0'; i++) { if (linebuffer[i]<=' ') { hadwhitespace = 1; } else if (linebuffer[i]==',') { int j; for (j=i+1;((linebuffer[j]<=' ')&&(linebuffer[j]!='\0'));j++); colData[itemsOnLine++]=linebuffer+j; hadwhitespace = hadcomma = 1; } else { if (hadwhitespace && !hadcomma) { colData[itemsOnLine++]=linebuffer+i; } hadwhitespace = hadcomma = 0; } if (itemsOnLine==MAX_DATACOLS) break; // Don't allow ColumnData array to overflow } // Add line numbers as first column to one-column datafiles if (itemsOnLine > 1) oneColumnInput=0; if ((itemsOnLine == 1) && autoUsingExprs && oneColumnInput) { colData[itemsOnLine++]=colData[0]; colData[0]=lineNumberStr; sprintf(lineNumberStr,"%ld",file_linenumber); } ppldata_ApplyUsingList(c, *out, usingExprs, labelExpr, selectExpr, continuity, &discontinuity, colData, NULL, itemsOnLine, filename, file_linenumber, NULL, linenumber_count, block_count, index_number, DATAFILE_COL, columnHeadings, NcolumnHeadings, columnUnits, NcolumnUnits, status, errtext, errCount, iterDepth); if (*status) { *status=0; /* It was just a warning... */ } } linenumber_count++; linenumber_stepcnt = ((linenumber_stepcnt-1) % linestep); } // Close input file FCLOSE_FI; // If we are reading rows, go through all of the data that we've read and rotate it by 90 degrees if (usingRowCol == DATAFILE_ROW) { ppldata_RotateRawData(c, &rawDataTab, *out, usingExprs, labelExpr, selectExpr, continuity, filename, block_count, index_number, rowHeadings, NrowHeadings, rowUnits, NrowUnits, status, errtext, errCount, iterDepth); if (*status) return; } // If data is to be sorted, sort it now if (sortBy != NULL) { *out = ppldata_sort(c, *out, Ncols-1, continuity==DATAFILE_CONTINUOUS); } // Debugging line // ppldata_DataTable_List(*out); // Delete rough workspace ppl_memAlloc_AscendOutOfContext(contextRough); return; } void ppldata_fromFuncs(ppl_context *c, dataTable **out, pplExpr **fnlist, int fnlist_len, double *rasterX, int rasterXlen, int parametric, pplObj *unitX, double *rasterY, int rasterYlen, pplObj *unitY, pplExpr **usingExprs, int autoUsingExprs, int Ncols, int NusingObjs, pplExpr *labelExpr, pplExpr *selectExpr, pplExpr *sortBy, int continuity, int *status, char *errtext, int *errCount, int iterDepth) { int discontinuity2=0, *discontinuity=&discontinuity2; const int sampleGrid=(rasterY!=NULL); int a, j, k, contextOutput; long expectedNrows; char buffer[FNAME_LENGTH]; pplObj colData[USING_ITEMS_MAX+2]; pplObj *ordinateVar[2], dummyTemp[2]; // Init if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Evaluated supplied set of functions."); ppl_log(&c->errcontext,NULL); } if (fnlist_len>USING_ITEMS_MAX) { sprintf(errtext, "Too many functions supplied. A maximum of %d are allowed.", USING_ITEMS_MAX); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); return; } if (Ncols<0) { // If number of columns unspecified, assume two autoUsingExprs=1; if ((*status=ppldata_autoUsingList(c, usingExprs, Ncols=fnlist_len+(!parametric)+((!parametric)&&sampleGrid), errtext))) return; } for (a=0; aerrcontext,errtext); return; } // Loop over ordinate values { int i,i2; const int ilen=rasterXlen, i2len = sampleGrid?rasterYlen:1; int offset=1+(!parametric)+((!parametric)&&sampleGrid); long p=0; for (i2=0; i2amMalloced; rc = ordinateVar[a]->refCount; ordinateVar[a]->amMalloced = 0; ppl_garbageObject(ordinateVar[a]); *(ordinateVar[a]) = **ru; ordinateVar[a]->amMalloced = am; ordinateVar[a]->refCount = rc; ordinateVar[a]->self_lval = NULL; ordinateVar[a]->self_this = NULL; ordinateVar[a]->imag = 0.0; ordinateVar[a]->flagComplex = 0; } ordinateVar[0]->real = rasterX[i]; if (sampleGrid) ordinateVar[1]->real = rasterY[i2]; if (sampleGrid) sprintf(buffer, "%c=%s; %c=%s", (parametric?'u':'x'), ppl_unitsNumericDisplay(c,ordinateVar[0],0,0,0), (parametric?'v':'y'), ppl_unitsNumericDisplay(c,ordinateVar[1],1,0,0)); else sprintf(buffer, "%c=%s", (parametric?'t':'x'), ppl_unitsNumericDisplay(c,ordinateVar[0],0,0,0)); pplObjNum(colData+0,0,p,0); if (!parametric) colData[1] = *ordinateVar[0]; if ((!parametric) && sampleGrid) colData[2] = *ordinateVar[1]; for (j=0; jstackPtr; pplObj *ob; ob = ppl_expEval(c, fnlist[j], &k, 0, iterDepth); if (c->errStat.status) { int errp = c->errStat.errPosExpr; char *errt = NULL; if (errp<0) errp=0; if (c->errStat.errMsgExpr[0]!='\0') errt=c->errStat.errMsgExpr; else if (c->errStat.errMsgCmd [0]!='\0') errt=c->errStat.errMsgCmd; else errt="Fail occurred."; COUNTERR_BEGIN; sprintf(c->errcontext.tempErrStr, "%s: Could not evaluate expression <%s>. The error, encountered at character position %d, was: '%s'", buffer, fnlist[j]->ascii, errp, errt); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); COUNTERR_END; STACK_CLEAN; ppl_tbClear(c); *status=1; break; } pplObjCpy(&colData[j+offset],ob,0,0,1); STACK_CLEAN; } expectedNrows = (*out)->Nrows+1; if (!(*status)) { ppldata_ApplyUsingList(c, *out, usingExprs, labelExpr, selectExpr, continuity, &discontinuity2, NULL, colData, fnlist_len+offset-1, buffer, 0, NULL, i, 0, 0, DATAFILE_COL, NULL, 0, NULL, 0, status, errtext, errCount, iterDepth); } else { if (!sampleGrid) discontinuity2 = 1; } if (sampleGrid && ((*out)->NrowsNcolumns_real; i++) (*out)->current->data_real[i + (*out)->current->blockPosition * (*out)->Ncolumns_real] = GSL_NAN; for (i=0; i<(*out)->Ncolumns_obj ; i++) pplObjNum(&(*out)->current->data_obj[i + (*out)->current->blockPosition * (*out)->Ncolumns_obj],0,GSL_NAN,0); (*out)->current->text[(*out)->current->blockPosition] = NULL; ppldata_DataTable_AddRow(*out); } for (j=0; jv->size; pplObj colData[USING_ITEMS_MAX+2]; gsl_vector *v[USING_ITEMS_MAX+2]; // Init if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Evaluated supplied set of functions."); ppl_log(&c->errcontext,NULL); } if (objListLen>USING_ITEMS_MAX) { sprintf(errtext, "Too many functions supplied. A maximum of %d are allowed.", USING_ITEMS_MAX); *status=1; if (DEBUG) ppl_log(&c->errcontext,errtext); return; } if (Ncols<0) { // If number of columns unspecified, assume two autoUsingExprs=1; if ((*status=ppldata_autoUsingList(c, usingExprs, Ncols=objListLen, errtext))) return; } for (i=0; iv; for (i=0; ierrcontext,errtext); return; } // Loop over data for (i=0; istk; pplObj *stko = stk + stkbase; pplExpr *usingExprs[USING_ITEMS_MAX], *selectExpr=NULL, *labelExpr=NULL, *sortBy=NULL; long everyList[6]={1,1,-1,-1,-1,-1}; int Nusing=0, autoUsingList=0, continuity=DATAFILE_CONTINUOUS, usingRowCol=DATAFILE_COL, indexNo=-1; int parametric=0, sampleGrid=0, spacingSet=0, rasterXlen=0, rasterYlen=0; int XminSet=0, XmaxSet=0; double *rasterX=NULL, *rasterY=NULL; pplObj unitX, unitY; double rasterXmin=0, rasterXmax=0, rasterYmin=0, rasterYmax=0; pplObj rasterXunits, rasterYunits; *status = 0; *out = NULL; if (filenameOut!=NULL) filenameOut[0]='\0'; // Test if parametric { const int pos1 = ptab[PARSE_INDEX_parametric]; const int pos2 = ptab[PARSE_INDEX_vmin]; const int pos3 = ptab[PARSE_INDEX_tmin]; if ((pos1>0)&&(stko[pos1].objType==PPLOBJ_STR)) parametric=1; if (parametric && ((pos2> 0)&&(stko[pos1].objType!=PPLOBJ_ZOM)) ) sampleGrid=1; if (parametric && ((pos3<=0)||(stko[pos3].objType==PPLOBJ_ZOM)) && c->set->graph_current.USE_T_or_uv) sampleGrid=0; } // Devise range for functions { const int poss = ptab[PARSE_INDEX_spacing]; const int post1 = ptab[PARSE_INDEX_tmin]; const int post2 = ptab[PARSE_INDEX_tmax]; const int posv1 = ptab[PARSE_INDEX_vmin]; const int posv2 = ptab[PARSE_INDEX_vmax]; int rasterXlog=0, rasterYlog=0; if (!parametric) { pplset_axis *X = &c->set->XAxes[1]; rasterXlog = (X->log == SW_BOOL_TRUE); // Read from axis x1 if (minSet[0]) { rasterXmin = min[0]; rasterXunits = unitRange[0]; XminSet=1; } else if (X->MinSet == SW_BOOL_TRUE) { rasterXmin = X->min; rasterXunits = X->unit; XminSet=1; } else if (maxSet[0]) { rasterXmin = rasterXlog ? (max[0] / 100) : (max[0] - 20); rasterXunits = unitRange[0]; } else if (X->MaxSet == SW_BOOL_TRUE) { rasterXmin = rasterXlog ? (X->max / 100) : (X->max - 20); rasterXunits = X->unit; } else { rasterXmin = rasterXlog ? 1.0 : -10.0; pplObjNum(&rasterXunits,0,0,0); } if ((maxSet[0]) && (ppl_unitsDimEqual(&rasterXunits,&unitRange[0]))) { rasterXmax = max[0]; XmaxSet=1; } else if ((X->MaxSet == SW_BOOL_TRUE) && (ppl_unitsDimEqual(&rasterXunits,&(X->unit) ))) { rasterXmax = X->max; XmaxSet=1; } else { rasterXmax = rasterXlog ? (rasterXmin * 100) : (rasterXmin + 20); } } else if (!sampleGrid) { XminSet = 1; XmaxSet = 1; rasterXlog = (c->set->graph_current.Tlog == SW_BOOL_TRUE); rasterXmin = c->set->graph_current.Tmin.real; rasterXmax = c->set->graph_current.Tmax.real; rasterXunits = c->set->graph_current.Tmin; } else { rasterXlog = (c->set->graph_current.Ulog == SW_BOOL_TRUE); rasterXmin = c->set->graph_current.Umin.real; rasterXmax = c->set->graph_current.Umax.real; rasterXunits = c->set->graph_current.Umin; rasterYlog = (c->set->graph_current.Vlog == SW_BOOL_TRUE); rasterYmin = c->set->graph_current.Vmin.real; rasterYmax = c->set->graph_current.Vmax.real; rasterYunits = c->set->graph_current.Vmin; } if ((post1>0)&&(stko[post1].objType!=PPLOBJ_ZOM)) { rasterXmin = stko[post1].real; if ((post2<=0)||(stko[post2].objType==PPLOBJ_ZOM)) { if (stko[post1].objType!=rasterXunits.objType) { *status=1; sprintf(errtext, "Mismatched data types between lower and upper limits of first parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!ppl_unitsDimEqual(&stko[post1],&rasterXunits)) { *status=1; sprintf(errtext, "Mismatched physical units between lower and upper limits of first parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } } rasterXunits=stko[post1]; } if ((post2>0)&&(stko[post2].objType!=PPLOBJ_ZOM)) { rasterXmax = stko[post2].real; if (stko[post2].objType!=rasterXunits.objType) { *status=1; sprintf(errtext, "Mismatched data types between lower and upper limits of first parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!ppl_unitsDimEqual(&stko[post2],&rasterXunits)) { *status=1; sprintf(errtext, "Mismatched physical units between lower and upper limits of first parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } } if ((posv1>0)&&(stko[posv1].objType!=PPLOBJ_ZOM)) { rasterYmin = stko[posv1].real; if ((posv2<=0)||(stko[posv2].objType==PPLOBJ_ZOM)) { if (stko[posv1].objType!=rasterYunits.objType) { *status=1; sprintf(errtext, "Mismatched data types between lower and upper limits of second parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!ppl_unitsDimEqual(&stko[posv1],&rasterYunits)) { *status=1; sprintf(errtext, "Mismatched physical units between lower and upper limits of second parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } } rasterYunits=stko[posv1]; } if ((posv2>0)&&(stko[posv2].objType!=PPLOBJ_ZOM)) { rasterYmax = stko[posv2].real; if (stko[posv2].objType!=rasterYunits.objType) { *status=1; sprintf(errtext, "Mismatched data types between lower and upper limits of second parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!ppl_unitsDimEqual(&stko[posv2],&rasterYunits)) { *status=1; sprintf(errtext, "Mismatched physical units between lower and upper limits of second parametric variable."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } } if (rasterXlog && ((rasterXmin<=0) || (rasterXmax<=0))) ppl_warning(&c->errcontext,ERR_NUMERICAL,"Attempt to tabulate data using a logarithmic ordinate axis with negative or zero limits set. Reverting limits to finite positive values with well-defined logarithms."); if (sampleGrid && rasterYlog && ((rasterYmin<=0) || (rasterYmax<=0))) ppl_warning(&c->errcontext,ERR_NUMERICAL,"Attempt to tabulate data using a logarithmic ordinate axis with negative or zero limits set. Reverting limits to finite positive values with well-defined logarithms."); // See if spacing has been specified if ((poss>0)&&(stko[poss].objType!=PPLOBJ_ZOM)) { int i; pplObj *spacing = &stko[poss]; spacingSet=1; for (i=0; i<=sampleGrid; i++) { double SpacingDbl, NumberOfSamplesDbl; int *rast_log = i ? &rasterYlog : &rasterXlog; double *rast_min = i ? &rasterYmin : &rasterXmin; double *rast_max = i ? &rasterYmax : &rasterXmax; pplObj *rast_unit = i ? &rasterYunits : &rasterXunits; int *out = i ? &rasterYlen : &rasterXlen; if (*rast_log) { if (!spacing->dimensionless) { *status=1; sprintf(errtext, "Specified spacing has units of <%s>. However, for a logarithmic ordinate axis, the spacing should be a dimensionless multiplicative factor.", ppl_printUnit(c,spacing,NULL,NULL,0,1,0)); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if ((spacing->real < 1e-200)||(spacing->real > 1e100)) { *status=1; sprintf(errtext, "The spacing specified must be a positive multiplicative factor for logarithmic ordinate axes."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } SpacingDbl = spacing->real; if ((*rast_max > *rast_min) && (SpacingDbl < 1.0)) SpacingDbl = 1.0/SpacingDbl; if ((*rast_min > *rast_max) && (SpacingDbl > 1.0)) SpacingDbl = 1.0/SpacingDbl; NumberOfSamplesDbl = 1.0 + floor(log(*rast_max / *rast_min) / log(SpacingDbl)); if (NumberOfSamplesDbl<2 ) { *status=1; sprintf(errtext, "The spacing specified produced fewer than two samples; this does not seem sensible."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (NumberOfSamplesDbl>1e7) { *status=1; sprintf(errtext, "The spacing specified produced more than 1e7 samples. If you really want to do this, use 'set samples'."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } *rast_max = *rast_min * pow(SpacingDbl, NumberOfSamplesDbl-1); *out = (int)NumberOfSamplesDbl; } else { if (!ppl_unitsDimEqual(rast_unit,spacing)) { *status=1; sprintf(errtext, "Specified spacing has units of <%s>, for an ordinate axis which has units of <%s>,", ppl_printUnit(c,spacing,NULL,NULL,0,1,0), ppl_printUnit(c,rast_unit,NULL,NULL,1,1,0)); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } SpacingDbl = spacing->real; if ((*rast_max > *rast_min) && (SpacingDbl < 0.0)) SpacingDbl = -SpacingDbl; if ((*rast_min > *rast_max) && (SpacingDbl > 0.0)) SpacingDbl = -SpacingDbl; NumberOfSamplesDbl = 1.0 + (*rast_max - *rast_min) / SpacingDbl; if (NumberOfSamplesDbl<2 ) { *status=1; sprintf(errtext, "The spacing specified produced fewer than two samples; this does not seem sensible."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (NumberOfSamplesDbl>1e6) { *status=1; sprintf(errtext, "The spacing specified produced more than 1e6 samples. If you really want to do this, use 'set samples'."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } *rast_max = *rast_min + SpacingDbl*(NumberOfSamplesDbl+1); *out = (int)NumberOfSamplesDbl; } } } else { rasterXlen = c->set->graph_current.samples; if (sampleGrid) { rasterXlen = (c->set->graph_current.SamplesXAuto==SW_BOOL_TRUE) ? c->set->graph_current.samples : c->set->graph_current.SamplesX; rasterYlen = (c->set->graph_current.SamplesYAuto==SW_BOOL_TRUE) ? c->set->graph_current.samples : c->set->graph_current.SamplesY; } } // Make raster unitX = rasterXunits; unitX.refCount=1; unitY = rasterYunits; unitY.refCount=1; rasterX = (double *)ppl_memAlloc(rasterXlen*sizeof(double)); if (rasterX==NULL) { *status=1; sprintf(errtext, "Out of memory (09)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!rasterXlog) ppl_linRaster(rasterX, rasterXmin, rasterXmax, rasterXlen); else ppl_logRaster(rasterX, rasterXmin, rasterXmax, rasterXlen); if (sampleGrid) { rasterY = (double *)ppl_memAlloc(rasterYlen*sizeof(double)); if (rasterY==NULL) { *status=1; sprintf(errtext, "Out of memory (10)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (!rasterYlog) ppl_linRaster(rasterY, rasterYmin, rasterYmax, rasterYlen); else ppl_logRaster(rasterY, rasterYmin, rasterYmax, rasterYlen); } } // Read index number { const int pos = ptab[PARSE_INDEX_index]; if ((pos>0)&&(stko[pos].objType==PPLOBJ_NUM)) indexNo = (int)round(stko[pos].real); } // Read data spool (on first pass only) if ((dataSpool!=NULL)&&(*dataSpool==NULL)) { const int pos = ptab[PARSE_INDEX_data]; if ((pos>0)&&(stk[pos].objType==PPLOBJ_BYT)) *dataSpool = (parserLine *)stk[pos].auxil; if (*dataSpool!=NULL) *dataSpool = (*dataSpool)->next; // first line is command line } // Read select criterion { const int pos = ptab[PARSE_INDEX_select_criterion]; if ((pos>0)&&(stko[pos].objType==PPLOBJ_EXP)) selectExpr = (pplExpr *)stko[pos].auxil; } // Read sort criterion { const int pos = ptab[PARSE_INDEX_sort_expression]; if ((pos>0)&&(stko[pos].objType==PPLOBJ_EXP)) sortBy = (pplExpr *)stko[pos].auxil; } // Read select / sort continuity { const int pos1 = ptab[PARSE_INDEX_continuous]; const int pos2 = ptab[PARSE_INDEX_discontinuous]; if ((pos1>0)&&(stko[pos1].objType==PPLOBJ_STR)) continuity=DATAFILE_CONTINUOUS; if ((pos2>0)&&(stko[pos2].objType==PPLOBJ_STR)) continuity=DATAFILE_DISCONTINUOUS; } // Read label expression { const int pos = ptab[PARSE_INDEX_label]; if (pos>0) labelExpr = (pplExpr *)stko[pos].auxil; } // Read every item list { int Nevery = 0; int pos = ptab[PARSE_INDEX_every_list] + stkbase; const int o = ptab[PARSE_INDEX_every_item]; if (o>0) while (stk[pos].objType == PPLOBJ_NUM) { long x; pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nevery>=6) { ppl_warning(&c->errcontext, ERR_SYNTAX, "More than six numbers supplied to the every modifier -- trailing entries ignored."); break; } x = (long)round(stk[pos+o].real); if (x>everyList[Nevery]) everyList[Nevery]=x; Nevery++; } } // Print every list to log file if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Every %ld:%ld:%ld:%ld:%ld:%ld", everyList[0], everyList[1], everyList[2], everyList[3], everyList[4], everyList[5]); ppl_log(&c->errcontext, NULL); } // Read using rows or columns { const int pos1 = ptab[PARSE_INDEX_use_columns]; const int pos2 = ptab[PARSE_INDEX_use_rows]; if ((pos1>0)&&(stko[pos1].objType==PPLOBJ_STR)) usingRowCol=DATAFILE_COL; if ((pos2>0)&&(stko[pos2].objType==PPLOBJ_STR)) usingRowCol=DATAFILE_ROW; } // Read list of using items into an array { int hadNonNullUsingItem = 0; int pos = ptab[PARSE_INDEX_using_list] + stkbase; const int o = ptab[PARSE_INDEX_using_item]; if (o>0) while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nusing>=USING_ITEMS_MAX) { *status=1; sprintf(errtext, "Too many using items; maximum of %d are allowed.", USING_ITEMS_MAX); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } if (stk[pos+o].objType == PPLOBJ_EXP) { usingExprs[Nusing] = (pplExpr *)stk[pos+o].auxil; hadNonNullUsingItem = 1; } else usingExprs[Nusing] = NULL; Nusing++; } if ((!hadNonNullUsingItem) && (Nusing==1)) Nusing=0; // If we've only had one using item, and it was blank, this is a parser abberation if ((Nusing==0)&&(Ncols>=0)) // If no using items were specified, generate an auto-generated list { autoUsingList=1; if (ppldata_autoUsingList(c, usingExprs, Ncols, errtext)) return; Nusing=Ncols; } else if ((Nusing==1)&&(Ncols==2)) // Need two columns; one supplied { int end=0,ep=0,es=0; char ascii[10]; pplExpr *exptmp=NULL; usingExprs[1] = usingExprs[0]; sprintf(ascii, "%d", 0); ppl_expCompile(c,pl->srcLineN,pl->srcId,pl->srcFname,ascii,&end,0,0,0,&exptmp,&ep,&es,errtext); if (es || c->errStat.status) { ppl_tbClear(c); *status=1; sprintf(errtext, "Out of memory (11)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } usingExprs[0] = pplExpr_tmpcpy(exptmp); pplExpr_free(exptmp); if (usingExprs[0]==NULL) { *status=1; sprintf(errtext, "Out of memory (12)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } Nusing=2; } } // Print using items to log file if (DEBUG) { int logi=0 , logj; sprintf(c->errcontext.tempErrStr+logi,"Using "); logi+=strlen(c->errcontext.tempErrStr+logi); for (logj=0; logjerrcontext.tempErrStr[logi++]=':'; sprintf(c->errcontext.tempErrStr+logi,"%s",usingExprs[logj]->ascii); } ppl_log(&c->errcontext, NULL); } // Check that number of using items matches number required if ((Ncols<1)&&(Nusing>0)) Ncols=Nusing; // If number of columns is specified as -1, any number of columns will do if ((Ncols>=0)&&(Nusing != Ncols)) { *status=1; sprintf(errtext, "The supplied using ... clause contains the wrong number of items. We need %d columns of data, but %d have been supplied.", Ncols, Nusing); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } // Test for expression list or filename { const int pos1 = ptab[PARSE_INDEX_expression_list] + stkbase; const int pos2 = ptab[PARSE_INDEX_filename] + stkbase; if ((pos1>0)&&(stk[pos1].objType==PPLOBJ_NUM)) // we have been passed a list of expressions { const int stkLevelOld = c->stackPtr; int pos = pos1; int Nexprs=0, i; pplExpr **exprList; pplObj *first; while (stk[pos].objType == PPLOBJ_NUM) // count number of expressions { pos = (int)round(stk[pos].real); if (pos<=0) break; Nexprs++; } if (Nexprs < 1) { *status=1; sprintf(errtext, "Fewer than one expression was supplied to evaluate."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } exprList = (pplExpr **)ppl_memAlloc(Nexprs*sizeof(pplExpr *)); if (exprList==NULL) { *status=1; sprintf(errtext, "Out of memory (13)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } for (i=0, pos=pos1; stk[pos].objType==PPLOBJ_NUM; i++) { pos = (int)round(stk[pos].real); if (pos<=0) break; exprList[i] = (pplExpr *)stk[pos+ptab[PARSE_INDEX_expression]].auxil; } first = ppl_expEval(c, exprList[0], &i, 0, iterDepth); if ((!c->errStat.status) && (first->objType==PPLOBJ_STR) && (Nexprs==1) && (rasterY==NULL)) // If we have a single expression that evaluates to a string, it's a filename { long file_linenumber=pl->srcLineN; int tmp=0, *discontinuity=&tmp; char *filename=pl->srcFname; // Dummy stuff needed for STACK_CLEAN char *datafile = (char *)first->auxil; ppldata_fromFile(c, out, datafile, wildcardMatchNumber, filenameOut, dataSpool, indexNo, usingExprs, autoUsingList, Ncols, NusingObjs, labelExpr, selectExpr, sortBy, usingRowCol, everyList, continuity, persistent, status, errtext, errCount, iterDepth); STACK_CLEAN; } else if ((!c->errStat.status) && (first->objType==PPLOBJ_VEC) && (rasterY!=NULL)) { const int stkLevelOld = c->stackPtr; pplObj *vecs; gsl_vector *v = ((pplVector *)first->auxil)->v; const int l = v->size; int j; vecs = (pplObj *)ppl_memAlloc(Nexprs*sizeof(pplObj)); if (vecs==NULL) { *status=1; sprintf(errtext, "Out of memory (14)."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } for (i=0; isrcLineN; int tmp=0, *discontinuity=&tmp; char *filename=pl->srcFname; // Dummy stuff needed for STACK_CLEAN int l2; pplObj *obj = ppl_expEval(c, exprList[i], &j, 0, iterDepth); if (c->errStat.status) { *status=1; sprintf(errtext, "Could not evaluate vector expressions."); for (j=0; jerrcontext, errtext); return; } if (obj->objType!=PPLOBJ_VEC) { *status=1; sprintf(errtext, "Vector data supplied to other columns, but columns %d evaluated to an object of type <%s>.", i+1, pplObjTypeNames[obj->objType]); for (j=0; jerrcontext, errtext); return; } l2 = ((pplVector *)first->auxil)->v->size; if (l!=l2) { *status=1; sprintf(errtext, "Data supplied as a list of vectors, but they have varying lengths, including %d (vector %d) and %d (vector %d).", l, 1, l2, i+1); for (j=0; jerrcontext, errtext); return; } pplObjCpy(vecs+i,obj,0,0,1); vecs[i].refCount = 1; STACK_CLEAN; } if (wildcardMatchNumber<=0) ppldata_fromVectors(c, out, vecs, Nexprs, usingExprs, autoUsingList, Ncols, NusingObjs, labelExpr, selectExpr, sortBy, continuity, status, errtext, errCount, iterDepth); for (i=0; isrcLineN; int tmp=0, *discontinuity=&tmp; char *filename=pl->srcFname; // Dummy stuff needed for STACK_CLEAN double *rX = rasterX; double *rY = rasterY; int rXl= rasterXlen; int rYl= rasterYlen; pplObj *uX = &unitX; pplObj *uY = &unitY; STACK_CLEAN; ppl_tbClear(c); // See if this set of functions want a special raster if ((!sampleGrid)&&(!spacingSet)) { ppldata_fromFuncs_checkSpecialRaster(c, exprList, Nexprs, parametric?"t":"x", (parametric || XminSet) ? &rasterXmin : NULL, (parametric || XmaxSet) ? &rasterXmax : NULL, uX, &rX, &rXl); } if (wildcardMatchNumber<=0) ppldata_fromFuncs(c, out, exprList, Nexprs, rX, rXl, parametric, uX, rY, rYl, uY, usingExprs, autoUsingList, Ncols, NusingObjs, labelExpr, selectExpr, sortBy, continuity, status, errtext, errCount, iterDepth); } } else if ((pos2>0)&&(stk[pos2].objType==PPLOBJ_STR)) // we have been passed a filename { char *filename = (char *)stk[pos2].auxil; ppldata_fromFile(c, out, filename, wildcardMatchNumber, filenameOut, dataSpool, indexNo, usingExprs, autoUsingList, Ncols, NusingObjs, labelExpr, selectExpr, sortBy, usingRowCol, everyList, continuity, persistent, status, errtext, errCount, iterDepth); } else { *status=1; sprintf(errtext, "Could not find any expressions to evaluate."); if (DEBUG) ppl_log(&c->errcontext, errtext); return; } } return; } pyxplot-0.9.2/src/help.xml0000664000175000017500000043112712026340554014075 0ustar dcf21dcf21 Welcome to the Pyxplot help system. The 'help' command provides an easily-navigable source of information which is supplementary to that in the Users' Guide. To obtain information on any particular topic, type 'help' followed by the name of the topic. For example, help plot provides information on Pyxplot's plot command. Some topics have subtopics, this being one example; these are listed at the end of each help page. To view them, add further words to the end of your help request, as in the example: help set title Information is arranged with general information about Pyxplot under the heading 'about' and information about the format that input datafiles should take under the heading 'datafile'. Information about each of Pyxplot's commands can be found under the name of that command. Other categories, listed below, are self-explanatory. To exit any help page, press the 'Q' key. Dominic Ford \\ Ross Church \\ email: \labcoders@pyxplot.org.uk\rab The inspiration for Pyxplot came from two sources, to which Pyxplot owes a considerable historical debt. Pyxplot's interface was heavily motivated by gnuplot's simple and intuitive interface, which was devised by Thomas Williams and Colin Kelley and has more recently been developed by many others. Pyxplot's graphical output engine was heavily motivated by the PyX graphics library for Python, originally written by Joerg Lehmann and Andre Wobst and more recently developed by a larger team. Versions of Pyxplot prior to 0.8.0 used PyX to produce their graphical output, and though version 0.8.x uses its own graphics engine, it continues to bear many similarities to PyX. Several other people have made very substantial contributions to Pyxplot's development. Matthew Smith provided extensive advice on many mathematical matters which arose during its development, provided C implementations of the Airy functions and the Riemann zeta function for general complex inputs, and suggested many mathematical functions which ought to be made available. Dave Ansell provided many good ideas which have helped to shape Pyxplot's interface. The writing of Pyxplot's PostScript engine was substantially eased thanks to the help of Michael Rutter, who happily shared his code and past experiences with us; the implementation of the image command is substantially his work. We are also very grateful to our team of alpha testers, without whose work this release of Pyxplot would doubtless contain many more bugs than it does: especial thanks go to Rachel Holdforth and Stuart Prescott. Of course, the authors remain solely responsible for any bugs which remain. Finally, we would like to think all of the users who have got in touch with us by email since Pyxplot was first released on the web in 2006. Your feedback and suggestions have been gratefully received. This is Pyxplot version $VERSION. Pyxplot expects its input datafiles to be in plain text format, with columns of data separated either by whitespace or by commas. This means that Pyxplot is compatible both with the format of datafiles read by gnuplot and with the Comma Separated Values (CSV) format which many spreadsheets are able to produce. The subsections below provide some details of the modifiers that can follow the plot command when working with datafiles to select which parts of the file should be used. They also apply equally to other commands -- for example, the interpolate, fit, fft and tabulate commands -- which also take input from datafiles. The using specifier allows one to choose which columns of a datafile to use. The example plot 'data.dat' using 2:5 with points would plot data from the file 'data.dat', drawing the horizontal positions of each datapoint from the second column of the datafile, and the vertical positions from the fifth. Algebraic expressions may also be used in place of column numbers, as in the example: plot 'data.dat' using (3+$1+$2):(2+$3) In such expressions, column numbers are prefixed by dollar signs to distinguish them from numerical constants. The example above would plot the sum of the values in the first two columns of the datafile, plus three, on the horizontal axis, against two plus the value in the third column on the vertical axis. The column numbers in such expressions can also be replaced by algebraic expressions, and so $2 can also be written as $(2) or $(1+1). In the following example, the datapoints are all placed on the vertical line x=3 -- the brackets around the 3 distinguish it as a numerical constant rather than a column number -- meanwhile their vertical positions are drawn from the value of some column n in the datafile, where the value of n is itself read from the second column of the datafile: plot 'data.dat' using (3):$($2) The rows modifier causes datafiles to be considered as sets of rows rather than columns. For example: plot 'data' using rows 2:5 with points would draw the horizontal positions of each datapoint from the second row of the datafile, and the vertical positions from the fourth. When Pyxplot reads a datafile, it looks for any blank lines in the file. It divides the datafile up into "data blocks", each being separated from the next by a single blank line. The first datablock is numbered 0, the next 1, and so on. When two or more blank lines are found together, the datafile is divided up into "index blocks". The first index block is numbered 0, the next 1, and so on. Each index block may be made up of a series of data blocks. To clarify this, a labelled example datafile is shown below: |#0.0###0.0#######Start#of#index#0,#data#block#0. \\ |#1.0###1.0###### \\ |#2.0###2.0###### \\ |#3.0###3.0###### \\ |#################A#single#blank#line#marks#the#start#of#a#new#data#block. \\ |#0.0###5.0#######Start#of#index#0,#data#block#1. \\ |#1.0###4.0###### \\ |#2.0###2.0###### \\ |#################A#double#blank#line#marks#the#start#of#a#new#index. \\ |#################... \\ |#0.0###1.0#######Start#of#index#1,#data#block#0. \\ |#1.0###1.0###### \\ |#################A#single#blank#line#marks#the#start#of#a#new#data#block. \\ |#0.0###5.0#######Start#of#index#1,#data#block#1. \\ |#################...etc... The every modifier chooses which lines and data blocks of a datafile to take data from; it takes up to six values, separated by colons: plot 'datafile' every a:b:c:d:e:f where the letters have the following meanings: a Plot data only from every a th line in datafile. b Plot only data from every b th block within each index block. c Plot only from line c onwards within each block. d Plot only data from block d onwards within each index block. e Plot only up to the e th line within each block. f Plot only up to the f th block within each index block. Any or all of these values can be omitted, and so the following would both be valid statements: plot 'data.dat' index 1 every 2:3 \\ plot 'data.dat' index 1 every ::3 The first would plot only every other datapoint from every third data block; the second from the third line onwards within each data block. To select which index blocks to take data from, see the "index" modifier. When Pyxplot reads a datafile, it looks for any blank lines in the file. It divides the datafile up into "data blocks", each being separated from the next by a single blank line. The first datablock is numbered 0, the next 1, and so on. When two or more blank lines are found together, the datafile is divided up into "index blocks". The first index block is numbered 0, the next 1, and so on. Each index block may be made up of a series of data blocks. The index specifier selects an index block from a data set to plot data from. For example: plot 'data' index 1 will plot the data from the second index block only. A negative block number will achieve the default option of plotting from all index blocks. For more information on the divisions of datafiles see the "every" modifier. This version of Pyxplot was released on $DATE. Pyxplot is distributed under the Gnu General Public License, Version 2. A copy of this can be downloaded from: http://www.gnu.org/copyleft/gpl.html . ?#[#\labtopic\rab#{#\labsub-topic\rab#}#]\\ The ? symbol is a shortcut to the help command. !#\labshell#command\rab\\...#`\labshell#command\rab`#...\\ Shell commands can be executed within Pyxplot by prefixing them with pling (!) characters, as in the example: !mkdir#foo\\ As an alternative, back-quotes (`) can be used to substitute the output of a shell command into a Pyxplot command, as in the example: set#xlabel#`echo#"'"#;#ls#;#echo#"'"`\\ Note that back-quotes cannot be used inside quote characters, and so the following would not work: set#xlabel#'`ls`'\\ arc#[#item#\labid\rab#]#[at]#\labvector\rab#radius#\lablength\rab\\####from#\labangle\rab#to#\labangle\rab#[#with#{#\laboption\rab#}#]\\ Arcs (curves with constant radius of curvature, that is, segments of circles) may be drawn on multiplot canvases using the arc command. The at modifier specifies the coordinates of the center of curvature, from which all points on the arc are at the distance given following the radius modifier. The angles start and finish, measured clockwise from the vertical, control where the arc begins and ends. For example, the command arc#at#0,0#radius#2#from#90#to#270\\ would draw a semi-circle beneath the line x=0, centered on the origin with radius 2 cm. The usual style modifiers for lines may be passed after the keyword with; if the fillcolor modifier is specified then the arc will be filled to form a pie-chart slice. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. arrow#[#item#\labid\rab#]#[from]#\labvector\rab#to#\labvector\rab\\##################[#with#{#\laboption\rab#}#]\\ Arrows may be drawn on multiplot canvases using the arrow command. The style of the arrows produced may be specified by following the with modifier by one of the style keywords nohead, head (default) or twohead. In addition, keywords such as color, linewidth and linetype have the same syntax and meaning following the keyword with as in the plot command. The following example would draw a bidirectional blue arrow: arrow#from#x1,y1#to#x2,y2#with#twohead#linetype#2#color#blue\\ The arrow command has a twin, the line command, which has the same syntax, but uses the default arrow style of nohead, producing short line segments. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. assert#(#\labexpression\rab#|#version#(#\rab=#|#\lab#)#\labversion\rab#)\\#######[#\laberror#message\rab#]\\ The assert command can be used to assert that a logical expression, such as x\rab0, is true. An error is reported if the expression is false, and optionally a string can be supplied to provide a more informative error message to the user: assert#x\rab0\\assert#y\lab0#"y#must#be#less#than#zero."\\ The assert command can also be used to test the version number of Pyxplot. It is possible to test either that the version is newer than or equal to a specific version, using the \rab= operator, or that it is older than a specific version, using the \lab operator, as demonstrated in the following examples: assert#version#\rab=#0.8.2\\assert#version#\lab##0.8##"This#script#is#designed#for#Pyxplot#0.7"\\ box#[#item#\labid\rab#]#at#\labvector\rab#width#\lablength\rab#height#\lablength\rab\\#########[#rotate#\labangle\rab#]#[#with#{#\laboption\rab#}#]\\\\box#[#item#\labid\rab#]#from#\labvector\rab#to#\labvector\rab\\#########[#rotate#\labangle\rab#]#[#with#{#\laboption\rab#}#]\\ The box command is used to draw and fill rectangular boxes on multiplot canvases. The position of each box may be specified in one of two ways. In the first, the coordinates of one corner of the box are specified, along with its width and height. If both the width and the height are positive then the coordinates are taken to be those of the bottom left-hand corner of the box; other corners may be specified if the supplied width and/or height are negative. If a rotation angle is specified then the box is rotated about the specified corner. The with modifier allows the style of the box to be specified using similar options to those accepted by the plot command. The second syntax allows two pairs of coordinates to be specified. Pyxplot will then draw a rectangular box with opposing corners at the specified locations. If an angle is specified the box will be rotated about its center. Hence the following two commands both draw a square box centered on the origin: box#from#-1,#-1#to#1,1\\box#at#1,#-1#width#-2#height#2\\ All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. break#[#\labloopname\rab#]\\ The break command terminates execution of do, while, for and foreach loops in an analogous manner to the break statement in the C programming language. Execution resumes at the statement following the end of the loop. For example, the following loop would only print the numbers1 and2: for#i#=#1#to#10\\#{\\##print#i\\##if#(i==2)\\###{\\####break\\###}\\#}\\ If several loops are nested, the break statement only acts on the innermost loop. If the break statement is encountered outside of any loop structure, an error results. Optionally, the for, foreach, do and while commands may be supplied with a name for the loop, prefixed by the word loopname, as in the examples: for#i=0#to#4#loopname#iloop\\\\foreach#i#in#"*.dat"#loopname#DatafileLoop\\ When loops are given such names, the break statement may be followed by the name of the loop whose iteration is to be broken, allowing it to act upon loops other than the innermost one. See also the continue command. call#\labexpression\rab\\ The call command evaluates a function or subroutine call, and discards the result. Whereas entering f(x) on the commandline alone will print the result of the function call, call f(x) quietly discards the function evaluation. cd#\labdirectory\rab\\ Pyxplot's cd command is very similar to the shell cd command; it changes the current working directory. The following example would enter the subdirectory foo: cd#foo\\ circle#[#item#\labid\rab#]#[at]#\labvector\rab#radius#\lablength\rab\\#######[#with#{#\laboption\rab#}#]\\ The circle command is used to draw circles on multiplot canvases. The coordinates of the circle's center and its radius are specified. The with modifier allows the style of the circle to be specified using similar options to those accepted by the plot command. The example circle#at#2,2#radius#1#with#color#red#fillcolor#blue\\ would draw a red circle of unit radius filled in blue, centered 2 cm above and to the right of the origin. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. clear\\ In multiplot mode, the clear command removes all plots, arrows and text objects from the working multiplot canvas. Outside of multiplot mode, it is not especially useful; it removes the current plot to leave a blank canvas. The clear command should not be followed by any parameters. continue#[#\labloopname\rab#]\\ The continue command terminates execution of the current iteration of for, foreach, do and while loops in an analogous manner to the continue statement in the C programming language. Execution resumes at the first statement of the next iteration of the loop, or at the first statement following the end of the loop in the case of the last iteration of the loop. For example, the following script will not print the number2: for#i#=#0#to#5\\#{\\##if#(i==2)\\###{\\####continue\\###}\\##print#i\\#}\\ If several loops are nested, the continue statement only acts on the innermost loop. If the continue statement is encountered outside of any loop structure, an error results. Optionally, the for, foreach, do and while statements may be supplied with a name for the loop, prefixed by the word loopname, as in the examples: for#i=0#to#4#loopname#iloop\\\\foreach#i#in#"*.dat"#loopname#DatafileLoop\\ When loops are given such names, the continue statement may be followed by the name of the loop whose iteration is to be broken, allowing it to act upon loops other than the innermost one. See also the break command. delete#{#\labitem#number\rab#}\\ The delete command removes vector graphics objects such as plots, arrows or text items from the current multiplot canvas. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. The items to be deleted should be identified using a comma-separated list of their identification numbers. The example delete#1,2,3\\ would remove item numbers1,2 and3. Having been deleted, multiplot items can be restored using the undelete command. do#[#loopname#\labloopname\rab#]\\#\labcode\rab\\while#\labcondition\rab\\ The do command executes a block of commands repeatedly, checking the condition given in the while clause at the end of each iteration. If the condition is true then the loop executes again. This is similar to a while loop, except that the contents of a do loop are always executed at least once. The following example prints the numbers1, 2 and3: i=1\\do\\#{\\##print#i\\##i#=#i#+#1\\#}#while#(i#\lab#4)\\ Note that there must always be a newline following the opening brace after the do command, and the while clause must always be on the same line as the closing brace. Ellipses may be drawn on multiplot canvases using the ellipse command. The shape of the ellipse may be specified in many different ways, by specifying [(i)] None the position of two corners of the smallest rectangle which can enclose the ellipse when its major axis is horizontal, together with an optional counter-clockwise rotation angle, applied about the center of the ellipse. For example: ellipse#from#0,0#to#4,1#rot#70\\ \\ None the position of both the center and one of the foci of the ellipse, together with any one of the following additional pieces of information: the ellipse's major axis length, its semi-major axis length, its minor axis length, its semi-minor axis length, its eccentricity, its latus rectum, or its semi-latus rectum. For example: ellipse#focus#0,0#center#2,2#majoraxis#4\\ellipse#focus#0,0#center#2,2#minoraxis#4\\ellipse#focus#0,0#center#2,2#ecc#0.5\\ellipse#focus#0,0#center#2,2#LatusRectum#6\\ellipse#focus#0,0#center#2,2#slr#3\\ \\ None the position of either the center or one of the foci of the ellipse, together with any two of the following additional pieces of information: the ellipse's major axis length, its semi-major axis length, its minor axis length, its semi-minor axis length, its eccentricity, its latus rectum, or its semi-latus rectum. An optional counter-clockwise rotation angle may also be specified, applied about either the center or one of the foci of the ellipse, whichever is specified. If no rotation angle is given, then the major axis of the ellipse is horizontal. For example: ellipse#center#0,0#majoraxis#4#minoraxis#4\\ \\ Optionally, an arc of an ellipse may be drawn by adding the following modified: arc#from#\labangle\rab#to#\labangle\rab\\ The line type, line width, and color of line with which the outlines of ellipses are drawn may be specified after the keyword with, as in the box and circle commands above. Likewise, ellipses may be filled in the same manner. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. The else statement is described in the entry for the if statement, of which it forms part. eps#[#item#\labid\rab#]#\labfilename\rab#[#at#\labvector\rab#]#[rotate#\labangle\rab]\\###########################[width#\lablength\rab]#[height#\lablength\rab]\\########################################[#clip#]#[#calcbbox#]\\ The eps command allows Encapsulated PostScript (EPS) images to be inserted onto multiplot canvases. The at modifier can be used to specify where the image should be placed on the vector graphics canvas; if it is not, then the image is placed at the origin. The settings texthalign and textvalign determined how the image is aligned relatively to this reference point - for example, whether its bottom left corner or its center is placed at the reference point. The rotate modifier can be used to rotate the image by any angle, measured in degrees counter-clockwise. The width or height modifiers can be used to specify the width or height with which the image should be rendered; both should be specified in centimeters. If neither is specified then the image will be rendered with the native dimensions specified within the PostScript. The eps command is often useful in multiplot mode, allowing PostScript images to be combined with plots, text labels, etc. The clip modifier causes Pyxplot to clip an eps image to its stated bounding box. The calcbbox modifier causes Pyxplot to ignore the bounding box stated in the eps file and calculate its own when working out how to scale the image to the specified width and height. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. exec#\labcommand\rab\\ The exec command can be used to execute Pyxplot commands contained within string variables, as in the following example: terminal="eps"\\exec#"set#terminal#%s"%(terminal)\\ It can also be used to write obfuscated Pyxplot scripts, and its use should be minimized wherever possible. exit\\ The exit command can be used to quit Pyxplot. If multiple command files, or a mixture of command files and interactive sessions, were specified on Pyxplot's command line, then Pyxplot moves onto the next command-line item after receiving the exit command. Pyxplot may also be quit be pressing CTRL-D or using the quit command. In interactive mode, CTRL-C terminates the current command, if one is running. When running a script, CTRL-C terminates execution of the script. fft#{#\labrange\rab#}#\labfunction#name\rab()\\####of#(#\labfilename\rab#|#\labfunction#name\rab()#)\\####[#using#{#\labexpression\rab#}#]\\\\ifft#{#\labrange\rab#}#\labfunction#name\rab()\\####of#(#\labfilename\rab#|#\labfunction#name\rab()#)\\####[#using#{#\labexpression\rab#}#]\\ The fft command calculates Fourier transforms of data files or functions. Transforms can be performed on datasets with arbitrary numbers of dimensions. To transform an algebraic expression with ndegrees of freedom, it must be wrapped in a function of the form f(i,i,...,i). To transform an n-dimensional dataset stored in a data file, the samples must be arranged on a regular linearly-spaced grid and stored in row-major order. For each dimension of the transform, a range specification must be provided to the fft command in the form [#\labminimum\rab#:#\labmaximum\rab#:#\labstep\rab#]\\ When data from a data file is being transformed, the specified range(s) must precisely match those of the samples read from the file; the first ncolumns of data should contain the values of the nreal-space coordinates, and the n+1th column should contain the data to be transformed. After the range(s), a function name should be provided for the output transform: a function of narguments with this name will be generated to represent the transformed data. Note that this function is in general complex - i.e. it has a non-zero imaginary component. Complex numerics can be enabled using the set numerics complex command and the fft command is of little use without doing so. The using, index, every and select modifiers can be used to specify how data will be sampled from the input function or data file in an analogous manner to how they are used in the plot command. The ifft command calculates inverse Fourier transforms; it has the same syntax as the fft command. fit#[#{#\labrange\rab#}#]#\labfunction#name\rab()#[#withouterrors#]\\####(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\####[#index#\labvalue\rab#]#[#using#{#\labexpression\rab#}#]\\####via#{#\labvariable\rab#}\\ The fit command can be used to fit arbitrary functional forms to data points read from files. It can be used to produce best-fit lines for datasets or to determine gradients and other mathematical properties of data by looking at the parameters associated with the best-fitting functional form. The following simple example fits a straight line to data in a file called data.dat: f(x)#=#a*x+b\\fit#f()#'data.dat'#index#1#using#2:3#via#a,b\\ The first line specifies the functional form which is to be used. The coefficients within this function, a and b, which are to be varied during the fitting process are listed after the keyword via in the fit command. The modifiers index, every, select and using have the same meanings in the fit command as in the plot command. When fitting a function of n variables, at least n+1 columns (or rows - see Section 3.9.1 of the Users' Guide) of data must be specified after the using modifier. By default, the first n+1 columns are used. These correspond to the values of each of the n arguments to the function, plus finally the value which the output from the function is aiming to match. If an additional column is specified, then this is taken to contain the standard error in the value that the output from the function is aiming to match, and can be used to weight the data points which are being used to constrain the fit. As the fit command works, it displays statistics including the best-fit values of each of the fitting parameters, the uncertainties in each of them, and the covariance matrix. These can be useful for analysing the security of the fit achieved, but calculating the uncertainties in the best-fit parameters and the covariance matrix can be time consuming, especially when many parameters are being fitted simultaneously. The optional keyword withouterrors can be included immediately before the filename of the data file to be fitted to substantially speed up cases where this information is not required. By default, the starting values for each of the fitting parameters is 1.0. However, if the variables to be used in the fitting process are already set before the fit command is called, these initial values are used instead. For example, the following would use the initial values {a=100,b=50}: f(x)#=#a*x+b\\a#=#100\\b#=#50\\fit#f()#'data.dat'#index#1#using#2:3#via#a,b\\ More details can be found in Section 5.6 of the Users' Guide. for#\labvariable\rab#=#\labstart\rab#to#\labend\rab#[step#\labstep\rab]\\##########################[loopname#\labloopname\rab]\\##\labcode\rab\\\\for#(\labinitialise\rab;#\labcriterion\rab;#\labstep\rab)\\##\labcode\rab\\ The for command executes a set of commands repeatedly. Pyxplot allows for loops to follow either the syntax of the BASIC programming language, or the C syntax. In the BASIC variant, a specified variable takes a different value on each iteration. The variable takes the value start on the first iteration, and increases by a fixed value step on each iteration; step may be negative if end \lab start. If step is not specified then a value of unity is assumed. The loop terminates when the variable exceeds end. The following example prints the squares of the first five natural numbers: for#i#=#1#to#5\\#{\\##print#i**2\\#}\\ In the C variant, three expressions are provided, which are evaluated (a) when the loop initialises, (b) as a boolean test of whether the loop should continue iterating, and (c) on each loop to increment/decrement variables as required. For example: for#(i=1,j=1;#i\lab=256;#i*=2,j++)#{#print#"%3d#%3d"%(j,i);#}\\ foreach#\labvariable\rab#in#(#\labfilename#wildcard\rab#|\\########################\lablist\rab#)\\######################[#loopname#\labloopname\rab#]\\##\labcode\rab\\ The foreach command can be used to run a block of commands repeatedly, once for each item in a list. The list of items can be specified in one of two ways. In the first case, a set of filenames or filename wildcards is supplied, and the foreach loop iterates once for each supplied filename, with a string variable set to each filename in succession. For example, the following loop would plot the data in the set of files whose names end with .dat: plot#####\##Create#blank#plot\\foreach#file#in#*.dat\\#{\\##replot#file#with#lines\\#}\\ The second form of the command takes a list of string or numerical values provided explicitly by the user, and the foreach loop iterates once for each value, with a variable set to each value in succession. For example, the following script would plot normal distributions of three different widths: plot#####\##Create#blank#plot\\foreach#sigma#in#(1,#2,#3)\\#{\\##replot#1/sigma*exp(-x**2/(2*sigma**2))\\#}\\ foreach#{#\labvariable\rab#}#in#[#{#\labrange\rab#}#]\\####(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\####[#every#{#\labexpression\rab#}#]\\####[#index#\labvalue\rab#]#[#select#\labexpression\rab#]\\####[#using#{#\labexpression\rab#}#]\\##\labcode\rab\\ The foreach datum command executes a series of commands for each data pointread from a data fileor function. It takes a similar set of modifiers to the plot command; the list of variables to be read from the supplied data on each iteration should be comma separated. global#{#\labvariable#name\rab#}\\ The global command command may be used within subroutines, which have their own private variable namespaces, to specify that the named variables should refer to the global namespace. If multiple variables are specified, their names should be comma separated. help#[#\labtopic\rab#{#\labsub-topic\rab#}#]\\ The help command provides an hierarchical source of information which is supplementary to this Users' Guide. To obtain information on any particular topic, type help followed by the name of the topic, as in the following example help#commands\\ which provides information on Pyxplot's commands. Some topics have sub-topics; these are listed at the end of each help page. To view them, add further words to the end of the help request, as in the example: help#commands#help\\ Information is arranged with general information about Pyxplot under the heading about and information about Pyxplot's commands under commands. Information about the format that input data files should take can be found under datafile. Other categories are self-explanatory. To exit any help page, press the q key. histogram#[#\labrange\rab#]#\labfunction#name\rab()\\#####(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\#####[#every#{#\labexpression\rab#}#]\\#####[#index#\labvalue\rab#]\\#####[#select#\labexpression\rab#]\\#####[#using#{#\labexpression\rab#}#]\\#####(#[#binwidth#\labvalue\rab#]#[#binorigin#\labvalue\rab#]#|\\#######[#bins#(x1,#x2,#...)#]#)\\ The histogram command takes a single column of data from a file and produces a function that represents the frequency distribution of the supplied data values. The output function consists of a series of discrete intervals which we term bins. Within each interval the output function has a constant value, determined such that the area under each interval - i.e. the integral of the function over each interval - is equal to the number of datapoints found within that interval. The following simple example histogram#f()#'input.dat'\\ produces a frequency distribution of the data values found in the first column of the file input.dat, which it stores in the function f(x). The value of this function at any given point is equal to the number of items in the bin at that point, divided by the width of the bins used. If the input datapoints are not dimensionless then the output frequency distribution adopts appropriate units, thus a histogram of data with units of length has units of one over length. The number and arrangement of bins used by the histogram command can be controlled by means of various modifiers. The binwidth modifier sets the width of the bins used. The binorigin modifier controls where their boundaries lie; the histogram command selects a system of bins which, if extended to infinity in both directions, would put a bin boundary at the value specified in the binorigin modifier. Thus, if binorigin 0.1 were specified, together with a bin width of20, bin boundaries might lie at20.1, 40.1, 60.1, and so on. Alternatively global defaults for the bin width and the bin origin can be specified using the set binwidth and set binorigin commands respectively. The example histogram#h()#'input.dat'#binorigin#0.5#binwidth#2\\ would bin data into bins between 0.5 and 2.5, between 2.5 and 4.5, and so forth. Alternatively the set of bins to be used can be controlled more precisely using the bins modifier, which allows an arbitrary set of bins to be specified. The example histogram#g()#'input.dat'#bins#(1,#2,#4)\\ would bin the data into two bins, x=1to2 and x=2to4. A range can be supplied immediately following the histogram command, using the same syntax as in the plot and fit commands; if such a range is supplied, only points that fall within that range will be binned. In the same way as in the plot command, the index, every, using and select modifiers can be used to specify which subsets of a data file should be used. Two points about the histogram command are worthy of note. First, although histograms are similar to bar charts, they are not the same. A bar chart conventionally has the height of each bar equal to the number of points that it represents, whereas a histogram is a continuous function in which the area underneath each interval is equal to the number of points within it. Thus, to produce a bar chart using the histogram command, the end result should be multiplied by the bin width used. Second, if the function produced by the histogram command is plotted using the plot command, samples are automatically taken not at evenly spaced intervals along the ordinate axis, but at the centers of each bin. If the boxes plot style is used, the box boundaries are be conveniently drawn to coincide with the bins into which the data were sorted. history#[#\labnumber#of#items\rab#]\\ The history command prints a list of the most recently executed commands on the terminal. The optional parameter, N, if supplied, causes only the latest N commands to be displayed. if#\labcriterion\rab#\labcode\rab\\{#else#if#\labcriterion\rab#\labcode\rab#}\\[#else################\labcode\rab#]\\ The if command allows conditional execution of blocks of commands. The code enclosed in braces following the if statement is executed if, and only if, the criterion is satisfied. An arbitrary number of subsequent else if statements can optionally follow the initial if statement; these have their own criteria for execution which are only considered if all of the previous criteria have tested false - i.e. if none of the previous command blocks have been executed. A final optional else statement can be provided; the block of commands which follows it are executed only if none of the preceding criteria have tested true. The following example illustrates a chain of else if clauses: if#(x==2)\\#{\\##print#"x#is#two!"\\#}#else#if#(x==3)#{\\##print#"x#is#three!"\\#}#else#if#(x\rab3)#{\\##print#"x#is#greater#than#three!"\\#}#else#{\\##x=2\\##print#"x#didn't#used#to#be#two,#but#it#is#now!"\\#}\\ ifft#{#\labrange\rab#}#\labfunction#name\rab()\\####of#(#\labfilename\rab#|#\labfunction#name\rab()#)\\####[using#{#\labexpression\rab#}#]\\ See fft. image#[#item#\labid\rab#]#\labfilename\rab#[#at#\labvector\rab#]\\#########[#rotate#\labangle\rab#]#[#width#\lablength\rab#]\\#########[#height#\lablength\rab]#[#smooth#]\\#########[#notransparent#]#[#transparent#rgb#\labr\rab:\labg\rab:\labb\rab#]\\ The image command allows graphical images to be inserted onto the current multiplot canvas from files on disk. Input graphical images may be in bitmap, gif, jpeg or png formats; the file type of each image is automatically detected. The at modifier can be used to specify where the image should be placed on the vector graphics canvas; if it is not, then the image is placed at the origin. The settings texthalign and textvalign determined how the image is aligned relatively to this reference point - for example, whether its bottom left corner or its center is placed at the reference point. The rotate modifier can be used to rotate images by any angle, measured in degrees counter-clockwise. The width or height modifiers can be used to specify the width or height with which images should be rendered; both should be specified in centimeters. If neither is specified then images are rendered with the native dimensions specified within the metadata present in the image file (if any). If both are specified, then the aspect ratio of the image is changed. The keyword smooth may optionally be supplied to cause the pixels of images to be interpolated[*]. Images which include transparency are supported. The optional keyword notransparent may be supplied to cause transparent regions to be filled with the image's default background color. Alternatively, an RGB color may be specified in the form rgb\labr\rab:\labg\rab:\labb\rab after the keyword transparent to cause that particular color to become transparent; the three components of the RGB color should be in the range0 to255. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. * -- Many commonly-used PostScript display engines, including Ghostscript, do not support this functionality. interpolate#(#akima#|#linear#|#loglinear#|#polynomial#|\\##############spline#|#stepwise#|\\##############2d#[#(#bmp_r#|#bmp_g#|#bmp_b#)#]#)\\############[#\labrange#specification\rab#]#\labfunction#name\rab()\\############\labfilename\rab\\############[#every#{#\labexpression\rab#}#]\\############[#index#\labvalue\rab#]\\############[#select#\labexpression\rab#]\\############[#using#{#\labexpression\rab#}#]\\ The interpolate command can be used to generate a special function within Pyxplot's mathematical environment which interpolates a set of data points supplied from a data file. Either one- or two-dimensional interpolation is possible. In the case of one-dimensional interpolation, various different types of interpolation are supported: linear interpolation, power law interpolation, polynomial interpolation, cubic spline interpolation and akima spline interpolation. Stepwise interpolation returns the value of the datapoint nearest to the requested point in argument space. The use of polynomial interpolation with large datasets is strongly discouraged, as polynomial fits tend to show severe oscillations between data points. Except in the case of stepwise interpolation, extrapolation is not permitted; if an attempt is made to evaluate an interpolated function beyond the limits of the data points which it interpolates, Pyxplot returns an error or value of not-a-number. In the case of two-dimensional interpolation, the type of interpolation to be used is set using the interpolate modifier to the set samples command, and may be changed at any time after the interpolation function has been created. The options available are nearest neighbor interpolation - which is the two-dimensional equivalent of stepwise interpolation, inverse square interpolation - which returns a weighted average of the supplied data points, using the inverse squares of their distances from the requested point in argument space as weights, and Monaghan Lattanzio interpolation, which uses the weighting function given in Monaghan & Lattanzio (1985). These are selected as follows: set#samples#interpolate#nearestNeighbor\\set#samples#interpolate#inverseSquare\\set#samples#interpolate#monaghanLattanzio\\ Finally, data can be imported from graphical images in bitmap (.bmp) format to produce a function of two arguments returning a value in the range0to1 which represents the data in one of the image's three color channels. The two arguments are the horizontal and vertical position within the bitmap image, as measured in pixels. A very common application of the interpolate command is to perform arithmetic functions such as addition or subtraction on datasets which are not sampled at the same abscissa values. The following example would plot the difference between two such datasets: interpolate#linear#f()#'data1.dat'\\interpolate#linear#g()#'data2.dat'\\plot#[min:max]#f(x)-g(x)\\ Note that it is advisable to supply a range to the plot command in this example: because the two datasets have been turned into continuous functions, the plot command has to guess a range over which to plot them unless one is explicitly supplied. The spline command is an alias for interpolate spline; the following two statements are equivalent: spline#f()#'data1.dat'\\interpolate#spline#f()#'data1.dat'\\ jpeg#[#item#\labid\rab#]#\labfilename\rab#[#at#\labvector\rab#]\\#########[#rotate#\labangle\rab#]#[#width#\lablength\rab#]\\#########[#height#\lablength\rab]#[#smooth#]\\#########[#notransparent#]#[#transparent#rgb#\labr\rab:\labg\rab:\labb\rab#]\\ See image. let#\labvariable#name\rab#=#\labvalue\rab\\ The let command sets the named variable to equal value. list\\ The list command returns a list of all of the items on the current multiplot canvas, giving their identification numbers and the commands used to produce them. The following is an example of the output produced: pyxplot\rab list \##ID###Command\\####1##plot#item#1#f(x)#using#columns\\####2##[deleted]#text#item#2#"Figure#1:#A#plot#of#f(x)"#at#0,0#rotate#0#gap#0\\####3##text#item#3#"Figure#1:#A#plot#of#$f(x)$"#at#0,0#rotate#0#gap#0\\ In this example, the user has plotted a graph of f(x) and added a caption to it. The ID column lists the reference numbers of each multiplot item. Item 1 has been deleted. load#\labfilename\rab\\ The load command executes a Pyxplot command script file, just as if its contents had been typed into the current terminal. For example: load#'foo'\\ would have the same effect as typing the contents of the file foo into the present terminal. Filename wildcard can be supplied, in which case all command files matching the given wildcard are executed, as in the example: load#'*.script'\\ local#{#\labvariable#name\rab#}\\ The global command command may be used within subroutines, which have their own private variable namespaces. It specifies that the named variables should, from now on, refer to the local namespace, even if the global command command has previously been used to reference the global namespace. If multiple variables are specified, their names should be comma separated. maximize#\labexpression\rab#via#{#\labvariable\rab#}\\ The maximize command can be used to find the maxima of algebraic expressions. A single algebraic expression should be supplied for optimisation, together with a comma-separated list of the variables with respect to which it should be optimised. In the following example, a maximum of the sinusoidal function cos(x) is sought: Note that this particular example doesn't work when complex arithmetic is enabled, since cos(x) diverges to infinity at x=infinityi. Various caveats apply the maximize command, as well as to the minimize and solve commands. All of these commands operate by searching numerically for optimal sets of input parameters to meet the criteria set by the user. As with all numerical algorithms, there is no guarantee that the locally optimum solutions returned are the globally optimum solutions. It is always advisable to double-check that the answers returned agree with common sense. These commands can often find solutions to equations when these solutions are either very large or very small, but they usually work best when the solution they are looking for is roughly of order unity. Pyxplot does have mechanisms which attempt to correct cases where the supplied initial guess turns out to be many orders of magnitude different from the true solution, but it cannot be guaranteed not to wildly overshoot and produce unexpected results in such cases. To reiterate, it is always advisable to double-check that the answers returned agree with common sense. minimize#\labexpression\rab#via#{#\labvariable\rab#}\\ The minimize command can be used to find the minima of algebraic expressions. A single algebraic expression should be supplied for optimisation, together with a comma-separated list of the variables with respect to which it should be optimised. In the following example, a minimum of the sinusoidal function cos(x) is sought: Note that this particular example doesn't work when complex arithmetic is enabled, since cos(x) diverges to -infinity at x=pi+infinityi. Various caveats apply the minimize command, as well as to the maximize and solve commands. All of these commands operate by searching numerically for optimal sets of input parameters to meet the criteria set by the user. As with all numerical algorithms, there is no guarantee that the locally optimum solutions returned are the globally optimum solutions. It is always advisable to double-check that the answers returned agree with common sense. These commands can often find solutions to equations when these solutions are either very large or very small, but they usually work best when the solution they are looking for is roughly of order unity. Pyxplot does have mechanisms which attempt to correct cases where the supplied initial guess turns out to be many orders of magnitude different from the true solution, but it cannot be guaranteed not to wildly overshoot and produce unexpected results in such cases. To reiterate, it is always advisable to double-check that the answers returned agree with common sense. move#\labitem#number\rab#to#\labvector\rab#[#rotate#\labangle\rab#]\\ The move command allows vector graphics objects to be moved around on the current multiplot canvas. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. The item to be moved should be specified using its identification number. The example move#23#to#8,8\\ would move multiplot item23 to position (8,8) centimeters. If this item were a plot, the end result would be the same as if the command set origin 8,8 had been executed before it had originally been plotted. plot#[#3d#]#[#item#\labid\rab#]#[#{#\labrange\rab#}#]\\#####(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\#####[#axes#\labaxes\rab]#[#every#{#\labexpression\rab#}#]\\#####[#index#\labvalue\rab]#[#select#\labexpression\rab#]\\#####[#label#\labstring#expression\rab#]\\#####[#title#\labstring\rab#]#[#using#{#\labexpression\rab#}#]\\#####[#with#{#\laboption\rab#}#]\\ The plot command is used to produce graphs. The following simple example would plot the sine function: plot#sin(x)\\ Ranges for the axes of a graph can be specified by placing them in square brackets before the name of the function to be plotted. An example of this syntax would be: plot#[-pi:pi]#sin(x)\\ which would plot the function sin(x) between -pi and pi. Data files may also be plotted as well as functions, in which case the filename of the data file to be plotted should be enclosed in either single or double quotation marks. An example of this syntax would be: plot#'data.dat'#with#points\\ which would plot data from the file data.dat. Section 3.8 of the Users' Guide provides further details of the format that input data files should take and how Pyxplot may be directed to plot only certain portions of data files. Multiple datasets can be plotted on a single graph by specifying them in a comma-separated list, as in the example: plot#sin(x)#with#color#blue,#cos(x)#with#linetype#2\\ If the 3d modifier is supplied to the plot command, then a three-dimensional plot is produced; many plot styles then take additional columns of data to signify the positions of datapoints along the z-axis. This is described further in Chapter 8 of the Users' Guide. The angle from which three-dimensional plots are viewed can be set using the set view command. The axes modifier may be used to specify which axes data should be plotted against when plots have multiple parallel axes - for example, if a plot has an x-axis along its lower edge and an x2-axis along its upper edge. The following example would plot data using the x2-axis as the ordinate axis and the y-axis as the abscissa axis: plot#sin(x)#axes#x2y1\\ It is also possible to use the axes modifier to specify that a vertical ordinate axis and a horizontal abscissa axis should be used; the following example would plot data using the y-axis as the ordinate axis and the x-axis as the abscissa axis: plot#sin(x)#axes#yx\\ By default, Pyxplot generates its own entry in the legend of a plot for each dataset plotted. This default behaviour can be overridden using the title modifier. The following example labels a dataset as `Dataset1': plot#sin(x)#title#'Dataset#1'\\ If a blank string, i.e. "", is supplied, then no entry is made in the plot's legend for that dataset. The same effect can be achieved using the notitle modifier. The with modifier controls the style in which data should be plotted. For example, the statement plot#"data.dat"#index#1#using#4:5#with#lines\\ specifies that data should be plotted using lines connecting each data pointto its neighbors. More generally, the with modifier can be followed by a range of settings which fine-tune the manner in which the data are displayed; for example, the statement plot#"data.dat"#with#lines#linewidth#2.0\\ would use twice the default width of line. The following is a complete list of all of Pyxplot's plot styles - i.e. all of the words which may be used in place of lines: arrows_head, arrows_nohead, arrows_twohead, boxes, colormap, contourmap, dots, filledRegion, fsteps, histeps, impulses, lines, linesPoints, lowerLimits, points, stars, steps, surface, upperLimits, wboxes, xErrorBars, xErrorRange, XYErrorBars, xyErrorRange, xyzErrorBars, XYZErrorRange, xzErrorBars, xzErrorRange, yErrorBars, yErrorRange, yErrorShaded, yzErrorBars, yzErrorRange, zErrorBars, zErrorRange. In addition, lp and pl are recognised as abbreviations for linespoints; errorbars is recognised as an abbreviation for yerrorbars; errorrange is recognised as an abbreviation for yerrorrange; and arrows_twoway is recognised as an alternative for arrows_twohead. As well as the names of these plot styles, the with modifier can also be followed by style modifiers such as linewidth which alter the exact appearance of various plot styles. A complete list of these is as follows: * color - used to select the color in which each dataset is to be plotted. It should be followed either by an integer, to set a color from the present palette (see Section 8.1.1 of the Users' Guide), by a recognised color name, or by an object of type color. This modifier may also be spelt colour. \\ * fillcolor - used to select the color in which each dataset is filled. The color may be specified using any of the styles listed for color. May also be spelt fillcolor. \\ * linetype - used to numerically select the type of line - for example, solid, dotted, dashed, etc. - which should be used in line-based plot styles. A complete list of Pyxplot's numbered line types can be found in Chapter 18 of the Users' Guide. May be abbreviated lt. \\ * linewidth - used to select the width of line which should be used in line-based plot styles, where unity represents the default width. May be abbreviated lw. \\ * pointlinewidth - used to select the width of line which should be used to stroke points in point-based plot styles, where unity represents the default width. May be abbreviated plw. \\ * pointsize - used to select the size of drawn points, where unity represents the default size. May be abbreviated ps. \\ * pointtype - used to numerically select the type of point - for example, crosses, circles, etc. - used by point-based plot styles. A complete list of Pyxplot's numbered point types can be found in Chapter 18 of the Users' Guide. May be abbreviated pt. \\ Any number of these modifiers may be placed sequentially after the keyword with, as in the following examples: plot#'datafile'#using#1:2#with#points#pointsize#2\\plot#'datafile'#using#1:2#with#lines#color#red#linewidth#2\\plot#'datafile'#using#1:2#with#lp#col#1#lw#2#ps#3\\ Where modifiers take numerical values, expressions of the form $2+1, similar to those supplied to the using modifier, may be used to indicate that each datapoint should be displayed in a different style or in a different color. The following example would plot a data file with points, drawing the position of each point from the first two columns of the supplied data file and the size of each point from the third column: plot#'datafile'#using#1:2#with#points#pointsize#$3\\ point#[#item#\labid\rab#]#[at]#\labvector\rab#[#label#\labstring\rab#]\\####################[#with#{#\laboption\rab#}#]\\ The point command allows a single point to be plotted on the current multiplot canvas independently of any graph. It is equivalent to plotting a data file containing a single datum and with invisible axes. If an optional label is specified then the text string provided is rendered next to the point. The with modifier allows the style of the point to be specified using similar options to those accepted by the plot command. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. print#{#\labexpression\rab#}\\ The print command displays a string or the value of a mathematical expression to the terminal. It is most often used to find the value of a variable, though it can also be used to produce formatted textual output from a Pyxplot script. For example, print#a\\ would print the value of the variable a, and print#"a#=#%s"%(a)\\ would produce the same result in the midst of formatted text. pwd\\ The pwd command prints the location of the current working directory. quit\\ The quit command can be used to exit Pyxplot. See exit for more details. rectangle#[#item#\labid\rab#]#at#\labvector\rab\\#########width#\lablength\rab#height#\lablength\rab\\#########[#rotate#\labangle\rab#]#[#with#{#\laboption\rab#}#]\\\\rectangle#[#item#\labid\rab#]#from#\labvector\rab#to#\labvector\rab\\#########[#rotate#\labangle\rab#]#[#with#{#\laboption\rab#}#]\\ See box. refresh\\ The refresh command produces an exact copy of the latest display. It can be useful, for example, after changing the terminal type, to produce a second copy of a plot in a different graphic format. It differs from the replot command in that it doesn't replot anything; use of the set command since the previous plot command has no effect on the output. replot#[#item#\labid\rab#]#...\\ The replot command has the same syntax as the plot command and is used to add more datasets to an existing plot, or to change its axis ranges. For example, having plotted one data file using the command plot#'datafile1.dat'\\ another can be plotted on the same axes using the command replot#'datafile2.dat'#using#1:3\\ or the ranges of the axes on the original plot can be changed using the command replot#[0:1][0:1]\\ The plot is also updated to reflect any changes to settings made using the set command. In multiplot mode, the replot command can likewise be used to modify the last plot added to the page. For example, the following would change the title of the latest plot to `foo', and add a plot of the function g(x) to it: set#title#'foo'\\replot#cos(x)\\ Additionally, in multiplot mode it is possible to modify any plot on the current multiplot canvas by adding an item modifier to the replot statement to specify which plot should be replotted. The following example would produce two plots, and then add an additional function to the first plot: set#multiplot\\plot#f(x)\\set#origin#10,0\\plot#g(x)\\replot#item#1#h(x)\\ If no item number is specified, then the replot command acts by default upon the most recent plot to have been added to the multiplot canvas. reset\\ The reset command reverts the values of all settings that have been changed with the set command back to their default values. It also clears the current multiplot canvas. save#\labfilename\rab\\ The save command saves a list of all of the commands which have been executed in the current interactive Pyxplot session into a file. The filename to be used for the output should be placed in quotes, as in the example: save#'foo'\\ would save a command history into the file named foo. set#\laboption\rab#\labvalue\rab\\ The set command is used to configure the values of a wide range of parameters within Pyxplot which control its behaviour and the style of the output which it produces. For example: set#pointsize#2\\ would set the size of points plotted by Pyxplot to be twice the default. In the majority of cases, the syntax follows that above: the set command should be followed by a keyword which specifies which parameter should be set, followed by the value to which that parameter should be set. Those parameters which work in an on/off fashion take a different syntax along the lines of: set key###|#Elephants Set option ON#\\ set nokey#|#Elephants Set option OFF More details of the effects of each individual parameter can be found in the subsections below, which forms a complete list of the recognised setting keywords. The reader should also see the show command, which can be used to display the current values of settings, and the unset command, which returns settings to their default values. Chapter 19 of the Users' Guide describes how commonly used settings can be saved into a configuration file. set#arrow#\labarrow#number\rab\\##from#[#\labsystem\rab#]#\labx\rab,#[#\labsystem\rab#]#\laby\rab,#[#[#\labsystem\rab#]#\labz\rab#]\\##to###[#\labsystem\rab#]#\labx\rab,#[#\labsystem\rab#]#\laby\rab,#[#[#\labsystem\rab#]#\labz\rab#]\\##[#with#{#\laboption\rab#}#]\\ where \labsystem\rab may take any of the values ( first | second | screen | graph | axis\labnumber\rab ) The set arrow command is used to add arrows to graphs. The example set#arrow#1#from#0,0#to#1,1\\ would draw an arrow between the points (0,0) and (1,1), as measured along the x and y-axes. The tag 1 immediately following the keyword arrow is an identification number and allows arrows to be subsequently removed using the unset arrow command. By default, the coordinates are specified relative to the first horizontal and vertical axes, but they can alternatively be specified any one of several of coordinate systems. The coordinate system to be used is specified as in the example: set#arrow#1#from#first#0,#second#0#to#axis3#1,#axis4#1\\ The name of the coordinate system to be used precedes the position value in that system. The coordinate system first, the default, measures the graph using the x- and y-axes. second uses the x2- and y2-axes. screen and graph both measure in centimeters from the origin of the graph. The syntax axis\labn\rab may also be used, to use the nth horizontal or vertical axis; for example, axis3 above. The set arrow command can be followed by the keyword with to specify the style of the arrow. For example, the specifiers nohead, head and twohead, when placed after the keyword with, can be used to make arrows with no arrow heads, normal arrow heads, or two arrow heads. twoway is an alias for twohead. All of the line type modifiers accepted by the plot command can also be used here, as in the example: set#arrow#2#from#first#0,#second#2.5#to#axis3#0,\\#############axis4#2.5#with#color#blue#nohead\\ set#autoscale#{#\labaxis\rab#}\\ The set autoscale command causes Pyxplot to choose the scaling for an axis automatically based on the data and/or functions to be plotted against it. The example set#autoscale#x1\\ would cause the range of the first horizontal axis to be scaled to fit the data. Multiple axes can be specified, as in the example set#autoscale#x1y3\\ Note that ranges explicitly specified in a plot command will override the set autoscale command. set#axescolor#\labcolor\rab\\ The setting axescolor changes the color used to draw graph axes. The example set#axescolor#blue\\ would specify that graph axes should be drawn in blue. Any of the recognised color names listed in Section 19.4 of the Users' Guide can be used, or a numbered color from the present palette, or an object of type color. set#axis#\labaxis\rab#[#(#visible#|#invisible#)#]\\##[#(#top#|#bottom#|#left#|#right#|#front#|#back#)#]\\##[#(#atzero#|#notatzero#)#]\\##[#(#automirrored#|#mirrored#|#fullmirrored#)#]\\##[#(#noarrow#|#arrow#|#reversearrow#|#twowayarrow#)#]\\##[#linked#[#item#\labnumber\rab#]#\labaxis\rab#[#using#\labexpression\rab#]#]\\ The set axis command is used to add additional axes to plots and to configure their appearance. Where an axis is stated on its own, as in the example set#axis#x2\\ additional horizontal or vertical axes are added with default settings. The converse statements set#noaxis#x2\\unset#axis#x2\\ are used, respectively, to remove axes from plots and to return them to their default configurations, which often has the same effect of removing them from the graph, unless they are configured otherwise in a configuration file. The position of any axis can be explicitly set using syntax of the form: set#axis#x#top\\set#axis#y#right\\set#axis#z#back\\ Horizontal axes can be set to appear either at the top or bottom; vertical axes can be set to appear either at the left or right; and z-axes can be set to appear either at the front or back. By default, the x1-axis is placed along the bottom of graphs and the y1-axis is placed up the left-hand side of graphs. On three-dimensional plots, the z1-axis is placed at the front of the graph. The second set of axes are placed opposite to the first: the x2-, y2- and z2-axes are placed respectively along the top, right and back sides of graphs. Higher-numbered axes are placed alongside the x1-, y1- and z1-axes. The following keywords may also be placed alongside the positional keywords listed above to specify how the axis should appear: * arrow - Specifies that an arrowhead should be drawn on the right/top end of the axis. [Not default]. \\ * atzero - Specifies that rather than being placed along an edge of the plot, the axis should mark the lines where the perpendicular axes x1, y1 and/or z1 are zero. [Not default]. \\ * automirrored - Specifies that an automatic decision should be made between the behaviour of mirrored and nomirrored. If there are no axes on the opposite side of the graph, a mirror axis is produced. If there are already axes on the opposite side of the graph, no mirror axis is produced. [Default]. \\ * fullmirrored - Similar to mirrored. Specifies that this axis should have a corresponding twin placed on the opposite side of the graph with mirroring ticks and labelling. [Not default; see automirrored]. \\ * invisible - Specifies that the axis should not be drawn; data can still be plotted against it, but the axis is unseen. See Example 24 of the Users' Guide for a plot where all of the axes are invisible. \\ * linked - Specifies that the axis should be linked to another axis; see Section 8.8.9 of the Users' Guide. \\ * mirrored - Specifies that this axis should have a corresponding twin placed on the opposite side of the graph with mirroring ticks but with no labels on the ticks. [Not default; see automirrored]. \\ * noarrow - Specifies that no arrowheads should be drawn on the ends of the axis. [Default]. \\ * nomirrored - Specifies that this axis should not have any corresponding twins. [Not default; see automirrored]. \\ * notatzero - Opposite of atzero; the axis should be placed along an edge of the plot. [Default]. \\ * notlinked - Specifies that the axis should no longer be linked to any other; see Section 8.8.9 of the Users' Guide. [Default]. \\ * reversearrow - Specifies that an arrowhead should be drawn on the left/bottom end of the axis. [Not default]. \\ * twowayarrow - Specifies that arrowheads should be drawn on both ends of the axis. [Not default]. \\ * visible - Specifies that the axis should be displayed; opposite of invisible. [Default]. \\ set#axisunitstyle#(#bracketed#|#squarebracketed#|#ratio#)\\ The setting axisunitstyle controls the style with which the units of plotted quantities are indicated on the axes of plots. The bracketed option causes the units to be placed in parentheses following the axis labels, whilst the squarebracketed option using square brackets instead. The ratio option causes the units to follow the label as a divisor so as to leave the quantity dimensionless. set#backup\\ The setting backup changes Pyxplot's behaviour when it detects that a file which it is about to write is going to overwrite an existing file. Whereas by default the existing file would be overwritten by the new one, when the setting backup is turned on, it is renamed, placing a tilde at the end of its filename. For example, suppose that a plot were to be written with filename out.ps, but such a file already existed. With the backup setting turned on the existing file would be renamed out.ps~ to save it from being overwritten. The setting is turned off using the set nobackup command. set#bar#(#large#|#small#|#\labvalue\rab#)\\ The setting bar changes the size of the bar drawn on the end of the error bars, relative to the current point size. For example: set#bar#2\\ sets the bars to be twice the size of the points. The options large and small are equivalent to1 (the default) and0 (no bar) respectively. set#binorigin#\labvalue\rab\\ The setting binorigin affects the behaviour of the histogram command by adjusting where it places the boundaries between the bins into which it places data. The histogram command selects a system of bins which, if extended to infinity in both directions, would put a bin boundary at the value specified in the set binorigin command. Thus, if a value of 0.1 were specified to the set binorigin command, and a bin width of20 were chosen by the histogram command, bin boundaries might lie at20.1, 40.1, 60.1, and so on. The specified value may have any physical units, but must be real and finite. set#binwidth#\labvalue\rab\\ The setting binwidth changes the width of the bins used by the histogram command. The specified width may have any physical units, but must be real and finite. set#boxfrom#\labvalue\rab\\ The setting boxfrom alters the vertical line from which bars are drawn when Pyxplot draws bar charts. By default, bars all originate from the line y=0, but the example set#boxfrom#2\\ would make the bars originate from the line y=2. The specified vertical abscissa value may have any physical units, but must be real and finite. set#boxwidth#\labwidth\rab\\ The setting boxwidth alters Pyxplot's behaviour when plotting bar charts. It sets the default width of the boxes used, in ordinate axis units. If the specified width is negative then, as happens by default, the boxes have automatically selected widths, such that the interfaces between them occur at the horizontal midpoints between their specified positions. For example: set#boxwidth#2\\ would set all boxes to be two units wide, and set#boxwidth#-2\\ would set all of the bars to have differing widths, centered upon their specified horizontal positions, such that their interfaces occur at the horizontal midpoints between them. The specified width may have any physical units, but must be real and finite. set#c1format#(#auto#|#\labformat\rab#)\\######(#horizontal#|#vertical#|#rotate#\labangle\rab#)\\ The c1format setting is used to manually specify an explicit format for the axis labels to take along the color scale bars drawn alongside plots which make use of the colormap plot style. It has similar syntax to the set xformat command. set#c1label#\labtext\rab#[#rotate#\labangle\rab#]\\ The setting c1label sets the label which should be written alongside the color scale bars drawn next to plots when the colormap plot style is used. An optional rotation angle may be specified to rotate axis labels clockwise by arbitrary angles. The angle should be specified either as a dimensionless number of degrees, or as a quantity with physical dimensions of angle. set#calendar#[#(#input#|#output#)#]#\labcalendar\rab\\ The set calendar command sets the calendar that Pyxplot uses to convert dates between calendar dates and Julian Day numbers. Pyxplot uses two separate calendars which may be different: an input calendar for processing dates that the user inputs as calendar dates, and an output calendar that controls how dates are displayed or written on plots. The available calendars are British, French, Greek, Gregorian, Hebrew, Islamic, Jewish, Julian, Muslim, Papal and Russian, where Jewish is an alias for Hebrew and Muslim is an alias for Islamic. set#clip\\ The set clip command causes Pyxplot to clip points which extend over the edge of plots. The opposite effect is achieved using the set noclip command. set#colorkey#[#\labposition\rab#]\\ The setting colorkey determines whether color scales are drawn along the edges of plots drawn using the colormap plot style, indicating the mapping between represented values and colors. Note that such scales are only ever drawn when the colormap plot style is supplied with only three columns of data, since the color mappings are themselves multi-dimensional when more columns are supplied. Issuing the command set#colorkey\\ by itself causes such a scale to be drawn on graphs in the default position, usually along the right-hand edge of the graphs. The converse action is achieved by: set#nocolorkey\\ The command unset#colorkey\\ causes Pyxplot to revert to its default behaviour, as specified in a configuration file, if present. A position for the key may optionally be specified after the set colorkey command, as in the example: set#colorkey#bottom\\ Recognised positions are top, bottom, left and right. above is an alias for top; below is an alias for bottom and outside is an alias for right. set#colormap#\labcolor#expression\rab#[#mask#\labexpr\rab#]\\ The setting colormap is used to specify the mapping between ordinate values and colors used by the colormap plot style. Within the color expression, the variables c1, c2, c3 and c4 refer quantities calculated from the third through sixth columns of data supplied to the colormap plot style in a way determined by the c\labn\rabrange setting. Thus, the following color mapping, which is the default, produces a greyscale color mapping of the third column of data supplied to the colormap plot style; further columns of data, if supplied, are not used: set#c1range#[*:*]#renormalise\\set#colormap#rgb(c1,c1,c1)\\ If a mask expression is supplied, then any areas in a color map where this expression evaluates to false (or zero) are made transparent. set#contours#[#(#\labnumber\rab#|\\###############"("#{#\labvalue\rab#}#")"#)#]\\#############[#(label#|#nolabel)#]\\ The setting contours is used to define the set of ordinate values for which contours are drawn when using the contourmap plot style. If \labnumber\rab is specified, the contours are evenly spaced - either linearly or logarithmically, depending upon the state of the logscale c1 setting - between the values specified in the c1range setting. Otherwise, the list of ordinate values may be specified as a ()-bracketed comma-separated list. If the option label is specified, then each contour is labelled with the ordinate value that it follows. If the option nolabel is specified, then the contours are not labelled. set#c\labn\rabrange#[#\labrange\rab#]\\##############[#reversed#|#noreversed#]\\##############[#renormalise#|#norenormalise#]\\ The set c\labn\rabrange command changes the range of ordinate values represented by different colors in the colormap plot style, and in the case of the set c1range command, also by contours in the contourmap plot style. The value \labn\rab should be an integer in the range 1-4. The effect of the set c1range command upon the set of ordinate values for which contours are drawn in the contourmap plot style is dependent upon whether the set contours command has been supplied with a number of contours to draw, or a list of explicit ordinate values for which they should be drawn. In the latter case, the set c1range command has no effect. In the former case, the contours are evenly spaced, either linearly or logarithmically depending upon the state of the logscale c1 setting, between the minimum and maximum ordinate values supplied to the set c1range command. If an asterisk (*) is supplied in place of either the minimum and/or the maximum, then the range of values used is automatically scaled to fit the range of the data supplied. The color of each pixel in a color map is determined by the colormap setting. This should contain an expression that evaluates to a color object, e.g. rgb(c1,c2,c3), and which may take the variables c1, c2, c3 and c4 as parameters. The colormap plot style should be supplied with between three and six columns of data, the first two of which contain the x- and y-positions of points, and the remainder of which are used to set the values of the variables c1, c2, c3 and c4 when calculating the color with which that point should be represented. If fewer than six columns of data are supplied, then not all of these variables will be set. The set c\labn\rabrange command is used to determine how the raw data values are mapped to the values of the variables c1-c4. If the norenormalise option is specified, then the raw values are passed directly to the expression. Otherwise, they are first scaled into the range zero to one. If an explicit range is specified to the set c\labn\rabrange command, then the upper limit of this range maps to the value one, and the lower limit maps to the value zero. This mapping is inverted if the reverse option is specified, such that the upper limit maps to zero, and the lower limit maps to one. If an asterisk (*) is supplied in place of either the upper and/or lower limit, then the range automatically scales to fit the data supplied. Intermediate values are scaled, either linearly or logarithmically, depending upon the state of the logscale c\labn\rab setting. For more details of the syntax of the range specifier, see the set xrange command. See set style data. set#[no]display\\ By default, whenever an item is added to a multiplot canvas, or an existing item is moved or replotted, the whole multiplot is redrawn to reflect the change. This can be a time-consuming process when constructing large and complex multiplot canvases, as fresh output is produced at each step. For this reason, the set nodisplay command is provided, which stops Pyxplot from producing any graphical output. The set display command can subsequently be issued to return to normal behaviour. Scripts which produces large and complex multiplot canvases are typically wrapped as follows: set#nodisplay\\...\\set#display\\refresh\\ set#filter#\labfilename#wildcard\rab#\labfilter#command\rab\\ The set filter command allows input filter programs to be specified to allow Pyxplot to deal with file types that are not in the plaintext format which it ordinarily expects. Firstly the pattern used to recognise the filenames of the data files to which the filter should apply to must be specified; the standard wildcard characters * and ? may be used. Then a filter program should be specified, along with any necessary command-line switches which should be passed to it. This program should take the name of the file to be filtered as the final option on its command line, immediately following any command-line switches specified above. It should output a suitable Pyxplot data fileon its standard output stream for Pyxplot to read. For example, to filter all files that end in .foo through the a program called defoo using the -text option one would type: set#filter#"*.foo"#"/usr/local/bin/defoo#--text"\\ set#fontsize#\labvalue\rab\\ The setting fontsize changes the size of the font used to render all text labels which appear on graphs and multiplot canvases, including keys, axis labels, text labels produced using the text command, and so forth. The value specified should be a multiplicative factor greater than zero; a value of2 would cause text to be rendered at twice its normal size, and a value of0.5 would cause text to be rendered at half its normal size. The default value is one. As an alternative, font sizes can be specified with coarser granulation directly in the LaTeX text of labels, as in the example: set#xlabel#'\Large#This#is#a#BIG#label'\\ See set style function. set#[no]grid#{#\labaxis\rab#}\\ The setting grid controls whether a grid is placed behind graphs or not. Issuing the command set#grid\\ would cause a grid to be drawn with its lines connecting to the ticks of the default axes (usually the first horizontal and vertical axes). Conversely, issuing the command set#nogrid\\ would remove from the plot all gridlines associated with the ticks of any axes. One or more axes can be specified for the set grid command to draw gridlines from; in such cases, gridlines are then drawn only to connect with the ticks of the specified axes, as in the example set#grid#x1#y3\\ It is possible, though not always aesthetically pleasing, to draw gridlines from multiple parallel axes, as in example: set#grid#x1x2x3\\ set#gridmajcolor#\labcolor\rab\\ The setting gridmajcolor changes the color that is used to draw the gridlines (see the set grid command) which are associated with the major ticks of axes (i.e. major gridlines). For example: set#gridmajcolor#purple\\ would cause the major gridlines to be drawn in purple. Any of the recognised color names listed in Section 19.4 of the Users' Guide can be used, or a numbered color from the present palette, or an object of type color. See also the set gridmincolor command. set#gridmincolor#\labcolor\rab\\ The setting gridmincolor changes the color that is used to draw the gridlines (see the set grid command) which are associated with the minor ticks of axes (i.e. minor gridlines). For example: set#gridmincolor#purple\\ would cause the minor gridlines to be drawn in purple. Any of the recognised color names listed in Section 19.4 of the Users' Guide can be used, or a numbered color from the present palette, or an object of type color. See also the set gridmajcolor command. set#key#\labposition\rab#[#\labvector\rab#]\\ The setting key determines whether legends are drawn on graphs, and if so, where they should be located on the plots. Issuing the command set#key\\ by itself causes legends to be drawn on graphs in the default position, usually in the upper-right corner of the graphs. The converse action is achieved by: set#nokey\\ The command unset#key\\ causes Pyxplot to revert to its default behaviour, as specified in a configuration file, if present. A position for the key may optionally be specified after the set key command, as in the example: set#key#bottom#left\\ Recognised positions are top, bottom, left, right, below, above, outside, xcenter and ycenter. In addition, if none of these options quite achieve the desired position, a horizontal and vertical offset may be specified as a comma-separated pair after any of the positional keywords above. The first value is assumed to be the horizontal offset, and the second the vertical offset, both measured in centimeters. The example set#key#bottom#left#0.0,#-0.5\\ would display a key below the bottom left corner of the graph. set#keycolumns#(#\labvalue\rab#|#auto#)\\ The setting keycolumns sets how many columns the legend of a plot should be arranged into. By default, the legends of plots are arranged into an automatically-selected number of columns, equivalent to the behaviour achieved by issuing the command set keycolumns auto. However, if a different arrangement is desired, the set keycolumns command can be followed by any positive integer to specify that the legend should be split into that number of columns, as in the example: set#keycolumns#3\\ set#linewidth#\labvalue\rab\\ The set linewidth command sets the default line width of the lines used to plot datasets onto graphs using plot styles such as lines, errorbars, etc. The value supplied should be a multiplicative factor relative to the default line width; a value of1.0 would result in lines being drawn with their default thickness. For example, in the following statement, lines of three times the default thickness are drawn: set#linewidth#3\\plot#sin(x)#with#lines\\ The set linewidth command only affects plot statements where no line width is manually specified. set#logscale#{#\labaxis\rab#}#[#\labbase\rab#]\\ The setting logscale causes an axis to be laid out with logarithmically, rather than linearly, spaced intervals. For example, issuing the command: set#log\\ would cause all of the axes of a plot to be scaled logarithmically. Alternatively, only one, or a selection of axes, can be set to scale logarithmically as follows: set#log#x1#y2\\ This would cause the first horizontal and second vertical axes to be scaled logarithmically. Linear scaling can be restored to all axes using the command set#nolog\\ meanwhile the command unset#log\\ restores axes to their default scaling, as specified in any configuration file which may be present. Both of these commands can also be applied to only one or a selection of axes, as in the examples set#nolog#x1#y2\\ and unset#log#x1y2\\ Optionally, a base may be specified at the end of the set logscale command, to produce axes labelled in logarithms of arbitrary bases. The default base is10. In addition to acting upon any combination of x-, y- and z-axes, the set logscale command may also be requested to set the c1, c2, c3, c4, t, u and/or v axes to scale logarithmically. The first four of these options affect whether the colors on color maps scale linearly or logarithmically with input ordinate values; see the set c\labn\rabrange command for more details. The final three of these options specifies whether parametric functions are sampled linearly or logarithmically in the variables t (one-dimensional), or u and v (two-dimensional); see the set trange, set urange and set vrange commands for more details. set#multiplot\\ Issuing the command set#multiplot\\ causes Pyxplot to enter multiplot mode, which allows many graphs to be plotted together and displayed side-by-side. See Section 10.2 of the Users' Guide for a full discussion of multiplot mode. See set xtics. See set xtics. See set ztics. set#noarrow#[#{#\labarrow#number\rab#}#]\\ Issuing the command set#noarrow\\ removes all arrows configured with the set arrow command. Alternatively, individual arrows can be removed using commands of the form set#noarrow#2\\ where the tag 2 is the identification number given to the arrow to be removed when it was initially specified with the set arrow command. set#noaxis#[#{#\labaxis\rab#}#]\\ The set noaxis command is used to remove axes from graphs; it achieves the opposite effect from the set axis command. It should be followed by a comma-separated lists of the axes which are to be removed from the current axis configuration. See backup. See clip. set#nocolorkey\\ Issuing the command set nocolorkey causes plots to be generated with no color scale when the colormap plot style is used. See the set colorkey command for more details. See display. set#nogrid#{#\labaxis\rab#}\\ Issuing the command set nogrid removes gridlines from the current plot. On its own, the command removes all gridlines from the plot, but alternatively, those gridlines connected to the ticks of certain axes can be selectively removed. The following example would remove gridlines associated with the first horizontal axis and the second vertical axis: set#nogrid#x1#y2\\ set#nokey\\ Issuing the command set nokey causes plots to be generated with no legend. See the set key command for more details. set#nolabel#{#\lablabel#number\rab#}\\ Issuing the command set#nolabel\\ removes all text labels configured using the set label command. Alternatively, individual labels can be removed using the syntax: set#nolabel#2\\ where the tag 2 is the identification number given to the label to be removed when it was initially set using the set label command. set#nologscale#{#\labaxis\rab#}\\ The setting nologscale causes an axis to be laid out with linearly, rather than logarithmically, spaced intervals; it is equivalent to the setting linearscale. It is the converse of the setting logscale. For example, issuing the command set#nolog\\ would cause all of the axes of a plot to be scaled linearly. Alternatively only one, or a selection of axes, can be set to scale linearly as follows: set#nologscale#x1#y2\\ This would cause the first horizontal and second vertical axes to be scaled linearly. set#nomultiplot\\ The set nomultiplot command causes Pyxplot to leave multiplot mode; outside of multiplot mode, only single graphs and vector graphics objects are displayed at any one time, whereas in multiplot mode, galleries of plots and vector graphics can be placed alongside one another. See Section 10.2 of the Users' Guide for a full discussion of multiplot mode. set#nostyle#\labstyle#number\rab\\ The setting nostyle deletes a numbered plot style set using the set style command. For example, the command set#nostyle#3\\ would delete the third numbered plot style, if defined. See the command set style for more details. set#notitle\\ Issuing the command set notitle will cause graphs to be produced with no title at the top. set#no\labaxis\rabtics\\ This command causes graphs to be produced with no major tick marks along the specified axis. For example, the set noxtics command removes all major tick marks from the x-axis. Similar to the set noxtics command, but acts on vertical axes. Similar to the set noxtics command, but acts on z-axes. set#numerics#[#(#complex#|#real#)#]#[#errors#(#explicit#|#quiet)#]\\####[#display#(#latex#|#natural#|#typeable)#]\\####[#sigfig#\labprecision\rab#]\\ The set numerics command is used to adjust the way in which calculations are carried out and numerical quantities are displayed: * The option complex causes Pyxplot to switch from performing real arithmetic (default) to performing complex arithmetic. The option real causes any calculations which return results with finite imaginary components to generate errors. \\ * The option errors controls how numerical errors such as divisions by zero, numerical overflows, and the querying functions outside of the domains in which they are defined, are communicated to the user. The option explicit (default) causes an error message to be displayed on the terminal whenever a calculation causes an error. The option quiet causes such calculations to silently generate a nan (not a number) result. The latter is especially useful when, for example, plotting an expression with the ordinate axis range set to extend outside the domain in which that expression returns a well-defined real result; it suppresses the error messages which might otherwise result from Pyxplot's attempts to evaluate the expression in those domains where its result is undefined. The option nan is a synonym for quiet. \\ * The setting display changes the format in which numbers are displayed on the terminal. Setting the option to typeable causes the numbers to be printed in a form suitable for pasting back into Pyxplot commands. The setting latex causes LaTeX-compatible output to be generated. The setting natural generates concise, human-readable output which has neither of the above properties. \\ * The setting sigfig changes the number of significant figures to which numbers are displayed on the Pyxplot terminal. Regardless of the value set, all calculations are internally carried out and stored at double precision, accurate to around16 significant figures. \\ set#origin#\labvector\rab\\ The set origin command is used to set the location of the bottom-left corner of the next graph to be placed on a multiplot canvas. For example, the command set#origin#3,5\\ would cause the next graph to be plotted with its bottom-left corner at position (3,5) centimeters on the multiplot canvas. Alternatively, either of the coordinates may be specified as quantities with physical units of length, such as unit(35*mm). The set origin command is of little use outside of multiplot mode. set#output#\labfilename\rab\\ The setting output controls the name of the file that is produced for non-interactive terminals (postscript, eps, jpeg, gif and png). For example, set#output#'myplot.eps'\\ causes the output to be written to the file myplot.eps. set#palette#{#\labcolor\rab#}\\ Pyxplot has a palette of colors which it assigns sequentially to datasets when colors are not manually assigned. This is also the palette to which reference is made if the user issues a command such as plot#sin(x)#with#color#5\\ requesting the fifth color from the palette. By default, this palette contains a range of distinctive colors. However, the user can choose to substitute his own list of colors using the set palette command. It should be followed by a comma-separated list of color names, for example: set#palette#red,green,blue\\ If, after issuing this command, the following plot statement were to be executed: plot#sin(x),#cos(x),#tan(x),#exp(x)\\ the first function would be plotted in red, the second in green, and the third in blue. Upon reaching the fourth, the palette would cycle back to red. Any of the recognised color names listed in Section 19.4 of the Users' Guide can be used, or a numbered color from the present palette, or an object of type color. set#papersize#(#\labnamed#size\rab#|#\labheight\rab,\labwidth\rab#)\\ The setting papersize changes the size of output produced by the postscript terminal, and whenever the enlarge terminal option is set (see the set terminal command). This can take the form of either a recognised paper size name, or as a (height, width) pair of values, both measured in millimeters. The following examples demonstrate these possibilities: set#papersize#a4\\set#papersize#letter\\set#papersize#200,100\\ The following named papersizes are recognised: |###########################2a0###1681###1189 |###########################4a0###2378###1681 |############################a0###1189####840 |############################a1####840####594 |###########################a10#####37#####26 |############################a2####594####420 |############################a3####420####297 |############################a4####297####210 |############################a5####210####148 |############################a6####148####105 |############################a7####105#####74 |############################a8#####74#####52 |############################a9#####52#####37 |############################b0###1414####999 |############################b1####999####707 |###########################b10#####44#####31 |############################b2####707####499 |############################b3####499####353 |############################b4####353####249 |############################b5####249####176 |############################b6####176####124 |############################b7####124#####88 |############################b8#####88#####62 |############################b9#####62#####44 |############################c0###1296####917 |############################c1####917####648 |###########################c10#####40#####28 |############################c2####648####458 |############################c3####458####324 |############################c4####324####229 |############################c5####229####162 |############################c6####162####114 |############################c7####114#####81 |############################c8#####81#####57 |############################c9#####57#####40 |#########################crown####508####381 |##########################demy####572####445 |###################double_demy####889####597 |######################elephant####711####584 |###################envelope_dl####110####220 |#####################executive####267####184 |######################foolscap####330####203 |#############government_letter####267####203 |####international_businesscard#####85#####53 |###################japanese_b0###1435###1015 |###################japanese_b1###1015####717 |##################japanese_b10#####44#####31 |###################japanese_b2####717####507 |###################japanese_b3####507####358 |###################japanese_b4####358####253 |###################japanese_b5####253####179 |###################japanese_b6####179####126 |###################japanese_b7####126#####89 |###################japanese_b8#####89#####63 |###################japanese_b9#####63#####44 |################japanese_kiku4####306####227 |################japanese_kiku5####227####151 |#############japanese_shiroku4####379####264 |#############japanese_shiroku5####262####189 |#############japanese_shiroku6####188####127 |####################large_post####533####419 |########################ledger####432####279 |#########################legal####356####216 |########################letter####279####216 |########################medium####584####457 |#######################monarch####267####184 |##########################post####489####394 |#####################quad_demy###1143####889 |########################quarto####254####203 |#########################royal####635####508 |#####################statement####216####140 |####################swedish_d0###1542###1090 |####################swedish_d1###1090####771 |###################swedish_d10#####48#####34 |####################swedish_d2####771####545 |####################swedish_d3####545####385 |####################swedish_d4####385####272 |####################swedish_d5####272####192 |####################swedish_d6####192####136 |####################swedish_d7####136#####96 |####################swedish_d8#####96#####68 |####################swedish_d9#####68#####48 |####################swedish_e0###1241####878 |####################swedish_e1####878####620 |###################swedish_e10#####38#####27 |####################swedish_e2####620####439 |####################swedish_e3####439####310 |####################swedish_e4####310####219 |####################swedish_e5####219####155 |####################swedish_e6####155####109 |####################swedish_e7####109#####77 |####################swedish_e8#####77#####54 |####################swedish_e9#####54#####38 |####################swedish_f0###1476###1044 |####################swedish_f1###1044####738 |###################swedish_f10#####46#####32 |####################swedish_f2####738####522 |####################swedish_f3####522####369 |####################swedish_f4####369####261 |####################swedish_f5####261####184 |####################swedish_f6####184####130 |####################swedish_f7####130#####92 |####################swedish_f8#####92#####65 |####################swedish_f9#####65#####46 |####################swedish_g0###1354####957 |####################swedish_g1####957####677 |###################swedish_g10#####42#####29 |####################swedish_g2####677####478 |####################swedish_g3####478####338 |####################swedish_g4####338####239 |####################swedish_g5####239####169 |####################swedish_g6####169####119 |####################swedish_g7####119#####84 |####################swedish_g8#####84#####59 |####################swedish_g9#####59#####42 |####################swedish_h0###1610###1138 |####################swedish_h1###1138####805 |###################swedish_h10#####50#####35 |####################swedish_h2####805####569 |####################swedish_h3####569####402 |####################swedish_h4####402####284 |####################swedish_h5####284####201 |####################swedish_h6####201####142 |####################swedish_h7####142####100 |####################swedish_h8####100#####71 |####################swedish_h9#####71#####50 |#######################tabloid####432####279 |###############us_businesscard#####89#####51 set#pointlinewidth#\labvalue\rab\\ The setting pointlinewidth changes the width of the lines that are used to plot data points. For example, set#pointlinewidth#20\\ would cause points to be plotted with lines20 times the default thickness. The setting pointlinewidth can be abbreviated as plw. set#pointsize#\labvalue\rab\\ The setting pointsize changes the size at which points are drawn, relative to their default size. It should be followed by a single value which can be any positive multiplicative factor. For example, set#pointsize#1.5\\ would cause points to be drawn at1.5 times their default size. set#preamble#\labtext\rab\\ The setting preamble changes the text of the preamble that is passed to LaTeX prior to the rendering of each text item on the current multiplot canvas. This allows, for example, different packages to be loaded by default and user-defined macros to be set up, as in the examples: set#preamble#\usepackage{marvosym}\\set#preamble#\def\degrees{$^\circ$}\\ set#samples#[\labvalue\rab]\\############[grid#\labx_samples\rab#[x]#\laby_samples\rab]\\############[interpolate#(#inverseSquare#|\\###########################monaghanLattanzio#|\\###########################nearestNeighbor#)#]\\ The setting samples determines the number of values along the ordinate axis at which functions are evaluated when they are plotted. For example, the command set#samples#100\\ would cause functions to be evaluated at 100points along the ordinate axis. Increasing this value will cause functions to be plotted more smoothly, but also more slowly, and the PostScript files generated will also be larger. When functions are plotted with the points plot style, this setting controls the number of points plotted. After the keyword grid may be specified the dimensions of the two-dimensional grid of samples used in the colormap and surface plot styles, and internally when calculating the contours to be plotted in the contourmap plot style. If a * is given in place of either of the dimensions, then the same number of samples as are specified in \labvalue\rab are taken. After the keyword interpolate, the method used for interpolating non-gridded two-dimensional data onto the above-mentioned grid may be specified. The available options are InverseSquare, MonaghanLattanzio and NearestNeighbour. set#seed#\labvalue\rab\\ The set seed command sets the seed used by all of those mathematical functions which generate random samples from probability distributions. This allows repeatable sequences of pseudo-random numbers to be generated. Upon initialisation, Pyxplot returns the sequence of random numbers obtained after issuing the command set seed0. set#size#[\labwidth\rab]\\#########[(#ratio#\labratio\rab#|#noratio##|#square)]\\#########[(zratio#\labratio\rab#|#nozratio#)]\\ The setting size is used to set the width or aspect ratio of the next graph to be generated. If a width is specified, then it may either take the form of a dimensionless number implicitly measured in centimeters, or a quantity with physical dimensions of length such as unit(50*mm). When the keyword ratio is specified, it should be followed by the ratio of the graph's height to its width, i.e. of the length of its y-axes to that of its x-axes. The keyword noratio returns the aspect ratio to its default value of the golden ratio, and the keyword square sets the aspect ratio to one. When the keyword zratio is specified, it should be followed by the ratio of the length of three-dimensional graphs' z-axes to that of their x-axes. The keyword nozratio returns this aspect ratio to its default value of the golden ratio. set#size#noratio\\ Executing the command set#size#noratio\\ resets Pyxplot to produce plots with its default aspect ratio, which is the golden ratio. Other aspect ratios can be set with the set size ratio command. set#size#ratio#\labratio\rab\\ This command sets the aspect ratio of plots produced by Pyxplot. The height of resulting plots will equal the plot width, as set by the set width command, multiplied by this aspect ratio. For example, set#size#ratio#2.0\\ would cause Pyxplot to produce plots that are twice as high as they are wide. The default aspect ratio which Pyxplot uses is a golden ratio of 2/(1+sqrt5). set#size#square\\ This command sets Pyxplot to produce square plots, i.e. with unit aspect ratio. Other aspect ratios can be set with the set size ratio command. set#style#{#data#|#function#}#{\labstyle#option\rab}\\ The set style data command affects the default style with which data from files is plotted. Likewise the set style function command changes the default style with which functions are plotted. Any valid style modifier which can follow the keyword with in the plot command can be used. For example, the commands set#style#data#points\\set#style#function#lines#linestyle#1\\ would cause data files to be plotted, by default, using points and functions using lines with the first defined line style. set#terminal#(#X11_singleWindow#|#X11_multiWindow#|#X11_persist#|\\###############bmp#|#eps#|#gif#|#jpeg#|#pdf#|#png#|#postscript#|\\###############svg#|#tiff#)\\#############(#color#|#color#|#monochrome#)\\#############(#dpi#\labvalue\rab#)\\#############(#portrait#|#landscape#)\\#############(#invert#|#noinvert#)\\#############(#transparent#|#solid#)\\#############(#antialias#|#noantialias#)\\#############(#enlarge#|#noenlarge#)\\ The set terminal command controls the graphical format in which Pyxplot renders plots and multiplot canvases, for example configuring whether it should output plots to files or display them in a window on the screen. Various options can also be set within many of the graphical formats which Pyxplot supports using this command. The following graphical formats are supported: X11_singleWindow, X11_multiWindow, X11_persist, bmp, eps, gif, jpeg, pdf, png, postscript, svg[*], tiff. To select one of these formats, simply type the name of the desired format after the set terminal command. To obtain more details on each, see the subtopics below. The following settings, which can also be typed following the set terminal command, are used to change the options within some of these graphic formats: color, monochrome, dpi, portrait, landscape, invert, noinvert, transparent, solid, enlarge, noenlarge. Details of each of these can be found below. The antialias terminal option causes plots produced with the bitmap terminals (i.e. bmp, gif, jpeg, png and tiff) to be antialiased; this is the default behaviour. * -- The svg output terminal is experimental and may be unstable. It relies upon the use of the svg output device in Ghostscript, which may not be present on all systems. The bmp terminal renders output as Windows bitmap images. The filename to which output is to be sent should be set using the set output command; the default is pyxplot.bmp. The number of dots per inch used can be changed using the dpi option. The invert option may be used to produce an image with inverted colors. The color terminal option causes plots to be produced in color; this is the default behaviour. The color terminal option is the US-English equivalent of color. When Pyxplot is set to produce bitmap graphics output, using the bmp, gif, jpg or png terminals, the setting dpi changes the number of dots per inch with which these graphical images are produced. That is to say, it changes the image resolution of the output images. For example, set#terminal#dpi#100\\ sets the output to a resolution of100 dots per inch. Higher DPI values yield better quality images, but larger file sizes. The enlarge terminal option causes plots and multiplot canvases to be enlarged or shrunk to fit within the margins of the currently selected paper size. It is especially useful when using the postscript terminal, as it allows for the production of immediately-printable output. Sends output to Encapsulated PostScript (eps) files. The filename to which output should be sent can be set using the set output command; the default is pyxplot.eps. This terminal produces images suitable for including in, for example, LaTeX documents. The gif terminal renders output as gif images. The filename to which output should be sent can be set using the set output command; the default is pyxplot.gif. The number of dots per inch used can be changed using the dpi option. Transparent gifs can be produced with the transparent option. The invert option may be used to produce an image with inverted colors. The invert terminal option causes the bitmap terminals (i.e. bmp, gif, jpeg, png and tiff) to produce output with inverted colors. The jpeg terminal renders output as jpeg images. The filename to which output should be sent can be set using the set output command; the default is pyxplot.jpg. The number of dots per inch used can be changed using the dpi option. The invert option may be used to produce an image with inverted colors. The landscape terminal option causes Pyxplot's output to be displayed in rotated orientation. This can be useful for fitting graphs onto sheets of paper, but is generally less useful for plotting things on screen. The monochrome terminal option causes plots to be rendered in black and white. This changes the default behaviour of the plot command to be optimised for monochrome display, and so, for example, different dash styles are used to differentiate between lines on plots with several datasets. The noantialias terminal option causes plots produced with the bitmap terminals (i.e. bmp, gif, jpeg, png and tiff) not to be antialiased. This can be useful when making plots which will subsequently have regions cut out and made transparent. The noenlarge terminal option causes the output not to be scaled to fit within the margins of the currently-selected papersize. This is the opposite of enlarge option. The noinvert terminal option causes the bitmap terminals (i.e. gif, jpeg, png) to produce normal output without inverted colors. This is the opposite of the inverse option. The pdf terminal renders output in Adobe's Portable Document Format (PDF). The png terminal renders output as png images. The filename to which output should be sent can be set using the set output command; the default is pyxplot.png. The number of dots per inch used can be changed using the dpi option. Transparent pngs can be produced with the transparent option. The invert option may be used to produce an image with inverted colors. The portrait terminal option causes Pyxplot's output to be displayed in upright (normal) orientation; it is the converse of the landscape option. The postscript terminal renders output as PostScript files. The filename to which output should be sent can be set using the set output command; the default is pyxplot.ps. This terminal produces non-encapsulated PostScript suitable for sending directly to a printer; it should not be used for producing images to be embedded in documents, for which the eps terminal should be used. The solid option causes the gif and png terminals to produce output with a non-transparent background, the converse of transparent. The transparent terminal option causes the gif and png terminals to produce output with a transparent background. The X11_multiwindow terminal displays plots on the screen in X11 windows. Each time a new plot is generated it appears in a new window, and the old plots remain visible. As many plots as may be desired can be left on the desktop simultaneously. When Pyxplot exits, however, all of the windows are closed. The X11_persist terminal displays plots on the screen in X11 windows. Each time a new plot is generated it appears in a new window, and the old plots remain visible. When Pyxplot is exited the windows remain in place until they are closed manually. The X11_singlewindow terminal displays plots on the screen in X11 windows. Each time a new plot is generated it replaces the old one, preventing the desktop from becoming flooded with old plots. This terminal is the default when running interactively. set#textcolor#\labcolor\rab\\ The setting textcolor changes the default color of all text displayed on plots or multiplot canvases. For example, set#textcolor#red\\ causes all text labels, including the labels on graph axes and legends, etc. to be rendered in red. Any of the recognised color names listed in Section 19.4 of the Users' Guide can be used, or a numbered color from the present palette, or an object of type color. set#texthalign#(#left#|#center#|#right#)\\ The setting texthalign controls how text labels are justified horizontally with respect to their specified positions, acting both upon labels placed on plots using the set label command, and upon text items created using the text command. Three options are available: set#texthalign#left\\set#texthalign#center\\set#texthalign#right\\ set#textvalign#(#bottom#|#center#|#top#)\\ The setting textvalign controls how text labels are justified vertically with respect to their specified positions, acting both upon labels placed on plots using the set label command, and upon text items created using the text command. Three options are available: set#textvalign#bottom\\set#textvalign#center\\set#textvalign#top\\ set#title#\labtitle\rab\\ The setting title can be used to set a title for a plot, to be displayed above it. For example, the command: set#title#'foo'\\ would cause a title `foo' to be displayed above a graph. The easiest way to remove a title, having set one, is using the command: set#notitle\\ set#trange#[#\labrange\rab#]#[reverse]\\ The set trange command changes the range of the free parameter t used when generating parametric plots. For more details of the syntax of the range specifier, see the set xrange command. Note that t is not allowed to autoscale, and so the * character is not permitted in the specified range. set#unit#[#angle#(#dimensionless#|#nodimensionless#)#]\\#########[#of#\labdimension\rab#\labunit\rab#]\\#########[#scheme#\labunit#scheme\rab#]\\#########[#preferred#\labunit\rab#]\\#########[#nopreferred#\labunit\rab#]\\#########[#display#(#full#|#abbreviated#|#prefix#|#noprefix#)#]\\ The set unit command controls how quantities with physical units are displayed by Pyxplot. The set unit scheme command provides the most general configuration option, allowing one of several units schemes to be selected, each of which comprises a list of units which are deemed to be members of that particular scheme. For example, in the CGS unit scheme, all lengths are displayed in centimeters, all masses are displayed in grammes, all energies are displayed in ergs, and so forth. In the imperial unit scheme, quantities are displayed in British imperial units - inches, pounds, pints, and so forth - and in the US unit scheme, US customary units are used. The available schemes are: ancient, cgs, imperial, planck, si, and us. To fine-tune the unit used to display quantities with a particular set of physical dimensions, the set unit of form of the command should be used. For example, the following command would cause all lengths to be displayed in inches: set#unit#of#length#inch\\ The set unit preferred command offers a slightly more flexible way of achieving the same result. Whereas the set unit of command can only operate on named quantities such as lengths and powers, and cannot act upon compound units such as W/Hz, the set unit preferred command can act upon any unit or combination of units, as in the examples: set#unit#preferred#parsec\\set#unit#preferred#W/Hz\\set#unit#preferred#N*m\\ The latter two examples are particularly useful when working with spectral densities (powers per unit frequency) or torques (forces multiplied by distances). Unfortunately, both of these units are dimensionally equal to energies, and so are displayed by Pyxplot in Joules by default. The above statement overrides such behaviour. Having set a particular unit to be preferred, this can be unset as in the following example: set#unit#nopreferred#parsec\\ By default, units are displayed in their abbreviated forms, for example A instead of amperes and W instead of watts. Furthermore, SI prefixes such as milli- and kilo- are applied to SI units where they are appropriate. Both of these behaviours can be turned on or off, in the former case with the commands set#unit#display#abbreviated\\set#unit#display#full\\ and in the latter case using the following pair of commands: set#unit#display#prefix\\set#unit#display#noprefix\\ set#urange#[#\labrange\rab#]#[reverse]\\ The set urange command changes the range of the free parameter u used when generating parametric plots sampled over grids of (u,v) values. For more details of the syntax of the range specifier, see the set xrange command. Note that u is not allowed to autoscale, and so the * character is not permitted in the specified range. Specifying the set urange command by itself specified that parametric plots should be sampled over two-dimensional grids of (u,v) values, rather than one-dimensional ranges of t values. set#view#\labtheta\rab,#\labphi\rab\\ The set view command is used to specify the angle from which three-dimensional plots are viewed. It should be followed by two angles, which can either be expressed in degrees, as dimensionless numbers, or as quantities with physical units of angle: set#view#60,30\\\\set#unit#angle#nodimensionless\\set#view#unit(0.1*rev),unit(2*rad)\\ The orientation (0,0) corresponds to having the x-axis horizontal, the z-axis vertical, and the y-axis directed into the page. The first angle supplied to the set view command rotates the plot in the (x,y) plane, and the second angle tips the plot up in the plane containing the z-axis and the normal to the user's two-dimensional display. set#viewer#(#auto#|#\labcommand\rab#)\\ The set viewer command is used to select which external PostScript viewing application is used to display Pyxplot output on screen in the X11 terminals. If the option auto is selected, then either ghostview or ggv is used, if installed. Alternatively, any other application such as evince or okular can be selected by name, providing it is installed in within your shell's search path or an absolute path is provided, as in the examples: set#viewer#evince\\set#viewer#/usr/bin/okular\\ Additional commandline switches may also be provided after the name of the application to be used, as in the example set#viewer#gv#--grayscale\\ set#vrange#[#\labrange\rab#]#[reverse]\\ See the set urange command. set#width#\labvalue\rab\\ The setting width is used to set the width of the next graph to be generated. The width is specified either as a dimensionless number implicitly measured in centimeters, or as a quantity with physical dimensions of length such as unit(50*mm). set#\labaxis\rabformat#(#auto#|#\labformat\rab#)\\######(#horizontal#|#vertical#|#rotate#\labangle\rab#)\\ By default, the major tick marks along axes are labelled with representations of the ordinate values at each point, each accurate to the number of significant figures specified using the set numerics sigfig command. These labels may appear as decimals, such as 3.142, in scientific notion, as in 3 x 10, or, on logarithmic axes where a base has been specified for the logarithms, using syntax such as[*] set#log#x1#2\\ in a format such as 1.5 x 2. The set xformat command - together with its companions such as set yformat - is used to manually specify an explicit format for the axis labels to take, as demonstrated by the following pair of examples: set#xformat#"%.2f"%(x)\\set#yformat#"%s$^\prime$"%(y/unit(feet))\\ The first example specifies that values should be displayed to two decimal places along the x-axis; the second specifies that distances should be displayed in feet along the y-axis. Note that the dummy variable used to represent the represented value is x, y or z depending upon the direction of the axis, but that the dummy variable used in the set x2format command is still x. The following pair of examples both have the equivalent effect of returning the x2-axis to its default system of tick labels: set#x2format#auto\\set#x2format#"%s"%(x)\\ The following example specifies that ordinate values should be displayed as multiples of pi: set#xformat#"%s$\pi$"%(x/pi)\\plot#[-pi:2*pi]#sin(x)\\ Note that where possible, Pyxplot intelligently changes the positions along axes where it places the ticks to reflect significant points in the chosen labelling system. The extent to which this is possible depends upon the format string supplied. It is generally easier when continuous-varying numerical values are substituted into strings, rather than discretely-varying values or strings. * -- Note that the x axis must be referred to as x1 here to distinguish this statement from set log x2. set#\labaxis\rablabel#\labtext\rab#[#rotate#\labangle\rab#]\\ The setting xlabel sets the label which should be written along the x-axis. For example, set#xlabel#'$x$'\\ sets the label on the x-axis to read `x'. Labels can be placed on higher numbered axes by inserting their number after the `x'; for example, set#x10label#'foo'\\ would label the tenth horizontal axis. Similarly, labels can be placed on vertical axes as follows: set#ylabel#'$y$'\\set#y2label#'foo'\\ An optional rotation angle may be specified to rotate axis labels clockwise by arbitrary angles. The angle should be specified either as a dimensionless number of degrees, or as a quantity with physical dimensions of angle. set#\labaxis\rabrange#\labrange\rab#[reverse]\\ The setting xrange controls the range of values spanned by the x-axes of plots. For function plots, this is also the domain across which the function will be evaluated. For example, set#xrange#[0:10]\\ sets the first horizontal axis to run from0 to10. Higher numbered axes may be referred to be inserting their number after the x; the ranges of vertical axes may similarly be set by replacing the x with a y. Hence, set#y23range#[-5:5]\\ sets the range of the 23rd vertical axis to run from-5 to5. To request a range to be automatically scaled an asterisk can be used. The following command would set the x-axis to have an upper limit of 10, but does not affect the lower limit; its range remains at its previous setting: set#xrange#[:10][*:*]\\ The keyword reverse is used to indicate that the two limits of an axis should be swapped. This is useful for setting auto-scaling axes to be displayed running from right to left, or from top to bottom. set#[m]\labaxis\rabtics\\####[#(#axis#|#border#|#inward#|#outward#|#both#)#]\\####[#(#autofreq\\##########|#[\labminimum\rab,]#\labincrement\rab#[,#\labmaximum\rab]\\##########|#"("#{#[#\lablabel\rab#]#\labposition\rab#}#")"\\#########]#)\\ By default, Pyxplot places a series of tick marks at significant points along each axis, with the most significant points being labelled. Labelled tick marks are termed major ticks, and unlabelled tick marks are termed minor ticks. The position and appearance of the major ticks along the x-axis can be configured using the set xtics command; the corresponding set mxtics command configures the appearance of the minor ticks along the x-axis. Analogous commands such as set ytics and set mx2tics configure the major and minor ticks along other axes. The keywords inward, outward and both are used to configure how the ticks appear - whether they point inward, towards the plot, as is default, or outwards towards the axis labels, or in both directions. The keyword axis is an alias for inward, and border is an alias for outward. The remaining options are used to configure where along the axis ticks are placed. If a series of comma-separated values \labminimum\rab, \labincrement\rab, \labmaximum\rab are specified, then ticks are placed at evenly spaced intervals between the specified limits. The \labminimum\rab and \labmaximum\rab values are optional; if only one value is specified then it is taken to be the step size between ticks. If two values are specified, then the first is taken to be \labminimum\rab. In the case of logarithmic axes, \labincrement\rab is applied as a multiplicative step size. Alternatively, if a bracketed list of quoted tick labels and tick positions are provided, then ticks can be placed on an axis manually and each given its own textual label. The quoted tick labels may be omitted, in which case they are automatically generated: set#xtics#("a"#1,#"b"#2,#"c"#3)\\set#xtics#(1,2,3)\\ The keyword autofreq overrides any manual selection of ticks which may have been placed on an axis and resumes the automatic placement of ticks along it. The show xtics command, together with its companions such as show x2tics and show ytics, is used to query the current ticking options. The set noxtics command is used to stipulate that no ticks should appear along a particular axis: set#noxtics\\show#xtics\\ See xformat. See xlabel. See xrange. See xtics. See xformat. See xlabel. See xrange. See xtics. show#{#all#|#axes#|#functions#|#settings#|#units\\#######|#userfunctions#|#variables#|#\labparameter\rab#}\\ The show command displays the present state of parameters which can be set with the set command. For example, show#pointsize\\ displays the currently set point size. Details of the various parameters which can be queried can be found under the set command; any keyword which can follow the set command can also follow the show command. In addition, show all shows a complete list of the present values of all of Pyxplot's configurable parameters. The command show settings shows all of these parameters, but does not list the currently-configured variables, functions and axes. show axes shows the configuration states of all graph axes. show variables lists all of the currently defined variables. And finally, show functions lists all of the current user-defined functions. solve#{#\labequation\rab#}#via#{#\labvariable\rab#}\\ The solve command can be used to solve simple systems of one or more equations numerically. It takes as its arguments a comma-separated list of the equations which are to be solved, and a comma-separated list of the variables which are to be found. The latter should be prefixed by the word via, to separate it from the list of equations. Note that the time taken by the solver dramatically increases with the number of variables which are simultaneously found, whereas the accuracy achieved simultaneously decreases. The following example solves a simple pair of simultaneous equations of two variables: No output is returned to the terminal if the numerical solver succeeds, otherwise an error message is displayed. If any of the fitting variables are already defined prior to the solve command's being called, their values are used as initial guesses, otherwise an initial guess of unity for each fitting variable is assumed. Thus, the same solve command returns two different values in the following two cases: In cases where any of the variables being solved for are not dimensionless, it is essential that an initial guess with appropriate units be supplied, otherwise the solver will try and fail to solve the system of equations using dimensionless values: x#=#unit(m)\\y#=#5*unit(km)\\solve#x=y#via#x\\ The solve command works by minimising the squares of the residuals of all of the equations supplied, and so even when no exact solution can be found, the best compromise is returned. The following example has no solution - a system of three equations with two variables is over-constrained - but Pyxplot nonetheless finds a compromise solution: When complex arithmetic is enabled, the solve command allows each of the variables being fitted to take any value in the complex plane, and thus the number of dimensions of the fitting problem is effectively doubled - the real and imaginary components of each variable are solved for separately - as in the following example: spline#[#\labrange\rab#]#\labfunction#name\rab()\\#######(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\#######[#every#{#\labexpression\rab#}#]\\#######[#index#\labvalue\rab#]\\#######[#select#\labexpression\rab#]\\#######[#using#{#\labexpression\rab#}#]\\ The spline command is an alias for the interpolate spline command. See the entry for the interpolate command for more details. swap#\labitem1\rab#\labitem2\rab\\ Items on multiplot canvases are drawn in order of increasing identification number, and thus items with low identification numbers are drawn first, at the back of the multiplot, and items with higher identification numbers are later, towards the front of the multiplot. When new items are added, they are given higher identification numbers than previous items and appear at the front of the multiplot. If this is not the desired ordering, then the swap command may be used to rearrange items. It takes the identification numbers of two multiplot items and swaps their identification numbers and hence their positions in the ordered sequence. Thus, if, for example, the corner of item3 disappears behind the corner of item5, when the converse effect is actually desired, the following command should be issued: swap#3#5\\ tabulate#[#\labrange\rab#]\\#######(#\labfilename\rab#|#{#\labexpression\rab#}#|#{#\labvector#obj\rab#}#)\\#######[#every#{#\labexpression\rab#}#]\\#######[#index#\labvalue\rab#]\\#######[#select#\labexpression\rab#]\\#######[#sortby#\labexpression\rab#]\\#######[#using#{#\labexpression\rab#}#]\\#######[#with#\laboutput#format\rab#]\\ Pyxplot's tabulate command is similar to its plot command, but instead of plotting a series of data points onto a graph, it outputs them to data files. This can be used to produce text files containing samples of functions, to rearrange/filter the columns in data files, to change the units in which data is expressed in data files, and so forth. The following example would produce a data file called gamma.dat containing a list of values of the gamma function: set#output#'gamma.dat'\\tabulate#[1:5]#gamma(x)\\ Multiple functions may be tabulated into the same file, either by using the using modifier: tabulate#[0:2*pi]#sin(x):cos(x):tan(x)#u#1:2:3:4\\ or by placing them in a comma-separated list, as in the plot command: tabulate#[0:2*pi]#sin(x),#cos(x),#tan(x)\\ In the former case, the functions are tabulated horizontally alongside one another in a series of columns. In the latter case, the functions are tabulated one after another in a series of index blocks separated by double linefeeds (see Section 3.8 of the Users' Guide). The setting samples can be used to control the number of points that are produced when tabulating functions, in the same way that it controls the plot command: set#samples#200\\ If the ordinate axis is set to be logarithmic then the points at which functions are evaluated are spaced logarithmically, otherwise they are spaced linearly. The select, using and every modifiers operate in the same manner in the tabulate command as in the plot command. Thus, the following example would write out the third, sixth and ninth columns of the data file input.dat, but only when the arcsine of the value in the fourth column is positive: set#output#'filtered.dat'\\tabulate#'input.dat'#u#3:6:9#select#(asin($4)\rab0)\\ The numerical display format used in each column of the output file is chosen automatically to preserve accuracy whilst simultaneously being as easily human readable as possible. Thus, columns which contain only integers are displayed as such, and scientific notation is only used in columns which contain very large or very small values. If desired, however, a format statement may be specified using the with format specifier. The syntax for this is similar to that expected by the string substitution operator (%; see Section 6.2.1 of the Users' Guide). As an example, to tabulate the values of x to very many significant figures with some additional text, one could use: tabulate#x**2#with#format#"x#=#%f#;#x**2#=#%27.20e"\\ This might produce the following output: x#=#0.000000#;#x**2#=##0.00000000000000000000e+00\\x#=#0.833333#;#x**2#=##6.94444444444442421371e-01\\x#=#1.666667#;#x**2#=##2.77777777777778167589e+00\\ The data produced by the tabulate command can be sorted in order of any arbitrary metric by supplying an expression after the sortby modifier; where such expressions are supplied, the data is sorted in order from the smallest value of the expression to the largest. text#[#item#\labid\rab#]#\labtext#string\rab#[#at#\labvector\rab#]\\#####[#rotate#\labangle\rab#]#[#gap#\lablength\rab#]\\#####[#halign#\labalignment\rab#]#[#valign#\labalignment\rab#]\\#####[#with#color#\labcolor\rab#]\\ The text command allows strings of text to a added as labels on multiplot canvases. The example text#'Hello#World!'#at#0,2\\ would render the text `Hello World!' at position (0,2), measured in centimeters. The alignment of the text item with respect to this position can be set using the set texthalign and set textvalign commands, or using the halign and valign modifiers supplied to the text command itself. A gap may be specified, which should either have dimensions of length, or be dimensionless, in which case it is interpreted as being measured in centimeters. If a gap is specified, then the text string is slightly displaced from the specified position, in the direction in which it is being aligned. A rotation angle may optionally be specified after the keyword rotate to produce text rotated to any arbitrary angle, measured in degrees counter-clockwise. The following example would produce upward-running text: text#'Hello'#at#1.5,#3.6#rotate#90\\ By default the text is black; however, an arbitrary color may be specified using the with color modifier. For example: text#'A#purple#label'#at#0,#0#with#color#purple\\ would add a purple label at the origin of the multiplot. Outside of multiplot mode, the text command can be used to produce images consisting simply of one single text item. This can be useful for importing LaTeXed equations as gif images into slideshow programs such as Microsoft Powerpoint which are incapable of producing such neat mathematical notation by themselves. All vector graphics objects placed on multiplot canvases receive unique identification numbers which count sequentially from one, and which may be listed using the list command. By reference to these numbers, they can be deleted and subsequently restored with the delete and undelete commands respectively. undelete#{#\labitem#number\rab#}\\ The undelete command allows vector graphics objects which have previously been deleted from the current multiplot canvas to be restored. The item(s) which are to be restored should be identified using the reference number(s) which were used to delete them, and can be queried using the list command. The example undelete#1\\ would cause the previously deleted item numbered 1 to reappear. unset#\labsetting\rab\\ The unset command causes a configuration option which has been changed using the set command to be returned to its default value. For example: unset#linewidth\\ returns the linewidth to its default value. Any keyword which can follow the set command to identify a configuration parameter can also follow the unset command; a complete list of these can be found under the set command. while#\labcondition\rab#[#loopname#\labloopname\rab#]\\##\labcode\rab\\ The while command executes a block of commands repeatedly, checking the provided condition at the start of each iteration. If the condition is true, the loop executes again. This is similar to a do loop, except that the contents of a while loop may not be executed at all if the iteration criterion tests false upon the first iteration. For example, the following code prints out the low-valued Fibonacci numbers: i#=#1\\j#=#1\\while#(j#\lab#50)\\#{\\##print#j\\##i#=#i#+#j\\##print#i\\##j#=#j#+#i\\#}\\ pyxplot-0.9.2/src/commands/0000775000175000017500000000000012026340554014214 5ustar dcf21dcf21pyxplot-0.9.2/src/commands/funcset.h0000664000175000017500000000200612026340554016032 0ustar dcf21dcf21// funcset.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: funcset.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _FUNCSET_H #define _FUNCSET_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_funcset(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); #endif pyxplot-0.9.2/src/commands/histogram.c0000664000175000017500000005201012026340554016353 0ustar dcf21dcf21// histogram.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: histogram.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _HISTOGRAM_C 1 #include #include #include #include #include #include "commands/histogram.h" #include "coreUtils/memAlloc.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define COUNTEDERR1 if (errCount >0) { errCount--; #define COUNTEDERR2 if (errCount==0) { sprintf(c->errcontext.tempErrStr, "%s: Too many errors: no more errors will be shown.",filenameOut); ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } static int hcompare(const void *x, const void *y) { if (*((const double *)x) > *((const double *)y)) return 1.0; else if (*((const double *)x) < *((const double *)y)) return -1.0; else return 0.0; } void ppl_directive_histogram(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; dataTable *data; dataBlock *blk; long int i=0, j, k; int contextLocalVec, contextDataTab, errCount=DATAFILE_NERRS; int gotBinList, logAxis; pplFunc *funcPtr; pplObj v, firstEntry; char filenameOut[FNAME_LENGTH]=""; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX]; double *xdata; parserLine *spool=NULL, **dataSpool = &spool; histogramDescriptor *output; // Read ranges { int i,pos=PARSE_histogram_0range_list,nr=0; const int o1 = PARSE_histogram_min_0range_list; const int o2 = PARSE_histogram_max_0range_list; for (i=0; i=1) { sprintf(c->errStat.errBuff,"Too many ranges specified; only one is allowed."); TBADD2(ERR_SYNTAX,0); return; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_histogram_min_0range_list]); return; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_histogram_min_0range_list]); return; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } nr++; } } // Allocate a new memory context for the data file we're about to read contextLocalVec= ppl_memAlloc_DescendIntoNewContext(); contextDataTab = ppl_memAlloc_DescendIntoNewContext(); // Read input data { const int NcolRequired=1; int status=0, j; ppldata_fromCmd(c, &data, pl, in, 0, filenameOut, dataSpool, PARSE_TABLE_histogram_, 0, NcolRequired, 0, min, minSet, max, maxSet, unit, 0, &status, c->errStat.errBuff, &errCount, iterDepth); // Exit on error if ((status)||(data==NULL)) { TBADD2(ERR_GENERIC,0); ppl_memAlloc_AscendOutOfContext(contextLocalVec); return; } // Check that the firstEntries above have the same units as any supplied ranges for (j=0; jfirstEntries+j)) { sprintf(c->errStat.errBuff, "The minimum and maximum limits specified in range %d in the fit command have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", j+1, ppl_printUnit(c,unit+j,NULL,NULL,0,1,0), ppl_printUnit(c,data->firstEntries+j,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); return; } } // Check that we have at least three datapoints if (data->Nrows < 3) { sprintf(c->errStat.errBuff, "Histogram construction is only possible on data sets with members at at least three values of x."); TBADD2(ERR_NUMERICAL,0); return; } firstEntry = data->firstEntries[0]; } // Transfer data from multiple data tables into a single vector xdata = (double *)ppl_memAlloc_incontext(data->Nrows * sizeof(double), contextLocalVec); if (xdata==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } // Copy data table into an array of x values blk = data->first; i=0; while (blk != NULL) { for (j=0; jblockPosition; j++) xdata[i++] = blk->data_real[j]; blk=blk->next; } // Free original data table which is no longer needed ppl_memAlloc_AscendOutOfContext(contextDataTab); // Sort data vector qsort((void *)xdata, i, sizeof(double), hcompare); // Work out whether we are constructing histogram in linear space or log space gotBinList = (stk[PARSE_histogram_bin_list].objType==PPLOBJ_NUM); logAxis = ((!gotBinList) && (c->set->XAxes[1].log == SW_BOOL_TRUE)); // Read from axis x1 // Filter out any values of x which are out-of-range for (j=k=0; jmax[0]) ) continue; // Ignore out-of-range datapoints if (logAxis) { if (xdata[j]<=0.0) { COUNTEDERR1; v=firstEntry; v.real=xdata[j]; sprintf(c->errcontext.tempErrStr,"Negative or zero values are not allowed in the construction of histograms in log space; value of x=%s will be ignored.",ppl_unitsNumericDisplay(c,&v, 0, 0, 0)); ppl_warning(&c->errcontext,ERR_NUMERICAL,NULL); COUNTEDERR2; continue; } xdata[k]=log(xdata[j]); // If we're constructing histogram in log space, log data now if (!gsl_finite(xdata[k])) continue; } else { xdata[k]=xdata[j]; } k++; } // Check that we have at least three points to interpolate if (k<3) { sprintf(c->errStat.errBuff, "Histogram construction is only possible on data sets with members at at least three values of x."); TBADD2(ERR_NUMERICAL,0); return; } // Make histogramDescriptor data structure output = (histogramDescriptor *)malloc(sizeof(histogramDescriptor)); if (output == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } output->unit = firstEntry; output->log = logAxis; output->filename = (char *)malloc(strlen(filenameOut)+1); if (output->filename == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); free(output); return; } strcpy(output->filename , filenameOut); // Now need to work out what bins we're going to use if (gotBinList) { int binListLen=0, j; int pos=PARSE_histogram_bin_list; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; binListLen++; } output->bins = (double *)malloc(binListLen*sizeof(double)); if (output->bins == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); free(output); free(output->filename); return; } j=0; pos=PARSE_histogram_bin_list; while (stk[pos].objType == PPLOBJ_NUM) { pplObj *val; pos = (int)round(stk[pos].real); if (pos<=0) break; val = &stk[pos+PARSE_histogram_x_bin_list]; if (!ppl_unitsDimEqual(&firstEntry,val)) { sprintf(c->errcontext.tempErrStr, "The supplied bin boundary at x=%s has conflicting physical dimensions with the data supplied, which has units of <%s>. Ignoring this bin boundary.", ppl_printUnit(c,val,NULL,NULL,0,1,0), ppl_printUnit(c,&firstEntry,NULL,NULL,1,1,0)); ppl_warning(&c->errcontext,ERR_NUMERICAL,NULL); } else { output->bins[j++] = val->real; } } binListLen = j; // some of the bins may have been rejected output->Nbins = binListLen; qsort((void *)output->bins, binListLen, sizeof(double), hcompare); // Make sure that bins are in ascending order } else { pplObj *BinWidth, *BinOrigin, tempValObj; int BinOriginSet; double BinOriginDbl=0, BinWidthDbl, xbinmin, xbinmax; pplObj *inbinWidth = &stk[PARSE_histogram_binwidth]; pplObj *inbinOrigin = &stk[PARSE_histogram_binorigin]; xbinmin = xdata[0]; xbinmax = xdata[k-1]; if (minSet[0]) xbinmin = logAxis ? log(min[0]) : min[0]; if (maxSet[0]) xbinmax = logAxis ? log(max[0]) : max[0]; if (xbinmax < xbinmin) { double temp=xbinmax; xbinmax=xbinmin; xbinmin=temp; } if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Prior to application of BinOrigin, histogram command using range [%e:%e]",xbinmin,xbinmax); ppl_log(&c->errcontext,NULL); } if (inbinWidth->objType == PPLOBJ_NUM) { BinWidth = inbinWidth; } else if (c->set->term_current.BinWidthAuto) { BinWidth = &tempValObj; tempValObj = firstEntry; tempValObj.flagComplex = 0; tempValObj.imag = 0.0; tempValObj.real = (xbinmax-xbinmin)/100; if (logAxis) tempValObj.real = exp(tempValObj.real); } else { BinWidth = &(c->set->term_current.BinWidth); } if (inbinOrigin->objType == PPLOBJ_NUM) { BinOrigin = inbinOrigin; BinOriginSet = 1; } else { BinOrigin = &(c->set->term_current.BinOrigin); BinOriginSet = !c->set->term_current.BinOriginAuto; } if ((!logAxis) && (!ppl_unitsDimEqual(&firstEntry,BinWidth))) { sprintf(c->errStat.errBuff,"The bin width supplied to the histogram command has conflicting physical dimensions with the data supplied. The former has units of <%s>, whilst the latter has units of <%s>.", ppl_printUnit(c,BinWidth,NULL,NULL,0,1,0), ppl_printUnit(c,&firstEntry,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((logAxis) && (BinWidth->dimensionless==0)) { sprintf(c->errStat.errBuff, "For logarithmically spaced bins, the multiplicative spacing between bins must be dimensionless. The supplied spacing has units of <%s>.", ppl_printUnit(c,BinWidth,NULL,NULL,0,1,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((BinOriginSet) && (!ppl_unitsDimEqual(&firstEntry,BinOrigin))) { sprintf(c->errStat.errBuff, "The bin origin supplied to the histogram command has conflicting physical dimensions with the data supplied. The former has units of <%s>, whilst the latter has units of <%s>.", ppl_printUnit(c,BinOrigin,NULL,NULL,0,1,0), ppl_printUnit(c,&firstEntry,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((logAxis) && (BinWidth->real <= 1.0)) { sprintf(c->errStat.errBuff, "For logarithmically spaced bins, the multiplicative spacing between bins must be greater than 1.0. Value supplied was %s.", ppl_unitsNumericDisplay(c,BinWidth,0,0,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if (BinWidth->real <= 0.0) { sprintf(c->errStat.errBuff, "The bin width supplied to the histogram command must be greater than zero. Value supplied was %s.", ppl_unitsNumericDisplay(c,BinWidth,0,0,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((logAxis) && (BinOriginSet) && (BinOrigin->real <= 0.0)) { sprintf(c->errStat.errBuff, "For logarithmically spaced bins, the specified bin origin must be greater than zero. Value supplied was %s.", ppl_unitsNumericDisplay(c,BinOrigin,0,0,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((logAxis) && (minSet[0]) && (min[0] <= 0.0)) { unit[0].real=min[0]; sprintf(c->errStat.errBuff, "For logarithmically spaced bins, the specified minimum must be greater than zero. Value supplied was %s.", ppl_unitsNumericDisplay(c,&unit[0],0,0,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((logAxis) && (maxSet[0]) && (max[0] <= 0.0)) { unit[0].real=max[0]; sprintf(c->errStat.errBuff, "For logarithmically spaced bins, the specified maximum must be greater than zero. Value supplied was %s.", ppl_unitsNumericDisplay(c,&unit[0],0,0,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if ((minSet[0]||maxSet[0])&&(!ppl_unitsDimEqual(&firstEntry,&unit[0]))) { sprintf(c->errStat.errBuff, "The range supplied to the histogram command has conflicting physical dimensions with the data supplied. The former has units of <%s>, whilst the latter has units of <%s>.", ppl_printUnit(c,&unit[0],NULL,NULL,0,1,0), ppl_printUnit(c,&firstEntry,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if (!gsl_finite(BinWidth->real)) { sprintf(c->errStat.errBuff, "The bin width specified to the histogram command is not a finite number."); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if (BinOriginSet && !gsl_finite(BinOrigin->real)) { sprintf(c->errStat.errBuff, "The bin origin specified to the histogram command is not a finite number."); TBADD2(ERR_NUMERICAL,0); free(output); free(output->filename); return; } if (logAxis) { if (BinOriginSet) BinOriginDbl = log(BinOrigin->real); BinWidthDbl = log(BinWidth->real); } else { if (BinOriginSet) BinOriginDbl = BinOrigin->real ; BinWidthDbl = BinWidth->real ; } if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Histogram command using a bin width of %e and a bin origin of %e.", BinWidthDbl, BinOriginDbl); ppl_log(&c->errcontext,NULL); } // Generate a series of bins to use based on supplied BinWidth and BinOrigin if (BinOriginSet) BinOriginDbl = BinOriginDbl - BinWidthDbl * floor(BinOriginDbl / BinWidthDbl); else BinOriginDbl = 0.0; xbinmin = floor((xbinmin-BinOriginDbl)/BinWidthDbl)*BinWidthDbl + BinOriginDbl; xbinmax = ceil ((xbinmax-BinOriginDbl)/BinWidthDbl)*BinWidthDbl + BinOriginDbl; if (DEBUG) { sprintf(c->errcontext.tempErrStr, "After application of BinOrigin, histogram command using range [%e:%e]",xbinmin,xbinmax); ppl_log(&c->errcontext,NULL); } if (((xbinmax-xbinmin)/BinWidthDbl + 1.0001) > 1e7) { sprintf(c->errStat.errBuff, "The supplied value of BinWidth produces a binning scheme with more than 1e7 bins. This is probably not sensible."); TBADD2(ERR_GENERIC,0); return; } output->Nbins = (long)((xbinmax-xbinmin)/BinWidthDbl + 1.0001); if (DEBUG) { sprintf(c->errcontext.tempErrStr, "Histogram command using %ld bins",output->Nbins); ppl_log(&c->errcontext,NULL); } output->bins = (double *)malloc(output->Nbins*sizeof(double)); if (output->bins == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } for (j=0; jNbins; j++) output->bins[j] = xbinmin + j*BinWidthDbl; } // Allocate vector for storing histogram values output->binvals = (double *)malloc(output->Nbins * sizeof(double)); if (output->binvals == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); free(output->bins); return; } for (i=0; iNbins; i++) output->binvals[i]=0.0; // Count number of data values in each histogram bin i=0; for (j=0; jNbins) && (xdata[j] > output->bins[i])) i++; if (i>=output->Nbins) break; // We gone off the top of the last bin if (i==0) continue; // We've not yet arrived in the bottom bin output->binvals[i-1] += 1.0; } // If this is a logarithmic set of bins, unlog bin boundaries now if (logAxis) for (i=0; iNbins; i++) output->bins[i] = exp(output->bins[i]); // Divide each bin's number of counts by its width for (i=0; iNbins-1; i++) output->binvals[i] /= output->bins[i+1] - output->bins[i] + 1e-200; // Debugging lines if (DEBUG) for (i=0; iNbins-1; i++) { sprintf(c->errcontext.tempErrStr, "Bin %ld [%e:%e] --> %e", i+1, output->bins[i], output->bins[i+1], output->binvals[i]); ppl_log(&c->errcontext,NULL); } // Make a new function descriptor funcPtr = (pplFunc *)malloc(sizeof(pplFunc)); if (funcPtr == NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst adding histogram object to function dictionary."); TBADD2(ERR_MEMORY,0); return; } funcPtr->functionType = PPL_FUNC_HISTOGRAM; funcPtr->refCount = 1; funcPtr->minArgs = 1; funcPtr->maxArgs = 1; funcPtr->notNan = 1; funcPtr->realOnly = 1; funcPtr->numOnly = 1; funcPtr->dimlessOnly = 0; funcPtr->needSelfThis = 0; funcPtr->functionPtr = (void *)output; funcPtr->argList = NULL; funcPtr->min = funcPtr->max = NULL; funcPtr->minActive = funcPtr->maxActive = NULL; funcPtr->next = NULL; funcPtr->description = funcPtr->LaTeX = funcPtr->descriptionShort = NULL; // Supersede any previous function descriptor { int om, rc; pplObj val; pplObj *obj=NULL; ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &obj, PARSE_histogram_varnames, PARSE_histogram_varname_varnames); if ((c->errStat.status) || (obj==NULL)) return; if (obj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD2(ERR_NAMESPACE,0); return; } om = obj->amMalloced; rc = obj->refCount; obj->amMalloced = 0; obj->refCount = 1; ppl_garbageObject(obj); val.refCount=1; pplObjFunc(&val,0,1,funcPtr); pplObjCpy(obj, &val, 0, om, 1); obj->refCount = rc; } // Free copies of data vectors defined within our local context ppl_memAlloc_AscendOutOfContext(contextLocalVec); return; } void ppl_histogram_evaluate(ppl_context *c, char *FuncName, histogramDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout) { long i, Nsteps, len, ss, pos; double dblin; if (!ppl_unitsDimEqual(in, &desc->unit)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errout, "The %s(x) function expects an argument with dimensions of <%s>, but has instead received an argument with dimensions of <%s>.", FuncName, ppl_printUnit(c, &desc->unit, NULL, NULL, 0, 1, 0), ppl_printUnit(c, in, NULL, NULL, 1, 1, 0)); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } *status=1; return; } if (in->flagComplex) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errout, "The %s(x) function expects a real argument, but the supplied argument has an imaginary component.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } *status=1; return; } dblin = in->real; *out = desc->unit; out->imag = 0.0; out->real = 0.0; out->flagComplex = 0; for (i=0; iexponent[i]!=0.0) out->exponent[i]*=-1; // Output has units of 'per x' if ((desc->Nbins<1) || (dblinbins[0]) || (dblin>desc->bins[desc->Nbins-1])) return; // Query is outside range of histogram len = desc->Nbins; Nsteps = (long)ceil(log(len)/log(2)); for (pos=i=0; i=len) continue; if (desc->bins[pos+ss]<=dblin) pos+=ss; } if (desc->bins[pos]>dblin) return; // Off left end else if (pos==len-1) return; // Off right end out->real = desc->binvals[pos]; return; } pyxplot-0.9.2/src/commands/interpolate.c0000664000175000017500000006725512026340554016725 0ustar dcf21dcf21// interpolate.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: interpolate.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _FFT_C 1 #include #include #include #include #include #include #include #include "commands/interpolate.h" #include "commands/interpolate_2d_engine.h" #include "coreUtils/memAlloc.h" #include "epsMaker/bmp_bmpread.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settingTypes.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { sprintf(c->errcontext.tempErrStr,"Stack forward reference detected."); TBADD2(ERR_INTERNAL,0); return; } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define COUNTEDERR1 if (errCount >0) { errCount--; #define COUNTEDERR2 if (errCount==0) { sprintf(c->errcontext.tempErrStr, "%s: Too many errors: no more errors will be shown.",filenameOut); ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } static double *compareZeroPoint; static int interpolateSorter(const void *x, const void *y) { if ( *(compareZeroPoint + (*((long *)x))) > *(compareZeroPoint + (*((long *)y))) ) return 1; else if ( *(compareZeroPoint + (*((long *)x))) < *(compareZeroPoint + (*((long *)y))) ) return -1; else return 0; } void ppl_directive_interpolate(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth, int mode) { pplObj *stk = in->stk; dataTable *data; dataBlock *blk; bitmap_data bmpdata; long int i=0, j, k, ims, jms, sizeX=0, sizeY=0; int contextLocalVec, contextDataTab, errCount=DATAFILE_NERRS; unsigned char *bmpchars = NULL; double *xdata=NULL, *ydata=NULL, *zdata=NULL, *MinList=NULL, *MaxList=NULL; pplFunc *funcPtr; pplObj v, firstEntries[3]; int NxRequired, NcolRequired, bmp=-1; char *splineTypeName; char filenameOut[FNAME_LENGTH]=""; parserLine *spool=NULL, **dataSpool = &spool; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX]; splineDescriptor *desc; const gsl_interp_type *splineType= NULL; gsl_spline *splineObj = NULL; gsl_interp_accel *accel = NULL; // Read ranges { int i,pos=PARSE_interpolate2d_0range_list,nr=0; const int o1 = PARSE_interpolate2d_min_0range_list; const int o2 = PARSE_interpolate2d_max_0range_list; for (i=0; i=2) { sprintf(c->errStat.errBuff,"Too many ranges specified; a maximum of two are allowed."); TBADD2(ERR_SYNTAX,0); return; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_interpolate2d_min_0range_list]); return; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_interpolate2d_min_0range_list]); return; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } nr++; } } // Work out number of datapoints and columns we need for each type of interpolation if (mode == INTERP_AKIMA ) { splineType = gsl_interp_akima; NcolRequired = 2; NxRequired = 5; } else if (mode == INTERP_LINEAR ) { splineType = gsl_interp_linear; NcolRequired = 2; NxRequired = 2; } else if (mode == INTERP_LOGLIN ) { splineType = gsl_interp_linear; NcolRequired = 2; NxRequired = 2; } else if (mode == INTERP_POLYN ) { splineType = gsl_interp_polynomial; NcolRequired = 2; NxRequired = 3; } else if (mode == INTERP_SPLINE ) { splineType = gsl_interp_cspline; NcolRequired = 2; NxRequired = 3; } else if (mode == INTERP_STEPWISE) { splineType = NULL; NcolRequired = 2; NxRequired = 1; } else if (mode == INTERP_2D ) { NcolRequired = 3; NxRequired = 1; } else if (mode == INTERP_BMPR ) { bmp = 0; NcolRequired = 3; NxRequired = 1; } else if (mode == INTERP_BMPG ) { bmp = 1; NcolRequired = 3; NxRequired = 1; } else if (mode == INTERP_BMPB ) { bmp = 2; NcolRequired = 3; NxRequired = 1; } else { sprintf(c->errStat.errBuff,"interpolate command requested to perform unknown type of interpolation."); TBADD2(ERR_INTERNAL,0); return; } // Allocate a new memory context for the data file we're about to read contextLocalVec= ppl_memAlloc_DescendIntoNewContext(); contextDataTab = ppl_memAlloc_DescendIntoNewContext(); // Fetch string name of interpolation type if (mode == INTERP_AKIMA ) splineTypeName="Akima spline"; else if (mode == INTERP_LINEAR ) splineTypeName="Linear"; else if (mode == INTERP_LOGLIN ) splineTypeName="Power-law"; else if (mode == INTERP_POLYN ) splineTypeName="Polynomial"; else if (mode == INTERP_SPLINE ) splineTypeName="Cubic spline"; else if (mode == INTERP_STEPWISE) splineTypeName="Stepwise"; else if (mode == INTERP_2D ) splineTypeName="Two-dimensional"; else if (mode == INTERP_BMPR ) splineTypeName="Bitmap (red component)"; else if (mode == INTERP_BMPG ) splineTypeName="Bitmap (green component)"; else if (mode == INTERP_BMPB ) splineTypeName="Bitmap (blue component)"; else { sprintf(c->errStat.errBuff,"interpolate command requested to perform unknown type of interpolation."); TBADD2(ERR_INTERNAL,0); return; } // Read input data if (bmp<0) { int status=0; ppldata_fromCmd(c, &data, pl, in, 0, filenameOut, dataSpool, PARSE_TABLE_interpolate2d_, 0, NcolRequired, 0, min, minSet, max, maxSet, unit, 0, &status, c->errStat.errBuff, &errCount, iterDepth); // Exit on error if ((status)||(data==NULL)) { TBADD2(ERR_GENERIC,0); ppl_memAlloc_AscendOutOfContext(contextLocalVec); return; } // Check that the firstEntries above have the same units as any supplied ranges for (j=0; jfirstEntries+j)) { sprintf(c->errStat.errBuff, "The minimum and maximum limits specified in range %ld in the fit command have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", j+1, ppl_printUnit(c,unit+j,NULL,NULL,0,1,0), ppl_printUnit(c,data->firstEntries+j,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); return; } } // Transfer data from multiple data tables into single vectors if ((NcolRequired<3)&&(mode!=INTERP_STEPWISE)) xdata = (double *)ppl_memAlloc_incontext(NcolRequired * (data->Nrows+2) * sizeof(double), contextLocalVec); else xdata = (double *)malloc (NcolRequired * (data->Nrows+2) * sizeof(double)); if (xdata==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } ydata = xdata + data->Nrows; zdata = xdata + 2*data->Nrows; MinList = xdata + NcolRequired* data->Nrows; MaxList = xdata + NcolRequired*(data->Nrows+1); // Copy data table into an array of x values, and an array of y values blk = data->first; i=0; while (blk != NULL) { k=i; for (j=0; jblockPosition; j++) xdata[i++] = blk->data_real[0 + NcolRequired*j]; i=k; for (j=0; jblockPosition; j++) ydata[i++] = blk->data_real[1 + NcolRequired*j]; if (NcolRequired>2) { i=k; for (j=0; jblockPosition; j++) zdata[i++] = blk->data_real[2 + NcolRequired*j]; } blk=blk->next; } // Check that we have at least minimum number of points to interpolate if (ierrStat.errBuff,"%s interpolation is only possible on data sets with at least %d member%s.",splineTypeName,NxRequired,(NxRequired>1)?"s":""); TBADD2(ERR_NUMERICAL,0); if (NcolRequired>=3) free(xdata); return; } // Fill out minimum and maximum of data for (jms=0; jmsxdata[jms*data->Nrows+ims])) MinList[jms] = xdata[jms*data->Nrows+ims]; if ((ims==0)||(MaxList[jms]Nrows+ims])) MaxList[jms] = xdata[jms*data->Nrows+ims]; } if (MaxList[jms]<=MinList[jms]) { double t=MinList[jms]; MinList[jms]=t*0.999; MaxList[jms]=t*1.001; } } firstEntries[0] = data->firstEntries[0]; firstEntries[1] = data->firstEntries[1]; if (NcolRequired>2) firstEntries[2] = data->firstEntries[2]; } else // Read data from bmp file { int i,j; long p; unsigned char buff[10]; int pos = PARSE_interpolate2d_expression_list; FILE *infile; for (i=0; i<2; i++) if ( minSet[i] || maxSet[i] ) { sprintf(c->errStat.errBuff, "Ranges cannot be applied when interpolating bitmap data."); TBADD2(ERR_NUMERICAL,0); return; } // Fetch filename of bitmap image if ( (stk[pos].objType!=PPLOBJ_NUM) || (pos=(int)round(stk[pos].real) , stk[pos].objType==PPLOBJ_NUM) ) { sprintf(c->errStat.errBuff, "A single filename must be supplied when interpolating a bitmap image."); TBADD2(ERR_SYNTAX,0); return; } { const int stkLevelOld = c->stackPtr; int i; pplExpr *expr = (pplExpr *)stk[pos+PARSE_interpolate2d_expression_expression_list].auxil; pplObj *first = ppl_expEval(c, expr, &i, 0, iterDepth); if ((c->errStat.status) || (first->objType!=PPLOBJ_STR)) { STACK_CLEAN; sprintf(c->errStat.errBuff, "A single filename must be supplied when interpolating a bitmap image."); TBADD2(ERR_SYNTAX,0); return; } strcpy(filenameOut, (char *)first->auxil); STACK_CLEAN; } // glob filename { wordexp_t wordExp; glob_t globData; char escaped[FNAME_LENGTH]; { int j,k; for (j=k=0; ((filenameOut[j]!='\0')&&(kerrStat.errBuff, "Could not open file '%s'.", escaped); TBADD2(ERR_FILE,0); return; } if ((glob(wordExp.we_wordv[0], 0, NULL, &globData) != 0) || (globData.gl_pathc <= 0)) { sprintf(c->errStat.errBuff, "Could not open file '%s'.", escaped); TBADD2(ERR_FILE,0); wordfree(&wordExp); return; } wordfree(&wordExp); snprintf(filenameOut, FNAME_LENGTH, "%s", globData.gl_pathv[0]); filenameOut[FNAME_LENGTH-1]='\0'; globfree(&globData); } infile = fopen(filenameOut, "r"); if (infile==NULL) { sprintf(c->errStat.errBuff, "Could not open input file '%s'", filenameOut); TBADD2(ERR_FILE,0); return; } for (i=0; i<3; i++) // Use magic to determine file type { j = fgetc(infile); if (j==EOF) { sprintf(c->errStat.errBuff, "Could not read any image data from the input file '%s'", filenameOut); TBADD2(ERR_FILE,0); fclose(infile); return; } buff[i] = (unsigned char)j; } if ((buff[0]!='B')&&(buff[1]!='M')) { sprintf(c->errStat.errBuff, "File '%s' does not appear to be a valid bitmap image.", filenameOut); TBADD2(ERR_FILE,0); fclose(infile); return; } ppl_bmp_bmpread(&c->errcontext, infile, &bmpdata); if (bmpdata.data == NULL) { sprintf(c->errStat.errBuff, "Reading of bitmap image data failed"); TBADD2(ERR_GENERIC,0); return; } pplObjNum(&firstEntries[0],0,0,0); firstEntries[0].refCount=1; pplObjNum(&firstEntries[1],0,0,0); firstEntries[1].refCount=1; pplObjNum(&firstEntries[2],0,0,0); firstEntries[2].refCount=1; sizeX = bmpdata.width; sizeY = bmpdata.height; bmpchars = (unsigned char *)malloc(sizeX*sizeY); if (bmpchars==NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst reading data from input file."); TBADD2(ERR_MEMORY,0); return; } if (bmpdata.colour == BMP_COLOUR_RGB) // RGB image { for (p=0; perrStat.errBuff, "The minimum and maximum limits specified in the interpolate command for the x axis have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", ppl_printUnit(c,unit+0,NULL,NULL,0,1,0), ppl_printUnit(c,firstEntries+0,NULL,NULL,1,1,0)); TBADD2(ERR_UNIT,0); return; } } if (minSet[1] || maxSet[1]) { if (!ppl_unitsDimEqual(unit+1,firstEntries+1)) { sprintf(c->errStat.errBuff, "The minimum and maximum limits specified in the interpolate command for the y axis have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", ppl_printUnit(c,unit+1,NULL,NULL,0,1,0), ppl_printUnit(c,firstEntries+1,NULL,NULL,1,1,0)); TBADD2(ERR_UNIT,0); return; } } // Free original data table which is no longer needed ppl_memAlloc_AscendOutOfContext(contextDataTab); // Sort data vectors according to x values { long int *sortArray = (long int *)ppl_memAlloc(2 * i * sizeof(long int)); long int *sortArrayI= sortArray + i; long int j; if (sortArray==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } for (j=0; jmax[0]) ) continue; // Ignore out-of-range datapoints if ( (minSet[1]) && (ydata[j]max[1]) ) continue; // Ignore out-of-range datapoints if ((j>0) && (xdata[j]==xdata[j-1])) { COUNTEDERR1; v=firstEntries[0]; v.real=xdata[j]; sprintf(c->errcontext.tempErrStr,"Repeat values for interpolation have been supplied at x=%s.",ppl_unitsNumericDisplay(c, &v, 0, 0, 0)); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); COUNTEDERR2; continue; } if (mode == INTERP_LOGLIN) { if ((xdata[j]<=0.0) || (ydata[j]<=0.0)) { COUNTEDERR1; v=firstEntries[0]; v.real=xdata[j]; sprintf(c->errcontext.tempErrStr,"Negative or zero values are not allowed in power-law interpolation; negative values supplied at x=%s will be ignored.",ppl_unitsNumericDisplay(c, &v, 0, 0, 0)); ppl_warning(&c->errcontext, ERR_NUMERICAL, NULL); COUNTEDERR2; continue; } xdata[k]=log(xdata[j]); ydata[k]=log(ydata[j]); if ( (!gsl_finite(xdata[k])) || (!gsl_finite(ydata[k])) ) continue; } else { xdata[k]=xdata[j]; ydata[k]=ydata[j]; } k++; } // Check that we have at least minimum number of points to interpolate if (kerrStat.errBuff,"%s interpolation is only possible on data sets with members at at least %d distinct values of x.",splineTypeName,NxRequired); TBADD2(ERR_NUMERICAL,0); if (NcolRequired>=3) free(xdata); return; } // Create GSL interpolation object if (splineType!=NULL) { int status=0; splineObj = gsl_spline_alloc(splineType, k); accel = gsl_interp_accel_alloc(); if (splineObj==NULL) { sprintf(c->errStat.errBuff,"Failed to make interpolation object."); TBADD2(ERR_INTERNAL,0); return; } if (accel ==NULL) { sprintf(c->errStat.errBuff,"Failed to make GSL interpolation accelerator."); TBADD2(ERR_MEMORY,0); return; } status = gsl_spline_init(splineObj, xdata, ydata, k); if (status) { sprintf(c->errStat.errBuff,"Error whilst creating interpolation object: %s", gsl_strerror(status)); TBADD2(ERR_INTERNAL,0); return; } } else { splineObj = (gsl_spline *)xdata; sizeX = k; sizeY = i; } } else if (bmp<0) // 2D interpolation { splineObj = (gsl_spline *)xdata; sizeX = i; } else // bitmap interpolation { splineObj = (gsl_spline *)bmpchars; } // Generate a function descriptor for this spline desc = (splineDescriptor *)malloc(sizeof(splineDescriptor)); if (desc == NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst adding interpolation object to function dictionary."); TBADD2(ERR_MEMORY,0); return; } desc->unitX = firstEntries[0]; desc->unitY = firstEntries[1]; desc->unitZ = firstEntries[2]; desc->sizeX = sizeX; desc->sizeY = sizeY; desc->logInterp = (mode == INTERP_LOGLIN); desc->splineObj = splineObj; desc->accelerator = accel; desc->filename = (char *)malloc(strlen(filenameOut)+1); if (desc->filename == NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst adding interpolation object to function dictionary."); TBADD2(ERR_MEMORY,0); return; } strcpy(desc->filename, filenameOut); desc->splineType = splineTypeName; // Make a new function descriptor funcPtr = (pplFunc *)malloc(sizeof(pplFunc)); if (funcPtr == NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst adding interpolation object to function dictionary."); TBADD2(ERR_MEMORY,0); return; } if (NcolRequired==2) funcPtr->functionType = PPL_FUNC_SPLINE; else if (bmp<0 ) funcPtr->functionType = PPL_FUNC_INTERP2D; else funcPtr->functionType = PPL_FUNC_BMPDATA; funcPtr->refCount = 1; funcPtr->minArgs = NcolRequired-1; funcPtr->maxArgs = NcolRequired-1; funcPtr->notNan = 1; funcPtr->realOnly = 1; funcPtr->numOnly = 1; funcPtr->dimlessOnly = 0; funcPtr->needSelfThis = 0; funcPtr->functionPtr = (void *)desc; funcPtr->argList = NULL; funcPtr->min = funcPtr->max = NULL; funcPtr->minActive = funcPtr->maxActive = NULL; funcPtr->next = NULL; funcPtr->description = funcPtr->LaTeX = funcPtr->descriptionShort = NULL; // Supersede any previous function descriptor { int om, rc; pplObj val; pplObj *obj=NULL; ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &obj, PARSE_interpolate2d_varnames, PARSE_interpolate2d_varname_varnames); if ((c->errStat.status) || (obj==NULL)) return; if (obj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD2(ERR_NAMESPACE,0); return; } om = obj->amMalloced; rc = obj->refCount; obj->amMalloced = 0; obj->refCount = 1; ppl_garbageObject(obj); val.refCount=1; pplObjFunc(&val,0,1,funcPtr); pplObjCpy(obj, &val, 0, om, 1); obj->refCount = rc; } // Free copies of data vectors defined within our local context ppl_memAlloc_AscendOutOfContext(contextLocalVec); return; } void ppl_spline_evaluate(ppl_context *c, char *FuncName, splineDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout) { double dblin, dblout; if (!ppl_unitsDimEqual(in, &desc->unitX)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x) function expects an argument with dimensions of <%s>, but has instead received an argument with dimensions of <%s>.", FuncName, ppl_printUnit(c, &desc->unitX, NULL, NULL, 0, 1, 0), ppl_printUnit(c, in, NULL, NULL, 1, 1, 0)); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } if (in->flagComplex) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x) function expects a real argument, but the supplied argument has an imaginary component.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } // If loglinear interpolation, log input value dblin = in->real; if (desc->logInterp) dblin = log(dblin); if (desc->splineType[1]!='t') // Not stepwise interpolation { *status = gsl_spline_eval_e(desc->splineObj, dblin, desc->accelerator, &dblout); } else // Stepwise interpolation { long i, pos, ss, len=desc->sizeX, xystep=desc->sizeY, Nsteps = (long)ceil(log(desc->sizeX)/log(2)); double *data = (double *)desc->splineObj; for (pos=i=0; i=len) continue; if (data[pos+ss]<=dblin) pos+=ss; } if (data[pos]>dblin) dblout=data[pos +xystep]; // Off left end else if (pos==len-1) dblout=data[pos +xystep]; // Off right end else if (fabs(dblin-data[pos])set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "Error whilst evaluating the %s(x) function: %s", FuncName, gsl_strerror(*status)); } else { *status=0; pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } // If loglinear interpolation, unlog output value if (desc->logInterp) dblout = exp(dblout); if (!gsl_finite(dblout)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "Error whilst evaluating the %s(x) function: result was not a finite number.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } // Return output pplObjNum(out,0,0,0); out->real = dblout; ppl_unitsDimCpy(out, &desc->unitY); return; } void ppl_interp2d_evaluate(ppl_context *c, const char *FuncName, splineDescriptor *desc, const pplObj *in1, const pplObj *in2, const unsigned char bmp, pplObj *out, int *status, char *errout) { double dblin1, dblin2, dblout; if (!ppl_unitsDimEqual(in1, &desc->unitX)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x,y) function expects its first argument to have dimensions of <%s>, but has instead received an argument with dimensions of <%s>.", FuncName, ppl_printUnit(c, &desc->unitX, NULL, NULL, 0, 1, 0), ppl_printUnit(c, in1, NULL, NULL, 1, 1, 0)); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } if (in1->flagComplex) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x,y) function expects real arguments, but first supplied argument has an imaginary component.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } if (!ppl_unitsDimEqual(in2, &desc->unitY)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x,y) function expects its second argument to have dimensions of <%s>, but has instead received an argument with dimensions of <%s>.", FuncName, ppl_printUnit(c, &desc->unitY, NULL, NULL, 0, 1, 0), ppl_printUnit(c, in2, NULL, NULL, 1, 1, 0)); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } if (in2->flagComplex) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "The %s(x,y) function expects real arguments, but second supplied argument has an imaginary component.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } dblin1 = in1->real; dblin2 = in2->real; if (!bmp) { ppl_interp2d_eval(c, &dblout, &c->set->graph_current, (double *)desc->splineObj, desc->sizeX, 2, 3, dblin1, dblin2); } else { int x = floor(dblin1); int y = floor(dblin2); if ((x<0) || (x>=desc->sizeX) || (y<0) || (y>=desc->sizeY)) dblout = GSL_NAN; else dblout = ((double)(((unsigned char *)desc->splineObj)[x+y*desc->sizeX]))/255.0; } if (!gsl_finite(dblout)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { *status=1; sprintf(errout, "Error whilst evaluating the %s(x,y) function: result was not a finite number.", FuncName); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } return; } // Return output pplObjNum(out,0,0,0); out->real = dblout; ppl_unitsDimCpy(out, &desc->unitZ); return; } pyxplot-0.9.2/src/commands/show.c0000664000175000017500000024477212026340554015360 0ustar dcf21dcf21// show.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: show.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include "commands/show.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/arrows_fns.h" #include "settings/axes_fns.h" #include "settings/epsColors.h" #include "settings/labels_fns.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "canvasItems.h" #include "pplConstants.h" #define SHOW_HIGHLIGHT(modified) \ if (interactive!=0) /* On interactive sessions, highlight those settings which have been manually set by the user */ \ { \ if (modified == 0) strcpy(out+i, *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_wrn , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)) ); \ else strcpy(out+i, *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_rep , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)) ); \ i += strlen(out+i); \ } #define SHOW_DEHIGHLIGHT \ if (interactive!=0) /* On interactive sessions, highlight those settings which have been manually set by the user */ \ { \ strcpy(out+i, *(char **)ppl_fetchSettingName(&c->errcontext, SW_TERMCOL_NOR , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)) ); \ i += strlen(out+i); \ } \ #define SHOW_TICKS(T,TD,U,UD,amLog,amLogD,A,B) \ sprintf(buf2, "Sets where the major ticks are placed along the %c%d axis, and how they appear", A, B); \ sprintf(buf, "%s ", *(char **)ppl_fetchSettingName(&c->errcontext, T.tickDir, SW_TICDIR_INT, SW_TICDIR_STR , sizeof(char *))); m = strlen(buf); \ if ((!T.tickStepSet) && (T.tickList == NULL)) \ { \ sprintf(buf+m, "autofreq"); \ } \ else if (T.tickList == NULL) \ { \ if (T.tickMinSet) \ { \ U.real = T.tickMin; \ sprintf(buf+m, "%s", ppl_unitsNumericDisplay(c,&(U),0,0,0)); m += strlen(buf+m); \ } \ if (T.tickStepSet) \ { \ U.real = T.tickStep; \ if (amLog==SW_BOOL_FALSE) sprintf(buf+m, "%s%s", (T.tickMinSet)?", ":"", ppl_unitsNumericDisplay(c,&(U),0,0,0)); \ else sprintf(buf+m, "%s%s", (T.tickMinSet)?", ":"", ppl_numericDisplay(T.tickStep,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); \ m += strlen(buf+m); \ } \ if (T.tickMaxSet) \ { \ U.real = T.tickMax; \ sprintf(buf+m, ", %s", ppl_unitsNumericDisplay(c,&(U),0,0,0)); m += strlen(buf+m); \ } \ } \ else \ { \ buf[m++]='('; \ for (n=0; T.tickStrs[n]!=NULL; n++) \ { \ strcpy(buf+m, (n==0)?"":", "); m += strlen(buf+m); \ U.real = T.tickList[n]; \ sprintf(buf+m, "%s", ppl_unitsNumericDisplay(c,&(U),0,0,0)); \ m += strlen(buf+m); \ if (T.tickStrs[n][0]!='\xFF') { buf[m++]=' '; buf[m]='\0'; ppl_strEscapify(T.tickStrs[n], buf+m); m += strlen(buf+m); } \ } \ sprintf(buf+m, ")"); \ } \ ppl_directive_show3(c, out+i, itemSet, 1, interactive, temp1, buf, (T.tickDir == TD.tickDir) && (pplaxis_cmpTics(c, &T, &TD, &U, &UD, amLog, amLogD)), buf2); static void ppl_directive_show3(ppl_context *c, char *out, char *itemSet, unsigned char itemSetShow, int interactive, char *setting_name, char *setting_value, int modified, char *description) { int i=0,j,k; SHOW_HIGHLIGHT(modified); sprintf(out+i, "set %*s", (int)strlen(itemSet), itemSetShow ? itemSet : ""); i += strlen(out+i); // Start off with a set command if (strcmp(setting_value, "on")==0) { sprintf(out+i, "%-41s", setting_name); i += strlen(out+i); } else if (strcmp(setting_value, "off")==0) { for (j=0,k=-1; setting_name[j]!='\0'; j++) if (setting_name[j]==' ') k=j; // Find last space in setting name for (j=0; j<=k; j++) out[i+j] = setting_name[j]; out[i+k+1] = 'n'; out[i+k+2] = 'o'; // Insert 'no' after this space for (j=k+1; setting_name[j]!='\0'; j++) out[i+j+2] = setting_name[j]; for (; j<39; j++) out[i+j+2] = ' '; // Pad with spaces up to 45 characters out[i+j+2] = '\0'; i += strlen(out+i); } else { sprintf(out+i, "%-16s %-24s", setting_name, setting_value); i += strlen(out+i); } if (description!=NULL) { sprintf(out+i, " # %s.", description); i += strlen(out+i); } // Finally put a decriptive comment after the setting strcpy(out+i, "\n"); i += strlen(out+i); // and a linefeed SHOW_DEHIGHLIGHT; return; } static int ppl_directive_show2(ppl_context *c, char *word, char *itemSet, int interactive, pplset_graph *sg, pplarrow_object **al, ppllabel_object **ll, pplset_axis *xa, pplset_axis *ya, pplset_axis *za) { char *out, *buf, *buf2, *bufp, *bufp2, temp1[32], temp2[32]; int i=0, p=0,j,k,l,m,n; unsigned char unchanged; unit *ud = c->unit_database; int outLen = 8*LSTR_LENGTH; out = (char *)ppl_memAlloc(outLen ); // Accumulate our whole output text here buf = (char *)ppl_memAlloc(LSTR_LENGTH ); // Put the value of each setting in here buf2= (char *)ppl_memAlloc(FNAME_LENGTH); if ((out==NULL)||(buf==NULL)||(buf2==NULL)) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory whilst trying to allocate buffers in show command."); if (out!=NULL) free(out); if (buf!=NULL) free(buf); if (buf2!=NULL) free(buf2); return 1; } out[0] = buf[0] = '\0'; if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "axescolour",1)>=0) || (ppl_strAutocomplete(word, "axescolor",1)>=0)) { #define S_RGB(X,Y) ppl_numericDisplay(X,c->numdispBuff[Y],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L)) #define SHOW_COLOR(COLOR,COL1234SPACE,COL1,COL2,COL3,COL4 , DEFAULT,DEF1234SPACE,DEF1,DEF2,DEF3,DEF4 , NAME1, NAME2) \ { \ if (COLOR>0) sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, COLOR, SW_COLOR_INT, SW_COLOR_STR , sizeof(char *))); \ else if (COL1234SPACE==SW_COLSPACE_RGB ) sprintf(buf, "rgb(%s,%s,%s)", S_RGB(COL1,0), S_RGB(COL2,1), S_RGB(COL3,2)); \ else if (COL1234SPACE==SW_COLSPACE_HSB ) sprintf(buf, "hsb(%s,%s,%s)", S_RGB(COL1,0), S_RGB(COL2,1), S_RGB(COL3,2)); \ else if (COL1234SPACE==SW_COLSPACE_CMYK) sprintf(buf, "cmyk(%s,%s,%s,%s)", S_RGB(COL1,0), S_RGB(COL2,1), S_RGB(COL3,2), S_RGB(COL4,3)); \ ppl_directive_show3(c, out+i, itemSet, 1, interactive, NAME1, buf, ((COLOR==DEFAULT)&&(COL1234SPACE==DEF1234SPACE)&&(COL1==DEF1)&&(COL2==DEF2)&&(COL3==DEF3)&&(COL4==DEF4)), NAME2); \ } SHOW_COLOR(sg->AxesColor,sg->AxesCol1234Space,sg->AxesColor1,sg->AxesColor2,sg->AxesColor3,sg->AxesColor4 , c->set->graph_default.AxesColor,c->set->graph_default.AxesCol1234Space,c->set->graph_default.AxesColor1,c->set->graph_default.AxesColor2,c->set->graph_default.AxesColor3,c->set->graph_default.AxesColor4 , "axesColor", "The color used to draw graph axes"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "axisunitstyle", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->AxisUnitStyle, SW_AXISUNITSTY_INT, SW_AXISUNITSTY_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "axisUnitStyle", buf, (c->set->graph_default.AxisUnitStyle == sg->AxisUnitStyle), "Select how the physical units associated with axes are appended to axis labels"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "backup", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.backup, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "backup", buf, (c->set->term_default.backup == c->set->term_current.backup), "Selects whether existing files are overwritten (nobackup) or moved (backup)"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "bar",1)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(sg->bar,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "bar", buf, (c->set->graph_default.bar == sg->bar), "Sets the size of the strokes which mark the lower and upper limits of errorbars"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "binorigin",1)>=0)) { bufp = "Used to control the exact position of the edges of the bins used by the histogram command"; if (c->set->term_current.BinOriginAuto) { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "binOrigin", "auto", c->set->term_current.BinOriginAuto==c->set->term_default.BinOriginAuto, bufp); } else { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "binOrigin", ppl_unitsNumericDisplay(c,&(c->set->term_current.BinOrigin),0,0,0), (c->set->term_current.BinOriginAuto==c->set->term_default.BinOriginAuto) && ppl_dblEqual( c->set->term_default.BinOrigin.real , c->set->term_current.BinOrigin.real) && ppl_dblEqual( c->set->term_default.BinOrigin.imag , c->set->term_current.BinOrigin.imag) && ppl_unitsDimEqual(&c->set->term_default.BinOrigin ,&c->set->term_current.BinOrigin ) , bufp ); } i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "binwidth",1)>=0)) { bufp = "Sets the width of bins used by the histogram command"; if (c->set->term_current.BinWidthAuto) { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "binWidth", "auto", c->set->term_current.BinWidthAuto==c->set->term_default.BinWidthAuto, bufp); } else { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "binWidth", ppl_unitsNumericDisplay(c,&(c->set->term_current.BinWidth),0,0,0), (c->set->term_current.BinWidthAuto==c->set->term_default.BinWidthAuto) && ppl_dblEqual( c->set->term_default.BinWidth.real , c->set->term_current.BinWidth.real) && ppl_dblEqual( c->set->term_default.BinWidth.imag , c->set->term_current.BinWidth.imag) && ppl_unitsDimEqual(&c->set->term_default.BinWidth ,&c->set->term_current.BinWidth ) , bufp ); } i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "boxfrom",1)>=0)) { bufp = "Sets the vertical level from which the bars of barcharts and histograms are drawn"; if (sg->BoxFromAuto) { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "boxFrom", "auto", sg->BoxFromAuto==c->set->graph_default.BoxFromAuto, bufp); } else { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "boxFrom", ppl_unitsNumericDisplay(c,&(sg->BoxFrom),0,0,0), (sg->BoxFromAuto==c->set->graph_default.BoxFromAuto) && ppl_dblEqual( c->set->graph_default.BoxFrom.real , sg->BoxFrom.real) && ppl_dblEqual( c->set->graph_default.BoxFrom.imag , sg->BoxFrom.imag) && ppl_unitsDimEqual(&c->set->graph_default.BoxFrom ,&sg->BoxFrom ) , bufp ); } i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "boxwidth",1)>=0)) { bufp = "Sets the width of bars on barcharts and histograms"; if (sg->BoxWidthAuto) { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "boxWidth", "auto", sg->BoxWidthAuto==c->set->graph_default.BoxWidthAuto, bufp); } else { ppl_directive_show3(c, out+i, itemSet, 0, interactive, "boxWidth", ppl_unitsNumericDisplay(c,&(sg->BoxWidth),0,0,0), (sg->BoxWidthAuto==c->set->graph_default.BoxWidthAuto) && ppl_dblEqual( c->set->graph_default.BoxWidth.real , sg->BoxWidth.real) && ppl_dblEqual( c->set->graph_default.BoxWidth.imag , sg->BoxWidth.imag) && ppl_unitsDimEqual(&c->set->graph_default.BoxWidth ,&sg->BoxWidth ) , bufp ); } i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c1format",1)>=0)) { pplExpr *c1format_current = (pplExpr *)sg->c1format; pplExpr *c1format_default = (pplExpr *)c->set->graph_default.c1format; if (sg->c1formatset) sprintf(buf, "%s ", c1format_current->ascii); else buf[0]='\0'; m = strlen(buf); sprintf(buf+m, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->c1TickLabelRotation, SW_TICLABDIR_INT, SW_TICLABDIR_STR , sizeof(char *))); m += strlen(buf+m); if (sg->c1TickLabelRotation == SW_TICLABDIR_ROT) { pplObj valobj; valobj.refCount=1; pplObjNum(&valobj,0,sg->c1TickLabelRotate,0); valobj.exponent[UNIT_ANGLE] = 1; valobj.dimensionless = 0; sprintf(buf+m, " %s", ppl_unitsNumericDisplay(c,&valobj,0,0,0)); } ppl_directive_show3(c, out+i, itemSet, 1, interactive, "c1format", buf, ( ( sg->c1TickLabelRotate == c->set->graph_default.c1TickLabelRotate ) && ( sg->c1TickLabelRotation == c->set->graph_default.c1TickLabelRotation) && ( sg->c1formatset == c->set->graph_default.c1formatset ) && ((!sg->c1formatset) || (strcmp(c1format_current->ascii,c1format_default->ascii)==0)) ) , "Format string for the tick labels on the c1 axis"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c1label",1)>=0)) { pplObj valobj; valobj.refCount=1; ppl_strEscapify(sg->c1label , buf); m = strlen(buf); pplObjNum(&valobj,0,sg->c1LabelRotate,0); valobj.exponent[UNIT_ANGLE] = 1; valobj.dimensionless = 0; sprintf(buf+m, " rotate %s", ppl_unitsNumericDisplay(c,&valobj,0,0,0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "c1label", buf, ( ( sg->c1LabelRotate == c->set->graph_default.c1LabelRotate) && ( strcmp(sg->c1label,c->set->graph_default.c1label)==0) ) , "Textual label for the c1 axis"); i += strlen(out+i) ; p=1; } { int showMinor = 0; if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c1tics",1)>=0)) { sprintf(temp1, "c1tics"); SHOW_TICKS(sg->ticsC , c->set->graph_default.ticsC , sg->unitC, c->set->graph_default.unitC, sg->Clog[0], c->set->graph_default.Clog[0], 'c', 1); i += strlen(out+i) ; p=1; showMinor=1; // If we've shown major tics, also show minor ticks too. } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "mc1tics",1)>=0) || showMinor) { sprintf(temp1, "mc1tics"); SHOW_TICKS(sg->ticsCM, c->set->graph_default.ticsCM, sg->unitC, c->set->graph_default.unitC, sg->Clog[0], c->set->graph_default.Clog[0], 'c', 1); i += strlen(out+i) ; p=1; } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "calendarin",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.CalendarIn, SW_CALENDAR_INT, SW_CALENDAR_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "calendarIn", buf, (c->set->term_current.CalendarIn == c->set->term_default.CalendarIn), "Selects the historical year in which the transition is made between Julian and Gregorian calendars when dates are being input"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "calendarout",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.CalendarOut, SW_CALENDAR_INT, SW_CALENDAR_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "calendarOut", buf, (c->set->term_current.CalendarOut == c->set->term_default.CalendarOut), "Selects the historical year in which the transition is made between Julian and Gregorian calendars when displaying dates"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "clip",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->clip, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "clip", buf, (sg->clip == c->set->graph_default.clip), "Selects whether point symbols which extend over the axes of graphs are allowed to do so, or are clipped at the edges"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "colkey",1)>=0) || (ppl_strAutocomplete(word, "colourkey",1)>=0) || (ppl_strAutocomplete(word, "colorkey",1)>=0)) { if (sg->ColKey == SW_ONOFF_OFF) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->ColKey, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); } else { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->ColKeyPos, SW_COLKEYPOS_INT, SW_COLKEYPOS_STR , sizeof(char *))); } ppl_directive_show3(c, out+i, itemSet, 1, interactive, "colkey", buf, (c->set->graph_default.ColKey == sg->ColKey)&&((sg->ColKey==SW_ONOFF_OFF)||(c->set->graph_default.ColKeyPos == sg->ColKeyPos)), "Selects whether a color scale is included on colormap plots"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "colmap",1)>=0) || (ppl_strAutocomplete(word, "colourmap",1)>=0) || (ppl_strAutocomplete(word, "colormap",1)>=0)) { pplExpr *exp_default = (pplExpr *)c->set->graph_default.ColMapExpr; pplExpr *exp_current = (pplExpr *)sg->ColMapExpr; pplExpr *maskdefault = (pplExpr *)c->set->graph_default.MaskExpr; pplExpr *maskcurrent = (pplExpr *)sg->MaskExpr; int k; int unchanged = ((exp_default==NULL)==(exp_current==NULL)) && ((exp_default==NULL)||(strcmp(exp_default->ascii,exp_current->ascii)==0)) && ((maskdefault==NULL)==(maskcurrent==NULL)) && ((maskdefault==NULL)||(strcmp(maskdefault->ascii,maskcurrent->ascii)==0)); if (exp_current != NULL) sprintf(buf, "%s", exp_current->ascii); else sprintf(buf, "rgb(c1,c1,c1)"); k =strlen(buf); if (maskcurrent==NULL) sprintf(buf+k, " nomask"); else sprintf(buf+k, " mask %s", maskcurrent->ascii); k+=strlen(buf+k); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "colmap", buf, unchanged, "The mapping of ordinate value to color used by the colormap plot style"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "contours",1)>=0)) { if (sg->ContoursListLen < 0) { sprintf(buf, "%d %slabel", sg->ContoursN, (sg->ContoursLabel==SW_ONOFF_ON)?"":"no"); } else { int p,q; pplObj v = sg->ContoursUnit; sprintf(buf, "("); p=strlen(buf); for (q=0; qContoursListLen; q++) { if (q!=0) { sprintf(buf+p, ", "); p+=strlen(buf+p); } v.real = sg->ContoursList[q]; sprintf(buf+p, "%s", ppl_unitsNumericDisplay(c,&v, 0, 0, 0)); p+=strlen(buf+p); } sprintf(buf+p, ") %slabel", (sg->ContoursLabel==SW_ONOFF_ON)?"":"no"); p+=strlen(buf+p); } ppl_directive_show3(c, out+i, itemSet, 1, interactive, "contour", buf, (c->set->graph_default.ContoursN==sg->ContoursN)&&(c->set->graph_default.ContoursLabel==sg->ContoursLabel)&&(c->set->graph_default.ContoursListLen==sg->ContoursListLen)&&ppl_unitsDimEqual(&c->set->graph_default.ContoursUnit,&sg->ContoursUnit)&&((sg->ContoursListLen<0)||(memcmp((void *)c->set->graph_default.ContoursList,(void *)sg->ContoursList,sg->ContoursListLen*sizeof(double))==0)), "The number of contours drawn by the contourmap plot style"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c1range",1)>=0)) { #define SHOW_CRANGE(C,X) \ sprintf(buf, "[%s:%s] %s %s", (sg->Cminauto[C]==SW_BOOL_TRUE) ? "*" : ppl_unitsNumericDisplay(c,&(sg->Cmin[C]), 0, 0, 0), \ (sg->Cmaxauto[C]==SW_BOOL_TRUE) ? "*" : ppl_unitsNumericDisplay(c,&(sg->Cmax[C]), 1, 0, 0), \ (sg->Crenorm [C]==SW_BOOL_TRUE) ? "renormalise" : "norenormalise", \ (sg->Creverse[C]==SW_BOOL_TRUE) ? "reverse" : "noreverse" ); \ ppl_directive_show3(c, out+i, itemSet, 1, interactive, "c" X "range", buf, (c->set->graph_default.Cminauto[C]==sg->Cminauto[C])&&(c->set->graph_default.Cmaxauto[C]==sg->Cmaxauto[C])&&((sg->Cminauto[C]==SW_BOOL_TRUE)||((c->set->graph_default.Cmin[C].real==sg->Cmin[C].real)&&ppl_unitsDimEqual(&(c->set->graph_default.Cmin[C]),&(sg->Cmin[C]))))&&((sg->Cmaxauto[C]==SW_BOOL_TRUE)||((c->set->graph_default.Cmax[C].real==sg->Cmax[C].real)&&ppl_unitsDimEqual(&(c->set->graph_default.Cmax[C]),&(sg->Cmax[C]))))&&(c->set->graph_default.Crenorm[C]==sg->Crenorm[C])&&(c->set->graph_default.Creverse[C]==sg->Creverse[C]), "The range of values represented by different colors in the colormap plot style, and by contours in the contourmap plot style"); \ i += strlen(out+i) ; p=1; SHOW_CRANGE(0,"1"); } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c2range",1)>=0)) { SHOW_CRANGE(1,"2"); } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c3range",1)>=0)) { SHOW_CRANGE(2,"3"); } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "c4range",1)>=0)) { SHOW_CRANGE(3,"4"); } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "logscale", 1)>=0) || (ppl_strAutocomplete(word, "linearscale", 1)>=0)) { int C; for (C=0; C<4; C++) { if (sg->Clog[C]==SW_BOOL_TRUE) bufp = "logscale"; else bufp = "nologscale"; sprintf(buf, "c%d",C+1); sprintf(buf2, "Sets whether colors in the colormap plot style, and contours in the contourmap plot style, demark linear or logarithmic intervals"); ppl_directive_show3(c, out+i, itemSet, 1, interactive, bufp, buf, (sg->Clog[C]==c->set->graph_default.Clog[C]), buf2); i += strlen(out+i) ; p=1; } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "display", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.display, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "display", buf, (c->set->term_default.display == c->set->term_current.display), "Sets whether any output is produced; turn on to improve performance whilst setting up large multiplots"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "filters",1)>=0)) { dictIterator *iter = ppl_dictIterateInit(c->set->filters); pplObj *item = NULL; char *key = NULL; while ((item = (pplObj *)ppl_dictIterate(&iter, &key))!=NULL) { ppl_strEscapify(key, buf+16); ppl_strEscapify((char *)item->auxil, buf2); sprintf(buf,"%s %s",buf+16,buf2); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "filter", buf, 1, "Sets an input filter to be used when reading datafiles"); i += strlen(out+i) ; p=1; } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "fontsize",1)>=0) || (ppl_strAutocomplete(word, "fountsize",1)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(sg->FontSize,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "fontSize", buf, (c->set->graph_default.FontSize == sg->FontSize), "Sets the font size of text output: 1.0 is the default, and other values multiply this default size"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "axes_", 1)>=0) || (ppl_strAutocomplete(word, "axis", 1)>=0) || (ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "grid",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->grid, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "grid", buf, (c->set->graph_default.grid == sg->grid), "Selects whether a grid is drawn on plots"); i += strlen(out+i) ; p=1; if (sg->grid == SW_ONOFF_ON) { bufp = buf; k=1; for (j=0; jGridAxisX[j] != 0 ) { sprintf(bufp, "x%d", j); bufp += strlen(bufp); } if (sg->GridAxisX[j] != c->set->graph_default.GridAxisX[j] ) k=0; } if (bufp != buf) ppl_directive_show3(c, out+i, itemSet, 1, interactive, "grid", buf, k, "Sets the x axis with whose ticks gridlines are associated"); i += strlen(out+i); bufp = buf; k=1; for (j=0; jGridAxisY[j] != 0 ) { sprintf(bufp, "y%d", j); bufp += strlen(bufp); } if (sg->GridAxisY[j] != c->set->graph_default.GridAxisY[j] ) k=0; } if (bufp != buf) ppl_directive_show3(c, out+i, itemSet, 1, interactive, "grid", buf, k, "Sets the y axis with whose ticks gridlines are associated"); i += strlen(out+i); bufp = buf; k=1; for (j=0; jGridAxisZ[j] != 0 ) { sprintf(bufp, "z%d", j); bufp += strlen(bufp); } if (sg->GridAxisZ[j] != c->set->graph_default.GridAxisZ[j] ) k=0; } if (bufp != buf) ppl_directive_show3(c, out+i, itemSet, 1, interactive, "grid", buf, k, "Sets the z axis with whose ticks gridlines are associated"); i += strlen(out+i); } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "gridmajcolor",1)>=0) || (ppl_strAutocomplete(word, "gridmajcolor",1)>=0)) { SHOW_COLOR(sg->GridMajColor,sg->GridMajCol1234Space,sg->GridMajColor1,sg->GridMajColor2,sg->GridMajColor3,sg->GridMajColor4 , c->set->graph_default.GridMajColor,c->set->graph_default.GridMajCol1234Space,c->set->graph_default.GridMajColor1,c->set->graph_default.GridMajColor2,c->set->graph_default.GridMajColor3,c->set->graph_default.GridMajColor4 , "gridMajColor", "The color of the major gridlines on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "gridmincolour",1)>=0) || (ppl_strAutocomplete(word, "gridmincolor",1)>=0)) { SHOW_COLOR(sg->GridMinColor,sg->GridMinCol1234Space,sg->GridMinColor1,sg->GridMinColor2,sg->GridMinColor3,sg->GridMinColor4 , c->set->graph_default.GridMinColor,c->set->graph_default.GridMinCol1234Space,c->set->graph_default.GridMinColor1,c->set->graph_default.GridMinColor2,c->set->graph_default.GridMinColor3,c->set->graph_default.GridMinColor4 , "gridMinColor", "The color of the minor gridlines on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "key",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->key, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "key", buf, (c->set->graph_default.key == sg->key), "Selects whether a legend is included on plots"); i += strlen(out+i) ; p=1; } if ( ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "key",1)>=0)) && (sg->key == SW_ONOFF_ON) ) { sprintf(buf, "%s %s , %s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->KeyPos, SW_KEYPOS_INT, SW_KEYPOS_STR , sizeof(char *)),ppl_unitsNumericDisplay(c,&(sg->KeyXOff),0,0,0),ppl_unitsNumericDisplay(c,&(sg->KeyYOff),1,0,0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "key", buf, ((c->set->graph_default.KeyPos == sg->KeyPos)&&(c->set->graph_default.KeyXOff.real == sg->KeyXOff.real)&&(c->set->graph_default.KeyYOff.real == sg->KeyYOff.real)), "Selects where legends are orientated on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "keycolumns",1)>=0)) { if (sg->KeyColumns>0) sprintf(buf, "%d", sg->KeyColumns); else sprintf(buf, "auto"); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "keyColumns", buf, (c->set->graph_default.KeyColumns == sg->KeyColumns), "Sets the number of columns into which legends on graphs are sorted"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "linewidth", 1)>=0) || (ppl_strAutocomplete(word, "lw", 2)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(sg->LineWidth,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "lineWidth", buf, (c->set->graph_default.LineWidth == sg->LineWidth), "Sets the widths of lines drawn on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "multiplot", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.multiplot, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "multiplot", buf, (c->set->term_default.multiplot == c->set->term_current.multiplot), "Selects whether multiplot mode is currently active"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "numerics", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.ComplexNumbers, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "numerics complex", buf, (c->set->term_default.ComplexNumbers==c->set->term_current.ComplexNumbers), "Selects whether numbers are allowed to have imagnary components; affects the behaviour of functions such as sqrt()"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.ExplicitErrors, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "numerics errors explicit", buf, (c->set->term_default.ExplicitErrors==c->set->term_current.ExplicitErrors), "Selects whether numerical errors quietly produce not-a-number results, or throw explicit errors"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", ppl_numericDisplay(c->set->term_current.SignificantFigures,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "numerics sigfig", buf, (c->set->term_default.SignificantFigures == c->set->term_current.SignificantFigures), "Sets the (minimum) number of significant figures to which decimal numbers are displayed by default"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.NumDisplay, SW_DISPLAY_INT, SW_DISPLAY_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "numerics display", buf, (c->set->term_default.NumDisplay==c->set->term_current.NumDisplay), "Selects how numerical results are displayed: in a natural textual way, in a way which can be copied into a terminal, or as LaTeX"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "origin", 1)>=0)) { sprintf(buf, "%s , %s", ppl_unitsNumericDisplay(c,&(sg->OriginX),0,0,0), ppl_unitsNumericDisplay(c,&(sg->OriginY),1,0,0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "origin", buf, ((c->set->graph_default.OriginX.real == sg->OriginX.real)&&(c->set->graph_default.OriginY.real == sg->OriginY.real)), "Selects where the bottom-left corners of graphs are located on multiplot pages"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "output", 1)>=0)) { ppl_strEscapify(c->set->term_current.output, buf); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "output", buf, (strcmp(c->set->term_default.output,c->set->term_current.output)==0), "Filename to which graphic output is sent"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "palette",1)>=0)) { l=0; for (j=0; jset->palette_current[j] == -1) && (c->set->palette_default[j] == -1)) break; if ((c->set->palette_current[j] == c->set->palette_default[j])&&((c->set->palette_current[j]>0)||((c->set->paletteS_current[j] == c->set->paletteS_default[j])&&(c->set->palette1_current[j] == c->set->palette1_default[j])&&(c->set->palette2_current[j] == c->set->palette2_default[j])&&(c->set->palette3_current[j] == c->set->palette3_default[j])&&(c->set->palette4_current[j] == c->set->palette4_default[j])))) continue; l=1; break; } for (j=k=0; c->set->palette_current[j]>=0; j++) { if (j>0) { sprintf(buf+k, ", "); k+=strlen(buf+k); } if (c->set->palette_current[j]>0) sprintf(buf+k, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->palette_current[j], SW_COLOR_INT, SW_COLOR_STR , sizeof(char *))); else if (c->set->paletteS_current[j]==SW_COLSPACE_RGB ) sprintf(buf+k, "rgb(%s,%s,%s)" , S_RGB(c->set->palette1_current[j],0), S_RGB(c->set->palette2_current[j],1), S_RGB(c->set->palette3_current[j],2)); else if (c->set->paletteS_current[j]==SW_COLSPACE_HSB ) sprintf(buf+k, "hsb(%s,%s,%s)" , S_RGB(c->set->palette1_current[j],0), S_RGB(c->set->palette2_current[j],1), S_RGB(c->set->palette3_current[j],2)); else if (c->set->paletteS_current[j]==SW_COLSPACE_CMYK) sprintf(buf+k, "cmyk(%s,%s,%s,%s)", S_RGB(c->set->palette1_current[j],0), S_RGB(c->set->palette2_current[j],1), S_RGB(c->set->palette3_current[j],2), S_RGB(c->set->palette4_current[j],3)); k+=strlen(buf+k); } ppl_directive_show3(c, out+i, itemSet, 0, interactive, "palette", buf, !l, "The sequence of colors used to plot datasets on color graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "papersize", 1)>=0)) { if (ppl_strAutocomplete("user", c->set->term_current.PaperName, 1)<0) { char docbuff[FNAME_LENGTH]; sprintf(docbuff, "The current papersize for postscript output (%s, %s)", ppl_unitsNumericDisplay(c,&(c->set->term_current.PaperWidth),0,0,0), ppl_unitsNumericDisplay(c,&(c->set->term_current.PaperHeight),1,0,0)); ppl_strEscapify(c->set->term_current.PaperName,buf); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "paperSize", buf, (strcmp(c->set->term_default.PaperName, c->set->term_current.PaperName)==0), docbuff); i += strlen(out+i) ; p=1; } else { sprintf(buf, "%s, %s", ppl_unitsNumericDisplay(c,&(c->set->term_current.PaperWidth),0,0,0), ppl_unitsNumericDisplay(c,&(c->set->term_current.PaperHeight),1,0,0)); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "paperSize", buf, ((c->set->term_default.PaperWidth.real==c->set->term_current.PaperWidth.real)&&(c->set->term_default.PaperHeight.real==c->set->term_current.PaperHeight.real)), "The current papersize for postscript output"); i += strlen(out+i) ; p=1; } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "pointlinewidth",1)>=0) || (ppl_strAutocomplete(word, "plw",3)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(sg->PointLineWidth,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "pointLineWidth", buf, (c->set->graph_default.PointLineWidth==sg->PointLineWidth), "The width of the strokes used to mark points on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "pointsize",1)>=0) || (ppl_strAutocomplete(word, "ps",2)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(sg->PointSize,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "pointSize", buf, (c->set->graph_default.PointSize==sg->PointSize), "The size of points marked on graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "preamble", 1)>=0)) { ppl_strEscapify(c->set->term_current.LatexPreamble,buf); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "preamble", buf, (strcmp(c->set->term_default.LatexPreamble,c->set->term_current.LatexPreamble)==0), "Configuration options sent to the LaTeX typesetting system"); i += strlen(out+i) ; p=1; } // if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "projection", 1)>=0)) // { // sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->projection, SW_PROJ_INT, SW_PROJ_STR , sizeof(char *))); // ppl_directive_show3(c, out+i, itemSet, 0, interactive, "projection", buf, (c->set->graph_default.projection==sg->projection), "The projection used when representing (x,y) data on a graph"); // i += strlen(out+i) ; p=1; // } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "samples",1)>=0)) { int k; sprintf(buf, "%d grid ", sg->samples); k =strlen(buf); if (sg->SamplesXAuto == SW_BOOL_TRUE) sprintf(buf+k, "* x "); else sprintf(buf+k, "%d x ", sg->SamplesX); k+=strlen(buf+k); if (sg->SamplesYAuto == SW_BOOL_TRUE) sprintf(buf+k, "*"); else sprintf(buf+k, "%d", sg->SamplesY); k+=strlen(buf+k); sprintf(buf+k, " interpolate %s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->Sample2DMethod, SW_SAMPLEMETHOD_INT, SW_SAMPLEMETHOD_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "samples", buf, ((c->set->graph_default.samples==sg->samples) && (c->set->graph_default.SamplesXAuto==sg->SamplesXAuto) && (c->set->graph_default.SamplesYAuto==sg->SamplesYAuto) && ((sg->SamplesXAuto==SW_BOOL_TRUE)||(c->set->graph_default.SamplesX==sg->SamplesX)) && ((sg->SamplesYAuto==SW_BOOL_TRUE)||(c->set->graph_default.SamplesY==sg->SamplesY)) && (c->set->graph_default.Sample2DMethod==sg->Sample2DMethod)), "The number of samples taken when functions are plotted"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "seed",1)>=0)) { sprintf(buf, "%ld", c->set->term_current.RandomSeed); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "seed", buf, (c->set->term_default.RandomSeed==c->set->term_current.RandomSeed), "The last seed set for the random number generator"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "size",1)>=0)) { if (sg->AutoAspect == SW_ONOFF_ON) sprintf(buf, "auto"); else sprintf(buf, "%s", ppl_numericDisplay(sg->aspect,c->numdispBuff[ 0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "size ratio", buf, ((c->set->graph_default.aspect==sg->aspect)&&(c->set->graph_default.AutoAspect==sg->AutoAspect)), "The y/x aspect-ratio of graphs"); i += strlen(out+i) ; p=1; if (sg->AutoZAspect == SW_ONOFF_ON) sprintf(buf, "auto"); else sprintf(buf, "%s", ppl_numericDisplay(sg->zaspect,c->numdispBuff[ 0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "size zratio", buf, ((c->set->graph_default.zaspect==sg->zaspect)&&(c->set->graph_default.AutoZAspect==sg->AutoZAspect)), "The z/x aspect-ratio of 3d graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "data", 1)>=0) || (ppl_strAutocomplete(word, "style", 1)>=0)) { ppl_withWordsPrint(c, &sg->dataStyle, buf); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "data style", buf, ppl_withWordsCmp(c,&c->set->graph_default.dataStyle,&sg->dataStyle), "Default plot options for plotting datafiles"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "function", 1)>=0) || (ppl_strAutocomplete(word, "style", 1)>=0)) { ppl_withWordsPrint(c, &sg->funcStyle, buf); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "function style", buf, ppl_withWordsCmp(c,&c->set->graph_default.funcStyle,&sg->funcStyle), "Default plot options for plotting functions"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.TermType, SW_TERMTYPE_INT, SW_TERMTYPE_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal", buf, (c->set->term_default.TermType==c->set->term_current.TermType), "The type of graphic output to be produced"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "antialias",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.TermAntiAlias, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal antialias", buf, (c->set->term_default.TermAntiAlias==c->set->term_current.TermAntiAlias), "Selects whether anti-aliasing is applied to bitmap output"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "colour", 1)>=0) || (ppl_strAutocomplete(word, "color",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.color, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal color", buf, (c->set->term_default.color==c->set->term_current.color), "Selects whether output is color or monochrome"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "dpi", 1)>=0)) { sprintf(buf, "%s", ppl_numericDisplay(c->set->term_current.dpi,c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal dpi", buf, (c->set->term_default.dpi == c->set->term_current.dpi), "Sets the pixel resolution used when producing bitmap graphic output"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "enlargement",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.TermEnlarge, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal enlarge", buf, (c->set->term_default.TermEnlarge==c->set->term_current.TermEnlarge), "Selects whether output photo-enlarged to fill the page"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "invert",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.TermInvert, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal invert", buf, (c->set->term_default.TermInvert==c->set->term_current.TermInvert), "Selects whether the colors of bitmap output are inverted"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "landscape", 1)>=0) || (ppl_strAutocomplete(word, "portrait", 1)>=0)) { if (c->set->term_current.landscape == SW_ONOFF_ON) sprintf(buf, "landscape"); else sprintf(buf, "portrait"); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal", buf, (c->set->term_default.landscape==c->set->term_current.landscape), "Selects the orientation of output"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "terminal", 1)>=0) || (ppl_strAutocomplete(word, "transparent", 1)>=0) || (ppl_strAutocomplete(word, "solid", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.TermTransparent, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "terminal transparent", buf, (c->set->term_default.TermTransparent==c->set->term_current.TermTransparent), "Selects whether gif and png output is transparent"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "textcolour",1)>=0) || (ppl_strAutocomplete(word, "textcolor",1)>=0)) { SHOW_COLOR(sg->TextColor,sg->TextCol1234Space,sg->TextColor1,sg->TextColor2,sg->TextColor3,sg->TextColor4 , c->set->graph_default.TextColor,c->set->graph_default.TextCol1234Space,c->set->graph_default.TextColor1,c->set->graph_default.TextColor2,c->set->graph_default.TextColor3,c->set->graph_default.TextColor4 , "textColor", "Selects the color of text labels"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "texthalign",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->TextHAlign, SW_HALIGN_INT, SW_HALIGN_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "textHAlign", buf, (c->set->graph_default.TextHAlign==sg->TextHAlign), "Selects the horizontal alignment of text labels"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "textvalign",1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, sg->TextVAlign, SW_VALIGN_INT, SW_VALIGN_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "textVAlign", buf, (c->set->graph_default.TextVAlign==sg->TextVAlign), "Selects the vertical alignment of text labels"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "timezone",1)>=0)) { ppl_strEscapify(c->set->term_current.timezone, buf); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "timezone", buf, ((strcmp(c->set->graph_default.title,sg->title)==0)&&(c->set->graph_default.TitleXOff.real==sg->TitleXOff.real)&&(c->set->graph_default.TitleYOff.real==sg->TitleYOff.real)), "The default timezone used by date objects"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "title", 1)>=0)) { ppl_strEscapify(sg->title, buf); k = strlen(buf); sprintf(buf+k, " %s , %s", ppl_unitsNumericDisplay(c,&(sg->TitleXOff), 0, 0, 0), ppl_unitsNumericDisplay(c,&(sg->TitleYOff), 1, 0, 0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "title", buf, ((strcmp(c->set->graph_default.title,sg->title)==0)&&(c->set->graph_default.TitleXOff.real==sg->TitleXOff.real)&&(c->set->graph_default.TitleYOff.real==sg->TitleYOff.real)), "A title to be displayed above graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "trange", 1)>=0) || (ppl_strAutocomplete(word, "urange", 1)>=0) || (ppl_strAutocomplete(word, "vrange", 1)>=0)) if (sg->USE_T_or_uv) { sprintf(buf, "[%s:%s]", ppl_unitsNumericDisplay(c,&(sg->Tmin), 0, 0, 0), ppl_unitsNumericDisplay(c,&(sg->Tmax), 1, 0, 0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "trange", buf, (c->set->graph_default.USE_T_or_uv==sg->USE_T_or_uv)&&(c->set->graph_default.Tmin.real==sg->Tmin.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Tmin),&(sg->Tmin))&&(c->set->graph_default.Tmax.real==sg->Tmax.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Tmax),&(sg->Tmax)), "The range of input values used in constructing parametric function plots"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "logscale", 1)>=0) || (ppl_strAutocomplete(word, "linearscale", 1)>=0)) { if (sg->Tlog==SW_BOOL_TRUE) bufp = "logscale"; else bufp = "nologscale"; sprintf(buf, "t"); sprintf(buf2, "Sets whether the t-axis scales linearly or logarithmically"); ppl_directive_show3(c, out+i, itemSet, 1, interactive, bufp, buf, (sg->Tlog==c->set->graph_default.Tlog), buf2); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "units", 1)>=0)) { sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.UnitAngleDimless, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "unit angle dimensionless", buf, (c->set->term_default.UnitAngleDimless==c->set->term_current.UnitAngleDimless), "Selects whether angles are treated as dimensionless quantities"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.UnitDisplayAbbrev, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "unit display abbreviated", buf, (c->set->term_default.UnitDisplayAbbrev==c->set->term_current.UnitDisplayAbbrev), "Selects whether units are displayed in abbreviated form ('m' vs. 'metres')"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.UnitDisplayPrefix, SW_ONOFF_INT, SW_ONOFF_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "unit display prefix", buf, (c->set->term_default.UnitDisplayPrefix==c->set->term_current.UnitDisplayPrefix), "Selects whether SI units are displayed with prefixes"); i += strlen(out+i) ; p=1; sprintf(buf, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, c->set->term_current.UnitScheme, SW_UNITSCH_INT, SW_UNITSCH_STR , sizeof(char *))); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "unit scheme", buf, (c->set->term_default.UnitScheme==c->set->term_current.UnitScheme), "Selects the scheme (e.g. SI or Imperial) of preferred units"); i += strlen(out+i) ; p=1; for (j=0; junit_pos; j++) if (ud[j].userSel != 0) { sprintf(buf, "unit of %s", ud[j].quantity); if (c->set->term_current.UnitDisplayAbbrev == SW_ONOFF_ON) sprintf(buf2, "%s%s", SIprefixes_abbrev[ud[j].userSelPrefix], ud[j].nameAs); else sprintf(buf2, "%s%s", SIprefixes_full [ud[j].userSelPrefix], ud[j].nameFs); ppl_directive_show3(c, out+i, itemSet, 0, interactive, buf, buf2, 0, "Selects a user-preferred unit for a particular quantity"); i += strlen(out+i) ; p=1; } // show preferred units { PreferredUnit *pu; listIterator *listiter = ppl_listIterateInit(c->unit_PreferredUnits); while ((pu = (PreferredUnit *)ppl_listIterate(&listiter))!=NULL) { int pbuf=0, ppu; buf[0]='\0'; for (ppu=0; ppuNUnits; ppu++) { if (ppu>0) sprintf(buf+pbuf, "*"); pbuf+=strlen(buf+pbuf); if (c->set->term_current.UnitDisplayAbbrev == SW_ONOFF_ON) sprintf(buf+pbuf, "%s%s", (pu->prefix[ppu]>=1)?SIprefixes_abbrev[ pu->prefix[ppu] ]:"", ud[ pu->UnitID[ppu] ].nameAs); else sprintf(buf+pbuf, "%s%s", (pu->prefix[ppu]>=1)?SIprefixes_full [ pu->prefix[ppu] ]:"", ud[ pu->UnitID[ppu] ].nameFs); pbuf+=strlen(buf+pbuf); if (pu->exponent[ppu]!=1) sprintf(buf+pbuf, "**%s", ppl_numericDisplay(pu->exponent[ppu],c->numdispBuff[0],c->set->term_current.SignificantFigures,(c->set->term_current.NumDisplay==SW_DISPLAY_L))); pbuf+=strlen(buf+pbuf); } ppl_directive_show3(c, out+i, itemSet, 0, interactive, "unit preferred", buf, !pu->modified, "Specifies a user-preferred physical unit"); i += strlen(out+i) ; p=1; } } } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "urange", 1)>=0) || (ppl_strAutocomplete(word, "trange", 1)>=0)) if (!sg->USE_T_or_uv) { sprintf(buf, "[%s:%s]", ppl_unitsNumericDisplay(c,&(sg->Umin), 0, 0, 0), ppl_unitsNumericDisplay(c,&(sg->Umax), 1, 0, 0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "urange", buf, (c->set->graph_default.USE_T_or_uv==sg->USE_T_or_uv)&&(c->set->graph_default.Umin.real==sg->Umin.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Umin),&(sg->Umin))&&(c->set->graph_default.Umax.real==sg->Umax.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Umax),&(sg->Umax)), "The range of input values used in constructing 2d parametric function plots"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "logscale", 1)>=0) || (ppl_strAutocomplete(word, "linearscale", 1)>=0)) { if (sg->Ulog==SW_BOOL_TRUE) bufp = "logscale"; else bufp = "nologscale"; sprintf(buf, "u"); sprintf(buf2, "Sets whether the u-axis scales linearly or logarithmically"); ppl_directive_show3(c, out+i, itemSet, 1, interactive, bufp, buf, (sg->Ulog==c->set->graph_default.Ulog), buf2); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "view", 1)>=0)) { int SF = c->set->term_current.SignificantFigures; int TY = (c->set->term_current.NumDisplay==SW_DISPLAY_L); sprintf(buf,"%s,%s",ppl_numericDisplay(sg->XYview.real/M_PI*180,c->numdispBuff[0],SF,TY),ppl_numericDisplay(sg->YZview.real/M_PI*180,c->numdispBuff[1],SF,TY)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "view", buf, (c->set->graph_default.XYview.real==sg->XYview.real)&&(c->set->graph_default.YZview.real==sg->YZview.real), "The rotation angle of 3d graphs"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "viewer", 1)>=0)) { unsigned char changed = (c->set->term_current.viewer != c->set->term_default.viewer); sprintf(buf, "Selects the postscript viewer used by the X11 terminals%s%s%s", (c->set->term_current.viewer != SW_VIEWER_CUSTOM)?" (":"", (c->set->term_current.viewer ==SW_VIEWER_GGV)?"g":"", (c->set->term_current.viewer != SW_VIEWER_CUSTOM)?"gv)":""); if ((c->set->term_current.viewer == SW_VIEWER_CUSTOM) && (c->set->term_default.viewer == SW_VIEWER_CUSTOM)) changed=(strcmp(c->set->term_current.ViewerCmd,c->set->term_default.ViewerCmd)!=0); ppl_directive_show3(c, out+i, itemSet, 0, interactive, "viewer", (c->set->term_current.viewer != SW_VIEWER_CUSTOM)?"auto":c->set->term_current.ViewerCmd, !changed, buf); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "vrange", 1)>=0) || (ppl_strAutocomplete(word, "trange", 1)>=0)) if (!sg->USE_T_or_uv) { sprintf(buf, "[%s:%s]", ppl_unitsNumericDisplay(c,&(sg->Vmin), 0, 0, 0), ppl_unitsNumericDisplay(c,&(sg->Vmax), 1, 0, 0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "vrange", buf, (c->set->graph_default.USE_T_or_uv==sg->USE_T_or_uv)&&(c->set->graph_default.Vmin.real==sg->Vmin.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Vmin),&(sg->Vmin))&&(c->set->graph_default.Vmax.real==sg->Vmax.real)&&ppl_unitsDimEqual(&(c->set->graph_default.Vmax),&(sg->Vmax)), "The range of input values used in constructing 2d parametric function plots"); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "logscale", 1)>=0) || (ppl_strAutocomplete(word, "linearscale", 1)>=0)) { if (sg->Vlog==SW_BOOL_TRUE) bufp = "logscale"; else bufp = "nologscale"; sprintf(buf, "v"); sprintf(buf2, "Sets whether the t-axis scales linearly or logarithmically"); ppl_directive_show3(c, out+i, itemSet, 1, interactive, bufp, buf, (sg->Vlog==c->set->graph_default.Vlog), buf2); i += strlen(out+i) ; p=1; } if ((ppl_strAutocomplete(word, "settings", 1)>=0) || (ppl_strAutocomplete(word, "width", 1)>=0) || (ppl_strAutocomplete(word, "size", 1)>=0)) { sprintf(buf, "%s", ppl_unitsNumericDisplay(c,&(sg->width), 0, 0, 0)); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "width", buf, (c->set->graph_default.width.real==sg->width.real), "The width of graphs"); i += strlen(out+i) ; p=1; } // Show axes l=0; if ((ppl_strAutocomplete(word, "axes_", 1)>=0) || (ppl_strAutocomplete(word, "axis", 1)>=0)) l=1; if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { for (k=0; k<3; k++) for (j=0; jset->YAxesDefault[j]); break; } case 2 : { axisPtr = &(za[j]); axisPtrDef = &(c->set->ZAxesDefault[j]); break; } default: { axisPtr = &(xa[j]); axisPtrDef = &(c->set->XAxesDefault[j]); break; } } if (!axisPtr->enabled) // Do not show any information for inactive axes, except that they're disabled { if (axisPtrDef->enabled) { sprintf(temp1, "%c%d", "xyzc"[k], j); sprintf(buf2, "Axis %s has been disabled", temp1); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "noaxis", temp1, 0, buf2); i += strlen(out+i) ; p=1; } continue; } sprintf(temp1, "%c%d", "xyzc"[k], j); sprintf(temp2, "%c" , "xyzc"[k] ); if (l || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { sprintf(buf , "%c%d ", "xyzc"[k], j); m = strlen(buf); sprintf(buf+m, "%s ", (axisPtr->invisible ? "invisible" : "visible" )); m += strlen(buf+m); if (k==1) sprintf(buf+m, "%s ", (axisPtr->topbottom ? "right" : "left" )); else if (k==2) sprintf(buf+m, "%s ", (axisPtr->topbottom ? "back" : "front" )); else sprintf(buf+m, "%s ", (axisPtr->topbottom ? "top" : "bottom")); m += strlen(buf+m); sprintf(buf+m, "%s ", *(char **)ppl_fetchSettingName(&c->errcontext, axisPtr->ArrowType, SW_AXISDISP_INT, SW_AXISDISP_STR , sizeof(char *))); m += strlen(buf+m); sprintf(buf+m, "%s ", (axisPtr->atzero ? "atZero" : "notAtZero")); m += strlen(buf+m); sprintf(buf+m, "%s ", *(char **)ppl_fetchSettingName(&c->errcontext, axisPtr->MirrorType, SW_AXISMIRROR_INT, SW_AXISMIRROR_STR , sizeof(char *))); m += strlen(buf+m); if (!axisPtr->linked) { sprintf(buf+m, "notLinked"); m += strlen(buf+m); } else { strcpy(buf+m, "linked"); m += strlen(buf+m); if (axisPtr->LinkedAxisCanvasID > 0) { sprintf(buf+m, " item %d", axisPtr->LinkedAxisCanvasID); m += strlen(buf+m); } sprintf(buf+m, " %c%d", "xyzc"[axisPtr->LinkedAxisToXYZ], axisPtr->LinkedAxisToNum); m += strlen(buf+m); if (axisPtr->linkusing != NULL) { sprintf(buf+m, " using %s", ((pplExpr *)axisPtr->linkusing)->ascii); m += strlen(buf+m); } } sprintf(buf2, "Settings for the %c%d axis", "xyzc"[k], j); ppl_directive_show3(c, out+i, itemSet, 1, interactive, "axis", buf, (axisPtr->atzero == axisPtrDef->atzero ) && (axisPtr->enabled == axisPtrDef->enabled ) && (axisPtr->invisible == axisPtrDef->invisible ) && (axisPtr->linked == axisPtrDef->linked ) && (axisPtr->topbottom == axisPtrDef->topbottom ) && (axisPtr->ArrowType == axisPtrDef->ArrowType ) && (axisPtr->LinkedAxisCanvasID == axisPtrDef->LinkedAxisCanvasID) && (axisPtr->LinkedAxisToXYZ == axisPtrDef->LinkedAxisToXYZ ) && (axisPtr->LinkedAxisToNum == axisPtrDef->LinkedAxisToNum ) && (axisPtr->MirrorType == axisPtrDef->MirrorType ) , buf2 ); i += strlen(out+i) ; p=1; } sprintf(temp1, "%c%dformat", "xyzc"[k], j); sprintf(temp2, "%cformat" , "xyzc"[k] ); if (l || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { if (axisPtr->format != NULL) sprintf(buf, "%s ", ((pplExpr *)axisPtr->format)->ascii); else buf[0]='\0'; m = strlen(buf); sprintf(buf+m, "%s", *(char **)ppl_fetchSettingName(&c->errcontext, axisPtr->TickLabelRotation, SW_TICLABDIR_INT, SW_TICLABDIR_STR , sizeof(char *))); m += strlen(buf+m); if (axisPtr->TickLabelRotation == SW_TICLABDIR_ROT) { pplObj valobj; valobj.refCount=1; pplObjNum(&valobj,0,axisPtr->TickLabelRotate,0); valobj.exponent[UNIT_ANGLE] = 1; valobj.dimensionless = 0; sprintf(buf+m, " %s", ppl_unitsNumericDisplay(c,&valobj,0,0,0)); } sprintf(buf2, "Format string for the tick labels on the %c%d axis", "xyzc"[k], j); ppl_directive_show3(c, out+i, itemSet, 1, interactive, temp1, buf, ( ( axisPtr->TickLabelRotate ==axisPtrDef->TickLabelRotate ) && ( axisPtr->TickLabelRotation==axisPtrDef->TickLabelRotation) && (((axisPtr->format==NULL)&&(axisPtrDef->format==NULL)) || ((axisPtr->format!=NULL)&&(axisPtrDef->format!=NULL)&&(strcmp(((pplExpr *)axisPtr->format)->ascii,((pplExpr *)axisPtrDef->format)->ascii)==0))) ) , buf2); i += strlen(out+i) ; p=1; } sprintf(temp1, "%c%dlabel", "xyzc"[k], j); sprintf(temp2, "%clabel" , "xyzc"[k] ); if (l || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { pplObj valobj; valobj.refCount=1; ppl_strEscapify(axisPtr->label==NULL ? "" : axisPtr->label , buf); m = strlen(buf); pplObjNum(&valobj,0,axisPtr->LabelRotate,0); valobj.exponent[UNIT_ANGLE] = 1; valobj.dimensionless = 0; sprintf(buf+m, " rotate %s", ppl_unitsNumericDisplay(c,&valobj,0,0,0)); sprintf(buf2, "Textual label for the %c%d axis", "xyzc"[k], j); ppl_directive_show3(c, out+i, itemSet, 1, interactive, temp1, buf, ( ( axisPtr->LabelRotate==axisPtrDef->LabelRotate) && (((axisPtr->label==NULL)&&(axisPtrDef->label==NULL)) || ((axisPtr->label!=NULL)&&(axisPtrDef->label!=NULL)&&(strcmp(axisPtr->label,axisPtrDef->label)==0))) ) , buf2); i += strlen(out+i) ; p=1; } if (l || (ppl_strAutocomplete(word, "logscale", 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, "linearscale", 1)>=0))) { if (axisPtr->log==SW_BOOL_TRUE) bufp = "logscale"; else bufp = "nologscale"; sprintf(buf, "%c%d", "xyzc"[k], j); m = strlen(buf); if (axisPtr->log==SW_BOOL_TRUE) sprintf(buf+m, " base %d", (int)axisPtr->tics.logBase); sprintf(buf2, "Sets whether the %c%d axis scales linearly or logarithmically", "xyzc"[k], j); ppl_directive_show3(c, out+i, itemSet, 1, interactive, bufp, buf, (axisPtr->log==axisPtrDef->log), buf2); i += strlen(out+i) ; p=1; } sprintf(temp1, "%c%drange", "xyzc"[k], j); sprintf(temp2, "%crange" , "xyzc"[k] ); if (l || (ppl_strAutocomplete(word, "autoscale", 1)>=0) || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { axisPtr->unit.real = axisPtr->min; if (axisPtr->MinSet==SW_BOOL_TRUE) bufp = ppl_unitsNumericDisplay(c,&(axisPtr->unit),0,0,0); else bufp = "*"; axisPtr->unit.real = axisPtr->max; if (axisPtr->MaxSet==SW_BOOL_TRUE) bufp2 = ppl_unitsNumericDisplay(c,&(axisPtr->unit),1,0,0); else bufp2 = "*"; sprintf(buf , "[%s:%s]%s", bufp, bufp2, axisPtr->RangeReversed ? " reversed" : ""); sprintf(buf2, "Sets the range of the %c%d axis", "xyzc"[k], j); ppl_directive_show3(c, out+i, itemSet, 1, interactive, temp1, buf, (axisPtr->min == axisPtrDef->min ) && (axisPtr->MinSet == axisPtrDef->MinSet) && (axisPtr->max == axisPtrDef->max ) && (axisPtr->MaxSet == axisPtrDef->MaxSet) , buf2); i += strlen(out+i) ; p=1; } sprintf(temp1, "%c%dtics", "xyzc"[k], j); sprintf(temp2, "%ctics" , "xyzc"[k] ); m=0; if (l || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { SHOW_TICKS(axisPtr->tics, axisPtrDef->tics, axisPtr->unit, axisPtrDef->unit, axisPtr->log, axisPtrDef->log, "xyzc"[k], j); i += strlen(out+i) ; p=1; m=1; // If we've shown major tics, also show minor ticks too. } sprintf(temp1, "m%c%dtics", "xyzc"[k], j); sprintf(temp2, "m%ctics" , "xyzc"[k] ); if (l || m || (ppl_strAutocomplete(word, temp1, 1)>=0) || ((j==1)&&(ppl_strAutocomplete(word, temp2, 1)>=0))) { SHOW_TICKS(axisPtr->ticsM, axisPtrDef->ticsM, axisPtr->unit, axisPtrDef->unit, axisPtr->log, axisPtrDef->log, "xyzc"[k], j); i += strlen(out+i) ; p=1; } } // loop over axes } // if axis data structures are not null // Showed numbered arrows if (ppl_strAutocomplete(word, "arrows", 1)>=0) { if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplarrow_object *ai; pplarrow_object *ai_default_prev = c->set->pplarrow_list_default; pplarrow_object *ai_default = c->set->pplarrow_list_default; SHOW_HIGHLIGHT(1); sprintf(out+i, "\n# Numbered arrows:\n\n"); i += strlen(out+i); p=1; SHOW_DEHIGHLIGHT; for (ai=*al; ai!=NULL; ai=ai->next) { if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } while ((ai_default != NULL) && (ai_default->id <= ai->id)) { if (ai_default->id < ai->id) { sprintf(buf2, "noarrow %6d", ai_default->id); sprintf(buf,"remove arrow %6d", ai_default->id); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, "", 1, buf); i += strlen(out+i); } ai_default_prev = ai_default; ai_default = ai_default->next; } pplarrow_print(c,ai,buf); sprintf(buf2, "arrow %6d", ai->id); if ((unchanged = ((ai_default_prev != NULL) && (ai_default_prev->id == ai->id)))!=0) unchanged = pplarrow_compare(c , ai , ai_default_prev); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, buf, unchanged, buf2); i += strlen(out+i); } while (ai_default != NULL) { sprintf(buf2, "noarrow %6d", ai_default->id); sprintf(buf,"remove arrow %6d", ai_default->id); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, "", 1, buf); i += strlen(out+i); ai_default = ai_default->next; } } } // Show numbered text labels if (ppl_strAutocomplete(word, "labels", 1)>=0) { if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { ppllabel_object *li; ppllabel_object *li_default_prev = c->set->ppllabel_list_default; ppllabel_object *li_default = c->set->ppllabel_list_default; SHOW_HIGHLIGHT(1); sprintf(out+i, "\n# Numbered text labels:\n\n"); i += strlen(out+i); p=1; SHOW_DEHIGHLIGHT; for (li=*ll; li!=NULL; li=li->next) { if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } while ((li_default != NULL) && (li_default->id <= li->id)) { if (li_default->id < li->id) { sprintf(buf2, "nolabel %6d", li_default->id); sprintf(buf,"remove label %6d", li_default->id); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, "", 1, buf); i += strlen(out+i); } li_default_prev = li_default; li_default = li_default->next; } ppllabel_print(c,li,buf); sprintf(buf2, "label %6d", li->id); if ((unchanged = ((li_default_prev != NULL) && (li_default_prev->id == li->id)))!=0) unchanged = ppllabel_compare(c , li , li_default_prev); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, buf, unchanged, buf2); i += strlen(out+i); } while (li_default != NULL) { sprintf(buf2, "nolabel %6d", li_default->id); sprintf(buf,"remove label %6d", li_default->id); ppl_directive_show3(c, out+i, itemSet, 1, interactive, buf2, "", 1, buf); i += strlen(out+i); li_default = li_default->next; } } } // Show numbered styles if ((ppl_strAutocomplete(word, "styles", 1)>=0) || (ppl_strAutocomplete(word, "linestyles", 1)>=0)) { SHOW_HIGHLIGHT(1); sprintf(out+i, "\n# Numbered styles:\n\n"); i += strlen(out+i); p=1; SHOW_DEHIGHLIGHT; for (j=0; jset->plot_styles[j]))) continue; if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } ppl_withWordsPrint(c,&(c->set->plot_styles[j]),buf); sprintf(buf2, "style %4d", j); ppl_directive_show3(c, out+i, itemSet, 0, interactive, buf2, buf, !ppl_withWordsCmp(c,&(c->set->plot_styles[j]),&(c->set->plot_styles_default[j])), buf2); i += strlen(out+i); } } // Show variables if ((ppl_strAutocomplete(word, "variables", 1)>=0) || (ppl_strAutocomplete(word, "vars", 1)>=0) || (ppl_strAutocomplete(word, "uservariables", 1)>=0) || (ppl_strAutocomplete(word, "uservars", 1)>=0)) { int l; for (l=c->ns_ptr ; l>=0 ; l=(l>1)?1:l-1) { char *key; pplObj *item; dictIterator *di = ppl_dictIterateInit( c->namespaces[l] ); if ((word[0]=='u')&&(l<1)) break; // Don't show default variables as user variables SHOW_HIGHLIGHT(1); if (l >1) sprintf(out+i, "\n# Local variables:\n\n"); else if (l==1) sprintf(out+i, "\n# Global variables:\n\n"); else sprintf(out+i, "\n# Default variables:\n\n"); i+=strlen(out+i); p=1; SHOW_DEHIGHLIGHT; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { if ((item->objType==PPLOBJ_ZOM) || (item->objType==PPLOBJ_GLOB) || (item->objType==PPLOBJ_FUNC)) continue; if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } SHOW_HIGHLIGHT((l==0)); sprintf(out+i, "%s = ", key); i+=strlen(out+i); pplObjPrint(c,item,key,out+i,600,0,1); i+=strlen(out+i); sprintf(out+i, "\n"); i+=strlen(out+i); SHOW_DEHIGHLIGHT; } } } // Show system functions if ((ppl_strAutocomplete(word, "functions", 1)>=0) || (ppl_strAutocomplete(word, "funcs", 1)>=0)) { char *key; pplObj *item; dictIterator *di = ppl_dictIterateInit( c->namespaces[0] ); SHOW_HIGHLIGHT(1); sprintf(out+i, "\n# System-defined functions:\n\n"); i+=strlen(out+i); p=1; SHOW_DEHIGHLIGHT; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { if (item->objType!=PPLOBJ_FUNC) continue; if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } SHOW_HIGHLIGHT(1); pplObjPrint(c,item,key,out+i,600,0,1); i+=strlen(out+i); sprintf(out+i, "\n"); i+=strlen(out+i); SHOW_DEHIGHLIGHT; } } // Show user functions if ((ppl_strAutocomplete(word, "functions", 1)>=0) || (ppl_strAutocomplete(word, "funcs", 1)>=0) || (ppl_strAutocomplete(word, "userfunctions", 1)>=0) || (ppl_strAutocomplete(word, "userfuncs", 1)>=0)) { int l; for (l=c->ns_ptr ; l>0 ; l=(l>1)?1:l-1) { char *key; pplObj *item; dictIterator *di = ppl_dictIterateInit( c->namespaces[l] ); SHOW_HIGHLIGHT(1); if (l >1) sprintf(out+i, "\n# Local functions:\n\n"); else sprintf(out+i, "\n# Global functions:\n\n"); i+=strlen(out+i); p=1; SHOW_DEHIGHLIGHT; while ((item = (pplObj *)ppl_dictIterate(&di,&key))!=NULL) { if (item->objType!=PPLOBJ_FUNC) continue; if (i > outLen-1024) { sprintf(out+i, "...\n"); i+=strlen(out+i); break; } SHOW_HIGHLIGHT(0); pplObjPrint(c,item,key,out+i,600,0,1); i+=strlen(out+i); sprintf(out+i, "\n"); i+=strlen(out+i); SHOW_DEHIGHLIGHT; } } } // Show list of recognised units if (ppl_strAutocomplete(word, "units", 5)>=0) { SHOW_HIGHLIGHT(1); sprintf(out+i, "\n# Recognised physical units:\n\n"); i += strlen(out+i); p=1; SHOW_DEHIGHLIGHT; l=-1; do { m=-1; for (j=0; junit_pos; j++) { if ( (l==-1) && (m==-1) ) m=j; else if ( (l==-1) && (ppl_strCmpNoCase(ud[j].nameFs , ud[m].nameFs)<0) ) m=j; else if ( (l>= 0) && (m==-1) && (ppl_strCmpNoCase(ud[j].nameFs , ud[l].nameFs)>0) ) m=j; else if ( (l>= 0) && (m>= 0) && (ppl_strCmpNoCase(ud[j].nameFs , ud[m].nameFs)<0) && (ppl_strCmpNoCase(ud[j].nameFs , ud[l].nameFs)>0) ) m=j; } l=m; if (m!=-1) { k=0; SHOW_HIGHLIGHT((ud[m].modified==0)); #define SHOW_ALL_UNIT_NAMES 0 sprintf(out+i, "# The '%s', also known as", ud[m].nameFs); i+=strlen(out+i); if ((SHOW_ALL_UNIT_NAMES) || (strcmp(ud[m].nameFp, ud[m].nameFs) != 0)) { sprintf(out+i, " '%s' or", ud[m].nameFp); i+=strlen(out+i); k=1; } if ((SHOW_ALL_UNIT_NAMES) || (strcmp(ud[m].nameAs, ud[m].nameFs) != 0)) { sprintf(out+i, " '%s' or", ud[m].nameAs); i+=strlen(out+i); k=1; } if ((SHOW_ALL_UNIT_NAMES) ||((strcmp(ud[m].nameAp, ud[m].nameAs) != 0) && (strcmp(ud[m].nameAp, ud[m].nameFp) != 0))){sprintf(out+i, " '%s' or", ud[m].nameAp); i+=strlen(out+i); k=1; } if ( ud[m].alt1 != NULL ) { sprintf(out+i, " '%s' or", ud[m].alt1 ); i+=strlen(out+i); k=1; } if ( ud[m].alt2 != NULL ) { sprintf(out+i, " '%s' or", ud[m].alt2 ); i+=strlen(out+i); k=1; } if ( ud[m].alt3 != NULL ) { sprintf(out+i, " '%s' or", ud[m].alt3 ); i+=strlen(out+i); k=1; } if ( ud[m].alt4 != NULL ) { sprintf(out+i, " '%s' or", ud[m].alt4 ); i+=strlen(out+i); k=1; } if (k==0) { i-=15; } else { i-=3; out[i++]=','; } sprintf(out+i, " is a unit of %s", ud[m].quantity); i += strlen(out+i); if (ud[m].comment != NULL) { sprintf(out+i, " (%s)", ud[m].comment); i += strlen(out+i); } sprintf(out+i, ".\n"); i += strlen(out+i); SHOW_DEHIGHLIGHT; } } while (m!=-1); } if (p!=0) ppl_report(&c->errcontext,out); return p; } #define TBADD(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") void ppl_directive_show(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplObj *stk = in->stk; int pos; char itemSet[32]; pplset_graph *sg; pplarrow_object **al; ppllabel_object **ll; pplset_axis *xa, *ya, *za; interactive = ( interactive && (c->errcontext.session_default.color == SW_ONOFF_ON) ); if (stk[PARSE_show_editno].objType != PPLOBJ_NUM) { sg = &c->set->graph_current; al = &c->set->pplarrow_list; ll = &c->set->ppllabel_list; xa = c->set->XAxes; ya = c->set->YAxes; za = c->set->ZAxes; itemSet[0]='\0'; } else { canvas_itemlist *canvas_items = c->canvas_items; canvas_item *ptr = canvas_items->first; int editNo = (int)round(stk[PARSE_show_editno].real); if ((editNo<1) || (editNo>MULTIPLOT_MAXINDEX) || (canvas_items == NULL)) { sprintf(c->errcontext.tempErrStr, "No multiplot item with index %d.", editNo); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } while ((ptr!=NULL)&&(ptr->id!=editNo)) ptr=ptr->next; if (ptr == NULL) { sprintf(c->errcontext.tempErrStr, "No multiplot item with index %d.", editNo); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } sg = &(ptr->settings); al = &(ptr->arrow_list); ll = &(ptr->label_list); xa = ptr->XAxes; ya = ptr->YAxes; za = ptr->ZAxes; sprintf(itemSet, "item %d ", editNo); } pos = PARSE_show_0setting_list; if ((stk[pos].objType != PPLOBJ_NUM) || (stk[pos].real <= 0)) { ppl_error(&c->errcontext, ERR_PREFORMED, -1, -1, ppltxt_show); } else { char textBuffer[SSTR_LENGTH], *showWord=NULL; int p=0,i=0; if (interactive!=0) // On interactive sessions, highlight those settings which have been manually set by the user { sprintf(textBuffer+i,"%sSettings which have not been changed by the user are shown in %s.%s\n", *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_rep , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)), *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_rep , SW_TERMCOL_INT , SW_TERMCOL_STR , sizeof(char *)), *(char **)ppl_fetchSettingName(&c->errcontext, SW_TERMCOL_NOR , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)) ); i += strlen(textBuffer+i); sprintf(textBuffer+i,"%sSettings which have been changed by the user are shown in %s.%s\n", *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_wrn , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)), *(char **)ppl_fetchSettingName(&c->errcontext, c->errcontext.session_default.color_wrn , SW_TERMCOL_INT , SW_TERMCOL_STR , sizeof(char *)), *(char **)ppl_fetchSettingName(&c->errcontext, SW_TERMCOL_NOR , SW_TERMCOL_INT , SW_TERMCOL_TXT , sizeof(char *)) ); i += strlen(textBuffer+i); ppl_report(&c->errcontext,textBuffer); } while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { pos = (int)round(stk[pos].real); showWord = (char *)stk[pos+PARSE_show_setting_0setting_list].auxil; if (ppl_strAutocomplete(showWord,"all",1)>=0) { ppl_directive_show2(c, "settings" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "axes_" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "arrows" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "labels" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "linestyles" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "variables" ,itemSet, interactive, sg, al, ll, xa, ya, za); ppl_directive_show2(c, "userfunctions" ,itemSet, interactive, sg, al, ll, xa, ya, za); //ppl_directive_show2(c, "units" ,itemSet, interactive, sg, al, ll, xa, ya, za); p=1; } else { p = (ppl_directive_show2(c, showWord, itemSet, interactive, sg, al, ll, xa, ya, za) || p); } } if ((p==0) && (showWord!=NULL)) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Unrecognised show option '%s'.\n\n%s", showWord, ppltxt_show); TBADD(ERR_SYNTAX,in->stkCharPos[pos+PARSE_show_setting_0setting_list]); } } return; } pyxplot-0.9.2/src/commands/tabulate.c0000664000175000017500000003362012026340554016165 0ustar dcf21dcf21// tabulate.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: tabulate.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _TABULATE_C 1 #include #include #include #include #include #include #include #include "commands/tabulate.h" #include "coreUtils/backup.h" #include "coreUtils/getPasswd.h" #include "coreUtils/memAlloc.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" // Display data from a data block static int ppl_tab_dataGridDisplay(ppl_context *c, FILE *output, dataTable *data, int *minSet, double *min, int *maxSet, double *max, pplObj *unit, char *format) { dataBlock *blk; char *cptr, tmpchr='\0'; double tmpdbl, multiplier[USING_ITEMS_MAX]; int inRange, split, allInts[USING_ITEMS_MAX], allSmall[USING_ITEMS_MAX]; long i,k; int j,l,pos; double val; const int Ncolumns = data->Ncolumns_real; // Check that the firstEntries above have the same units as any supplied ranges for (j=0; jfirstEntries+j)) { sprintf(c->errcontext.tempErrStr, "The minimum and maximum limits specified in range %d in the tabulate command have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", j+1, ppl_printUnit(c,&unit[j],NULL,NULL,0,1,0), ppl_printUnit(c,data->firstEntries+j,NULL,NULL,1,1,0)); ppl_error(&c->errcontext,ERR_NUMERICAL,-1,-1,NULL); return 1; } } // Output a column units line fprintf(output, "# ColumnUnits: "); for (j=0; jfirstEntries[j].dimensionless) { fprintf(output, "1 "); // This column contains dimensionless data multiplier[j] = 1.0; } else { data->firstEntries[j].real = 1.0; data->firstEntries[j].imag = 0.0; data->firstEntries[j].flagComplex = 0; cptr = ppl_printUnit(c, data->firstEntries+j, multiplier+j, &tmpdbl, 0, 1, SW_DISPLAY_T); for (i=0; ((cptr[i]!='\0')&&(cptr[i]!='(')); i++); i++; // Fastforward over opening bracket for ( ; ((cptr[i]!='\0')&&(cptr[i]!=')')); i++) fprintf(output, "%c", cptr[i]); fprintf(output, " "); } } fprintf(output, "\n"); // Iterate over columns of data in this data grid, working out which columns of data are all ints, and which are all %f-able data for (j=0; jfirst; while (blk != NULL) { for (i=0; iblockPosition; i++) { inRange=1; for (k=0; kdata_real[k + Ncolumns*i]; if ( (minSet[k]&&(valmax[k])) ) { inRange=0; break; } // Check that value is within range } if (inRange) for (k=0; kdata_real[k + Ncolumns*i] * multiplier[k]; if (!gsl_finite(val) ) allInts [k]=0; // don't try to represent NANs as integers! if ((fabs(val)>1000) || (!ppl_dblEqual(val,floor(val+0.5)))) allInts [k]=0; if ((fabs(val)>1000) || (fabs(val)<0.0099999999999) ) allSmall[k]=0; // Columns containing only numbers in this range are fprintfed using %f, rather than %e } } blk=blk->next; } // Iterate over columns of data in this data grid, working out which columns of data are all ints, and which are all %f-able data blk = data->first; split = 0; while (blk != NULL) { for (i=0; iblockPosition; i++) { inRange=1; if (blk->split[i]) split=1; for (k=0; kdata_real[k + Ncolumns*i]; if ( (minSet[k]&&(valmax[k])) ) { inRange=0; break; } // Check that value is within range } if (inRange) { if (split) { fprintf(output, "\n"); split=0; } if (format == NULL) // User has not supplied a format string, and so we just list the contents of each column in turn using best-fit format style { for (k=0; kdata_real[k + Ncolumns*i] * multiplier[k]; if (allInts [k]) fprintf(output, "%10d " , (int)val); else if (allSmall[k]) fprintf(output, "%17.10f ", val); else fprintf(output, "%17.8e " , val); } } else { // The user has supplied a format string, which we now substitute column values into for (pos=l=0; ; pos++) { if (format[pos]=='\0') { if ((l>0)&&(l while ((format[k]>='0') && (format[k]<='9')) k++; // length can be some digits if (format[k]=='.') // precision starts with a . and is followed by more digits { k++; while ((format[k]>='0') && (format[k]<='9')) k++; // length can be some digits } // We do not allow user to specify optional length flag, which could potentially be if (l>=Ncolumns) val = GSL_NAN; else val = blk->data_real[l + Ncolumns*i] * multiplier[l]; // Set val to equal data from data table that we're about to print. l++; if (format[k]!='\0') { tmpchr = format[k+1]; format[k+1] = '\0'; } // NULL terminate format token before passing it to fprintf if (format[k]=='d') // %d -- print quantity as an integer, but take care to avoid overflows { if ((!gsl_finite(val))||(val>INT_MAX-1)||(val=Ncolumns) sprintf(c->errcontext.tempErrStr, "nan"); else if (allInts [l-1]) sprintf(c->errcontext.tempErrStr, "%10d " , (int)val); else if (allSmall[l-1]) sprintf(c->errcontext.tempErrStr, "%17.10f ", val); else sprintf(c->errcontext.tempErrStr, "%17.8e " , val); fprintf(output, format+pos, c->errcontext.tempErrStr); pos = k; } else { fprintf(output, "%c", format[pos]); l--; } // l-- because this wasn't a valid format token, so we didn't print any data in the end if (format[k]!='\0') format[k+1] = tmpchr; // Remove temporary NULL termination at the end of the format token } } } fprintf(output, "\n"); } else split=1; } blk=blk->next; } return 0; } #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") void ppl_directive_tabulate(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { wordexp_t wordExp; int pos; pplObj *stk=in->stk; FILE *output=NULL; long j; char *filename, filenameTemp[FNAME_LENGTH]; parserLine *spool=NULL, **dataSpool = &spool; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX]; // Read data range { int i,pos=PARSE_tabulate_0range_list,nr=0; const int o1 = PARSE_tabulate_min_0range_list; const int o2 = PARSE_tabulate_max_0range_list; for (i=0; i=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff,"Too many ranges specified; a maximum of %d are allowed.", USING_ITEMS_MAX); TBADD2(ERR_SYNTAX,0); return; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_tabulate_min_0range_list]); return; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_tabulate_min_0range_list]); return; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } nr++; } } // Work out filename for output file filename = c->set->term_current.output; if ((filename==NULL)||(filename[0]=='\0')) filename = "pyxplot.txt"; // Perform expansion of shell filename shortcuts such as ~ if ((wordexp(filename, &wordExp, 0) != 0) || (wordExp.we_wordc <= 0)) { sprintf(c->errcontext.tempErrStr, "Could not find directory containing filename '%s'.", filename); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); return; } if (wordExp.we_wordc > 1) { sprintf(c->errcontext.tempErrStr, "Filename '%s' is ambiguous.", filename); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); return; } strncpy(filenameTemp, wordExp.we_wordv[0], FNAME_LENGTH); filenameTemp[FNAME_LENGTH-1]='\0'; wordfree(&wordExp); filename = filenameTemp; // Open output file and write header at the top of it ppl_createBackupIfRequired(c,filename); output = fopen(filename,"w"); if (output==NULL) { sprintf(c->errcontext.tempErrStr, "The tabulate command could not open output file '%s' for writing.", filename); ppl_error(&c->errcontext,ERR_FILE,-1,-1,NULL); return; } fprintf(output, "# Datafile generated by Pyxplot %s\n# Timestamp: %s\n", VERSION, ppl_strStrip(ppl_friendlyTimestring(),c->errcontext.tempErrStr)); fprintf(output, "# User: %s\n# Pyxplot command: %s\n\n", ppl_unixGetIRLName(&c->errcontext), pl->linetxt); // Loop over datasets being tabulated pos = PARSE_tabulate_0tabulate_list; j = 1; while (stk[pos].objType == PPLOBJ_NUM) { char *format, datafname[FNAME_LENGTH]=""; int w, errCount=5; dataTable *data=NULL; pos = (int)round(stk[pos].real); if (pos<=0) break; fprintf(output, "\n\n\n# Index %ld\n", j); // Put a heading at the top of the new data index // Read display format if (stk[pos+PARSE_tabulate_format_0tabulate_list].objType==PPLOBJ_STR) format=(char *)stk[pos+PARSE_tabulate_format_0tabulate_list].auxil; else format=NULL; for (w=0 ; ; w++) { // Descend into new memory context int contextLocal = ppl_memAlloc_DescendIntoNewContext(); int status = 0; // Fetch data ppldata_fromCmd(c, &data, pl, in, w, datafname, dataSpool, PARSE_TABLE_tabulate_, pos, -1, 0, min, minSet, max, maxSet, unit, 0, &status, c->errcontext.tempErrStr, &errCount, iterDepth); // Print data if ((status)||(data==NULL)) { if (w==0) ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); ppl_memAlloc_AscendOutOfContext(contextLocal); break; } else { if (datafname[0]!='\0') { if (w>0) { j++; fprintf(output, "\n\n\n# Index %ld\n", j); } fprintf(output, "\n# %s\n\n", datafname); } ppl_tab_dataGridDisplay(c, output, data, minSet, min, maxSet, max, unit, format); } // Ascend out of memory content ppl_memAlloc_AscendOutOfContext(contextLocal); } j++; } fclose(output); return; } pyxplot-0.9.2/src/commands/fit.h0000664000175000017500000000200112026340554015140 0ustar dcf21dcf21// fit.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fit.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _FIT_H #define _FIT_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_fit(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/commands/interpolate_2d_engine.h0000664000175000017500000000251212026340554020625 0ustar dcf21dcf21// interpolate_2d_engine.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: interpolate_2d_engine.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _INTERPOLATE2D_H #define _INTERPOLATE2D_H 1 #include "datafile.h" #include "settings/settings.h" #include "userspace/context.h" void ppl_interp2d_eval(ppl_context *c, double *output, const pplset_graph *sg, const double *in, const long InSize, const int ColNum, const int NCols, const double x, const double y); void ppl_interp2d_grid(ppl_context *c, dataTable **output, const pplset_graph *sg, dataTable *in, pplset_axis *axis_x, pplset_axis *axis_y, unsigned char SampleToEdge, int *XSizeOut, int *YSizeOut); #endif pyxplot-0.9.2/src/commands/set.h0000664000175000017500000000176112026340554015165 0ustar dcf21dcf21// set.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: set.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _SET_H #define _SET_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_set(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); #endif pyxplot-0.9.2/src/commands/fit.c0000664000175000017500000010700412026340554015144 0ustar dcf21dcf21// fit.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fit.c 1298 2012-08-31 13:17:45Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _FIT_C 1 #include #include #include #include #include #include #include #include #include #include #include #include "commands/fit.h" #include "coreUtils/errorReport.h" #include "coreUtils/memAlloc.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/fnCall.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" // Structure used for passing data around typedef struct fitComm { ppl_context *c; parserLine *pl; int NArgs; // The number of arguments taken by the function that we're fitting int NExpect; // The total number of columns we're reading from datafile; equals NArgs, plus the target value for f(), plus possibly the error on each target int NFitVars; // The number of variables listed after via .... int NParams; // The total number of free parameters in the fitting problems; either equals NFitVars, or twice this if complex arithmetic is enabled long int NDataPoints; // The number of data points read from the supplied datafile pplObj **varObj; // Pointers to the values of the variables which we're fitting the values of in the user's variable space const gsl_vector *paramVals; // Trial parameter values to be tried by fitResidual in this iteration const gsl_vector *bestFitParamVals; // The best fit parameter values (only set after first round of minimisation) gsl_vector *paramValsHessian; // Internal variable used by GetHessian() to vary parameter values when differentiating pplObj *firstVals; // The first values found in each column of the supplied datafile. These determine the physical units associated with each column. double *dataTable; // Two-dimensional table of the data read from the datafile. unsigned char flagYErrorBars; // If true, the user has specified errorbars for each target value. If false, we have no idea of uncertainty. char *errtext, *functionName; // String workspaces pplObj *functionObj; unsigned char goneNaN; // Used by the minimiser to keep track of when the function being minimised has returned NAN. double sigmaData; // The assumed errorbar (uniform for all datapoints) on the supplied target values if errorbars are not supplied. We fit this. int diff1 , diff2; // The numbers of the free parameters currently being differentiated inside GetHessian() double diff1step, diff2step; // The step size which GetHessian() recommends using for each of the parameters being differentiated } fitComm; #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(errText,"Stack forward reference detected."); return GSL_NAN; } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") // Routine for printing a GSL matrix in pythonesque format static char *matrixPrint(ppl_context *c, const gsl_matrix *m, const size_t size, char *out) { size_t i,j,p=0; strcpy(out+p, "[ ["); p+=strlen(out+p); for (i=0;inumdispBuff[0],c->set->term_current.SignificantFigures,0)); p+=strlen(out+p); } if (size>0) p--; // Delete final comma strcpy(out+p, "] , ["); p+=strlen(out+p); // New row } if (size>0) p-=3; // Delete final comma and open bracket strcpy(out+p, "]"); return out; } // Low-level routine for working out the mismatch between function and data for a given set of free parameter values static double fitResidual(fitComm *p) { ppl_context *c = p->c; char *errText = p->errtext; const int stkLevelOld = c->stackPtr; int i, k; long int j; double accumulator, residual; pplObj *out; pplExpr dummy; // Dummy expression object with dummy line number information dummy.srcLineN = 0; dummy.srcId = 0; dummy.srcFname = ""; dummy.ascii = NULL; // Set free parameter values for (i=0; iNFitVars; i++) if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) p->varObj[i]->real = gsl_vector_get(p->paramVals, i ); // This is setting variables in the user's variable space else { p->varObj[i]->real = gsl_vector_get(p->paramVals, 2*i ); p->varObj[i]->imag = gsl_vector_get(p->paramVals, 2*i+1); } accumulator = 0.0; // Add up sum of square residuals // Check there's enough space on the stack STACK_MUSTHAVE(c,p->NArgs); if (c->stackFull) { strcpy(errText, "stack overflow in the fit command."); return GSL_NAN; } for (j=0; jNDataPoints; j++) // Loop over all of the data points in the file that we're fitting { // Push function object pplObjCpy(&c->stack[c->stackPtr], p->functionObj, 1, 0, 1); c->stack[c->stackPtr].refCount=1; c->stackPtr++; // Push each argument in turn for (k=0; kNArgs; k++) { pplObjNum(&c->stack[c->stackPtr], 0 , p->dataTable[j*p->NExpect+k], 0); ppl_unitsDimCpy(&c->stack[c->stackPtr], &p->firstVals[k]); c->stack[c->stackPtr].refCount = 1; c->stackPtr++; } // Call function c->errStat.errMsgExpr[0]='\0'; ppl_fnCall(c, &dummy, 0, 1, 1, 1); out = &c->stack[c->stackPtr-1]; if (c->errStat.status) { strcpy(errText, c->errStat.errMsgExpr); ppl_tbClear(c); STACK_CLEAN; return GSL_NAN; } if (out->objType!=PPLOBJ_NUM) { sprintf(errText, "The supplied function to fit produces a value which is not a number but has type <%s>.", pplObjTypeNames[out->objType]); STACK_CLEAN; return GSL_NAN; } if (!ppl_unitsDimEqual(out, p->firstVals+p->NArgs)) { sprintf(errText, "The supplied function to fit produces a value which is dimensionally incompatible with its target value. The function produces a result with dimensions of <%s>, while its target value has dimensions of <%s>.", ppl_printUnit(c,out,NULL,NULL,0,1,0), ppl_printUnit(c,p->firstVals+p->NArgs,NULL,NULL,1,1,0)); STACK_CLEAN; return GSL_NAN; } residual = pow(out->real - p->dataTable[j*p->NExpect+k] , 2) + pow(out->imag , 2); // Calculate squared deviation of function result from desired result if (p->flagYErrorBars) residual /= 2 * pow(p->dataTable[j*p->NExpect+k+1] , 2); // Divide square residual by 2 sigma squared. else residual /= 2 * pow(p->sigmaData , 2); accumulator += residual; // ... and sum STACK_CLEAN; } return accumulator; } // Slave routines called by the differentiation operation when working out the Hessian matrix static double GetHessian_diff2(double x, void *p_void) { double tmp, output; fitComm *p = (fitComm *)p_void; tmp = gsl_vector_get(p->paramValsHessian, p->diff2); // Replace old parameter with x gsl_vector_set(p->paramValsHessian, p->diff2, x); output = fitResidual(p); // Evaluate residual gsl_vector_set(p->paramValsHessian, p->diff2, tmp); // Restore old parameter value return output; } static double GetHessian_diff1(double x, void *p_void) { double tmp, output, output_error; gsl_function fn; fitComm *p = (fitComm *)p_void; fn.function = &GetHessian_diff2; fn.params = p_void; tmp = gsl_vector_get(p->paramValsHessian, p->diff1); // Replace old parameter with x gsl_vector_set(p->paramValsHessian, p->diff1, x); gsl_deriv_central(&fn, gsl_vector_get(p->paramValsHessian, p->diff2), p->diff2step, &output, &output_error); // Differentiate residual a second time gsl_vector_set(p->paramValsHessian, p->diff1, tmp); // Restore old parameter value return output; } // Routine for working out the Hessian matrix static gsl_matrix *GetHessian(fitComm *p) { gsl_matrix *out; int i,j; double output, output_error; gsl_function fn; // Allocate a vector for passing our position in free-parameter space to fitResidual() p->paramValsHessian = gsl_vector_alloc(p->NParams); for (i=0; iNParams; i++) gsl_vector_set(p->paramValsHessian, i, gsl_vector_get(p->bestFitParamVals, i)); p->paramVals = p->paramValsHessian; out = gsl_matrix_alloc(p->NParams, p->NParams); // Allocate memory for Hessian matrix if (out==NULL) return NULL; fn.function = &GetHessian_diff1; fn.params = (void *)p; for (i=0; iNParams; i++) for (j=0; jNParams; j++) // Loop over elements of Hessian matrix { p->diff1 = i; p->diff1step = ((output = gsl_vector_get(p->paramVals,i)*1e-6) < 1e-100) ? 1e-6 : output; p->diff2 = j; p->diff2step = ((output = gsl_vector_get(p->paramVals,j)*1e-6) < 1e-100) ? 1e-6 : output; gsl_deriv_central(&fn, gsl_vector_get(p->paramVals, p->diff1), p->diff1step, &output, &output_error); gsl_matrix_set(out,i,j,-output); // Minus sign here since fitResidual returns the negative of log(P) } gsl_vector_free(p->paramValsHessian); p->paramValsHessian = NULL; return out; } // Slave routines called by minimisers static double ResidualMinimiserSlave(const gsl_vector *x, void *p_void) { fitComm *p = (fitComm *)p_void; p->paramVals = x; return fitResidual(p); } static double FitsigmaData(const gsl_vector *x, void *p_void) { double term1, term2, term3; int sgn; gsl_matrix *hessian; gsl_permutation *perm; fitComm *p = (fitComm *)p_void; p->sigmaData = gsl_vector_get(x,0); p->paramVals = p->bestFitParamVals; term1 = fitResidual(p); // Likelihood for the best-fit set of parameters, without the Gaussian normalisation factor term2 = -(p->NDataPoints * log(1.0 / sqrt(2*M_PI) / p->sigmaData)); // Gaussian normalisation factor // term3 is the Occam Factor, which equals the determinant of -H hessian = GetHessian(p); gsl_matrix_scale(hessian, -1.0); // Want the determinant of -H // Generate the LU decomposition of the Hessian matrix perm = gsl_permutation_alloc(p->NParams); gsl_linalg_LU_decomp(hessian,perm,&sgn); // Hessian matrix is overwritten here, but we don't need it again // Calculate the determinant of the Hessian matrix term3 = gsl_linalg_LU_lndet(hessian) * 0.5; // -log(1/sqrt(det)) gsl_matrix_free(hessian); gsl_permutation_free(perm); return term1+term2+term3; // We return the negative of the log-likelihood, which GSL then minimises by varying the assume errorbar size } // Top-level routine for managing the GSL minimiser static int FitMinimiseIterate(fitComm *commlink, double(*slave)(const gsl_vector *, void *), unsigned char FittingsigmaData) { ppl_context *c = commlink->c; size_t iter = 0,iter2 = 0; int i, status=0, NParams; double size=0,sizelast=0,sizelast2=0; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; // We don't use nmsimplex2 here because it was new in gsl 1.12 gsl_multimin_fminimizer *s; gsl_vector *x, *ss; gsl_multimin_function fn; if (!FittingsigmaData) NParams = commlink->NParams; else NParams = 1; x = gsl_vector_alloc( NParams ); ss = gsl_vector_alloc( NParams ); fn.n = NParams; fn.f = slave; fn.params = (void *)commlink; iter2=0; do { iter2++; sizelast2 = size; if (!FittingsigmaData) { if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF)for(i=0;iNFitVars;i++) gsl_vector_set(x, i,commlink->varObj[i]->real); else for(i=0;iNFitVars;i++){gsl_vector_set(x,2*i,commlink->varObj[i]->real); gsl_vector_set(x,2*i+1,commlink->varObj[i]->imag); } } else { gsl_vector_set(x,0,commlink->sigmaData); } for (i=0; i1e-6) gsl_vector_set(ss, i, 0.1 * gsl_vector_get(x,i)); else gsl_vector_set(ss, i, 0.1 ); // Avoid having a stepsize of zero } s = gsl_multimin_fminimizer_alloc (T, fn.n); gsl_multimin_fminimizer_set (s, &fn, x, ss); // If initial value we are giving the minimiser produces an algebraic error, it's not worth continuing (*slave)(x,(void *)commlink); if (commlink->errtext[0]!='\0') { gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free(s); return 1; } iter = 0; commlink->goneNaN = 0; do { iter++; for (i=0; i<2+NParams*2; i++) // When you're minimising over many parameters simultaneously sometimes nothing happens for a long time { status = gsl_multimin_fminimizer_iterate(s); if (status) break; } if (status) break; sizelast = size; size = gsl_multimin_fminimizer_minimum(s); } while ((iter < 10) || ((size < sizelast) && (iter < 50))); // Iterate 10 times, and then see whether size carries on getting smaller gsl_multimin_fminimizer_free(s); } while ((iter2 < 3) || ((commlink->goneNaN==0) && (!status) && (size < sizelast2) && (iter2 < 20))); // Iterate 2 times, and then see whether size carries on getting smaller if (iter2>=20) status=1; if (status) { sprintf(commlink->errtext, "Failed to converge. GSL returned error: %s", gsl_strerror(status)); gsl_vector_free(x); gsl_vector_free(ss); return 1; } sizelast = (*slave)(x,(void *)commlink); // Calling minimiser slave now sets all fitting variables to desired values gsl_vector_free(x); gsl_vector_free(ss); return 0; } // Main entry point for the implementation of the fit command void ppl_directive_fit(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk=in->stk; int status=0, Nargs, Nvars, NExpect, Nusing; char *fnName, *scratchPad; long int i, j, k, NDataPoints; int contextLocalVec, contextDataTab, errCount=DATAFILE_NERRS; char *fitVars[USING_ITEMS_MAX]; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX]; pplObj firstVals[USING_ITEMS_MAX], *varObj[USING_ITEMS_MAX]; dataTable *data; dataBlock *blk; parserLine *spool=NULL, **dataSpool = &spool; double *localDataTable, val; gsl_vector *bestFitParamVals; gsl_matrix *hessian, *hessian_lu, *hessian_inv; int sgn; double stdDev[2*USING_ITEMS_MAX], tmp1, tmp2, tmp3; fitComm dataComm; // Structure which we fill with variables we need to pass to the minimiser pplFunc *funcDef; pplObj *funcObj; gsl_permutation *perm; // Get list of fitting variables { int pos = PARSE_fit_fit_variables; Nvars=0; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nvars>=USING_ITEMS_MAX-4) { sprintf(c->errStat.errBuff,"Too many fitting variables; a maximum of %d may be specified.",USING_ITEMS_MAX-4); TBADD2(ERR_SYNTAX,in->stkCharPos[pos+PARSE_fit_fit_variable_fit_variables]); return; } fitVars[Nvars] = (char *)stk[pos+PARSE_fit_fit_variable_fit_variables].auxil; Nvars++; } if (Nvars<1) { sprintf(c->errStat.errBuff,"Too few fitting variables; a minimum of one must be specified."); TBADD2(ERR_SYNTAX,0); return; } } // Get pointers to fitting variables { int i; for (i=0; ierrStat.errBuff,"No such function as '%s()'.",fnName); TBADD2(ERR_NAMESPACE, in->stkCharPos[PARSE_fit_fit_function]); return; } if (funcObj->objType!=PPLOBJ_FUNC) { sprintf(c->errStat.errBuff,"Object '%s' is not a function, but has type <%s>.", fnName, pplObjTypeNames[funcObj->objType]); TBADD2(ERR_TYPE, in->stkCharPos[PARSE_fit_fit_function]); return; } funcDef = (pplFunc *)funcObj->auxil; if (funcDef->functionType==PPL_FUNC_MAGIC) { sprintf(c->errStat.errBuff,"Function %s() needs wrapping in a user-defined function before it can be fit.", fnName); TBADD2(ERR_TYPE, in->stkCharPos[PARSE_fit_fit_function]); return; } __sync_add_and_fetch(&funcDef->refCount,1); Nargs = funcDef->minArgs; // Count length of using list { int hadNonNullUsingItem = 0; int pos = PARSE_fit_using_list; const int o = PARSE_fit_using_item_using_list; Nusing=0; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nusing>=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff, "Too many using items; maximum of %d are allowed.", USING_ITEMS_MAX); TBADD2(ERR_RANGE, in->stkCharPos[pos+o]); goto cleanup; } Nusing++; } if ((!hadNonNullUsingItem) && (Nusing==1)) Nusing=0; // If we've only had one using item, and it was blank, this is a parser abberation } // Work out how many columns of data we're going to read if (Nusing != Nargs+2) NExpect = Nargs+1; else NExpect = Nargs+2; // Only expect weights to go with fitting data if using list has exactly the right length // Read ranges { int i,pos=PARSE_fit_0range_list,nr=0; const int o1 = PARSE_fit_min_0range_list; const int o2 = PARSE_fit_max_0range_list; for (i=0; i=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff,"Too many ranges specified; a maximum of %d are allowed.", USING_ITEMS_MAX); TBADD2(ERR_SYNTAX,0); goto cleanup; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_fit_min_0range_list]); goto cleanup; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_fit_min_0range_list]); goto cleanup; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } nr++; } } // Allocate a new memory context for the data file we're about to read contextLocalVec= ppl_memAlloc_DescendIntoNewContext(); contextDataTab = ppl_memAlloc_DescendIntoNewContext(); // Read data from file ppldata_fromCmd(c, &data, pl, in, 0, NULL, dataSpool, PARSE_TABLE_fit_, 0, NExpect, 0, min, minSet, max, maxSet, unit, 0, &status, c->errStat.errBuff, &errCount, iterDepth); // Exit on error if ((status)||(data==NULL)) { TBADD2(ERR_GENERIC,0); ppl_memAlloc_AscendOutOfContext(contextLocalVec); goto cleanup; } // Check that the firstEntries above have the same units as any supplied ranges for (j=0; jfirstEntries+j)) { sprintf(c->errStat.errBuff, "The minimum and maximum limits specified in range %ld in the fit command have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", j+1, ppl_printUnit(c,unit+j,NULL,NULL,0,1,0), ppl_printUnit(c,data->firstEntries+j,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); goto cleanup; } } // Work out how many data points we have within the specified ranges NDataPoints = 0; blk = data->first; while (blk != NULL) { int j; for (j=0; jblockPosition; j++) { int inRange=1, k; for (k=0; kdata_real[k + NExpect*j]; if ( (minSet[k]&&(valmax[k])) ) { inRange=0; break; } // Check that value is within range } if (inRange) NDataPoints++; } blk=blk->next; } // Copy data into a new table and apply the specified ranges to it localDataTable = (double *)ppl_memAlloc_incontext(NDataPoints * NExpect * sizeof(double), contextLocalVec); if (localDataTable==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); goto cleanup; } i=0; blk = data->first; while (blk != NULL) { int j; for (j=0; jblockPosition; j++) { int inRange=1, k; for (k=0; kdata_real[k + NExpect*j]; if ( (minSet[k]&&(valmax[k])) ) { inRange=0; break; } // Check that value is within range localDataTable[i * NExpect + k] = val; } if (inRange) i++; } blk=blk->next; } // Make a copy of the physical units of all of the columns of data for (j=0; jfirstEntries[j]; // Free original data table which is no longer needed ppl_memAlloc_AscendOutOfContext(contextDataTab); data = NULL; // Populate dataComm dataComm.c = c; dataComm.pl = pl; dataComm.functionName = fnName; dataComm.functionObj = funcObj; dataComm.NFitVars = Nvars; dataComm.NArgs = Nargs; dataComm.NExpect = NExpect; dataComm.NParams = dataComm.NFitVars * ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) ? 1 : 2); dataComm.NDataPoints = NDataPoints; dataComm.varObj = varObj; dataComm.paramVals = NULL; dataComm.bestFitParamVals = NULL; dataComm.firstVals = firstVals; dataComm.dataTable = localDataTable; dataComm.flagYErrorBars = (NExpect == Nargs+2); dataComm.sigmaData = 1.0; dataComm.errtext = (char *)ppl_memAlloc_incontext(LSTR_LENGTH, contextLocalVec); scratchPad = (char *)ppl_memAlloc_incontext(LSTR_LENGTH, contextLocalVec); if ((scratchPad==NULL)||(dataComm.errtext==NULL)) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); goto cleanup; } dataComm.errtext[0] = '\0'; // Set up a minimiser status = FitMinimiseIterate(&dataComm, &ResidualMinimiserSlave, 0); if (status) { sprintf(c->errStat.errBuff, "%s", dataComm.errtext); TBADD2(ERR_NUMERICAL,0); goto cleanup; } // Display the results of the minimiser ppl_report(&c->errcontext,"\n# Best fit parameters were:\n# -------------------------\n"); for (j=0; jset->term_current.NumDisplay != SW_DISPLAY_L) sprintf(c->errcontext.tempErrStr, "%s = %s", fitVars[j], ppl_unitsNumericDisplay(c,varObj[j],0,0,0) ); else sprintf(c->errcontext.tempErrStr, "$%s = %s", fitVars[j], ppl_unitsNumericDisplay(c,varObj[j],0,0,0)+1); ppl_report(&c->errcontext,NULL); } // If 'withouterrors' is specified, stop now if (stk[PARSE_fit_withouterrors].objType==PPLOBJ_STR) { ppl_memAlloc_AscendOutOfContext(contextLocalVec); goto cleanup; } // Store best-fit position bestFitParamVals = gsl_vector_alloc(dataComm.NParams); for (i=0; iset->term_current.ComplexNumbers == SW_ONOFF_OFF) gsl_vector_set(bestFitParamVals, i , varObj[i]->real); else { gsl_vector_set(bestFitParamVals, 2*i , varObj[i]->real); gsl_vector_set(bestFitParamVals, 2*i+1, varObj[i]->imag); } dataComm.bestFitParamVals = bestFitParamVals; // Estimate the size of the errorbars on the supplied data if no errorbars were supplied (this doesn't affect best fit position, but does affect error estimates) if (!dataComm.flagYErrorBars) { sprintf(c->errcontext.tempErrStr, "\n# Estimating the size of the error bars on supplied data.\n# This may take a while.\n# The fit command can be made to run very substantially faster if the 'withouterrors' option is set."); ppl_report(&c->errcontext,NULL); status = FitMinimiseIterate(&dataComm, &FitsigmaData, 1); if (status) { sprintf(c->errStat.errBuff, "%s", dataComm.errtext); TBADD2(ERR_NUMERICAL,0); gsl_vector_free(bestFitParamVals); goto cleanup; } firstVals[Nargs].real = dataComm.sigmaData; firstVals[Nargs].imag = 0.0; firstVals[Nargs].flagComplex = 0; sprintf(c->errcontext.tempErrStr, "\n# Estimate of error bars on supplied data, based on their fit to model function = %s", ppl_unitsNumericDisplay(c,firstVals+Nargs,0,0,0)); ppl_report(&c->errcontext,NULL); } // Calculate and print the Hessian matrix hessian = GetHessian(&dataComm); matrixPrint(c, hessian, dataComm.NParams, scratchPad); sprintf(c->errcontext.tempErrStr, "\n# Hessian matrix of log-probability distribution:\n# -----------------------------------------------\n\nhessian = %s", scratchPad); ppl_report(&c->errcontext,NULL); // Set variables in user's variable space to best-fit values for (i=0; iset->term_current.ComplexNumbers == SW_ONOFF_OFF) varObj[i]->real = gsl_vector_get(dataComm.bestFitParamVals, i ); else { varObj[i]->real = gsl_vector_get(dataComm.bestFitParamVals, 2*i ); varObj[i]->imag = gsl_vector_get(dataComm.bestFitParamVals, 2*i+1); } // Calculate and print the covariance matrix hessian_lu = gsl_matrix_alloc(dataComm.NParams, dataComm.NParams); hessian_inv = gsl_matrix_alloc(dataComm.NParams, dataComm.NParams); gsl_matrix_memcpy(hessian_lu, hessian); gsl_matrix_scale(hessian_lu, -1.0); // Want the inverse of -H perm = gsl_permutation_alloc(dataComm.NParams); gsl_linalg_LU_decomp(hessian_lu,perm,&sgn); gsl_linalg_LU_invert(hessian_lu,perm,hessian_inv); matrixPrint(c, hessian_inv, dataComm.NParams, scratchPad); sprintf(c->errcontext.tempErrStr, "\n# Covariance matrix of probability distribution:\n# ----------------------------------------------\n\ncovariance = %s", scratchPad); ppl_report(&c->errcontext,NULL); // Calculate the standard deviation of each parameter for (i=0; ierrcontext.tempErrStr, "One of the calculated variances for the fitted parameters is negative. This strongly suggests that the fitting process has failed."); ppl_warning(&c->errcontext, ERR_NUMERICAL, NULL); stdDev[i] = 1e-100; } else { stdDev[i] = sqrt( gsl_matrix_get(hessian_inv, i, i) ); } } // Calculate the correlation matrix for (i=0; ierrcontext.tempErrStr, "\n# Correlation matrix of probability distribution:\n# ----------------------------------------------\n\ncorrelation = %s", scratchPad); ppl_report(&c->errcontext,NULL); // Print a list of standard deviations ppl_report(&c->errcontext,"\n# Uncertainties in best-fit parameters are:\n# -----------------------------------------\n"); for (i=0; iset->term_current.ComplexNumbers == SW_ONOFF_OFF) { dummyTemp.real = stdDev[i] ; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; // Apply appropriate unit to standard deviation, which is currently just a double if (c->set->term_current.NumDisplay != SW_DISPLAY_L) { sprintf(scratchPad, "sigma_%s", fitVars[i]); sprintf(c->errcontext.tempErrStr, "%22s = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)); } else { sprintf(scratchPad, "$\\sigma_\\textrm{"); j = strlen(scratchPad); for (k=0; fitVars[i][k]!='\0'; k++) { if (fitVars[i][k]=='_') scratchPad[j++]='\\'; scratchPad[j++]=fitVars[i][k]; } scratchPad[j++]='\0'; sprintf(c->errcontext.tempErrStr, "%33s} = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)+1); } ppl_report(&c->errcontext,NULL); } else { if (c->set->term_current.NumDisplay != SW_DISPLAY_L) { dummyTemp.real = stdDev[2*i ] ; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; sprintf(scratchPad, "sigma_%s_real", fitVars[i]); sprintf(c->errcontext.tempErrStr, "%27s = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)); ppl_report(&c->errcontext,NULL); dummyTemp.real = stdDev[2*i+1] ; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; sprintf(scratchPad, "sigma_%s_imag", fitVars[i]); sprintf(c->errcontext.tempErrStr, "%27s = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)); ppl_report(&c->errcontext,NULL); } else { dummyTemp.real = stdDev[2*i ] ; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; sprintf(scratchPad, "$\\sigma_\\textrm{"); j = strlen(scratchPad); for (k=0; fitVars[i][k]!='\0'; k++) { if (fitVars[i][k]=='_') scratchPad[j++]='\\'; scratchPad[j++]=fitVars[i][k]; } scratchPad[j++]='\0'; sprintf(c->errcontext.tempErrStr, "%38s,real} = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)+1); ppl_report(&c->errcontext,NULL); dummyTemp.real = stdDev[2*i+1] ; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; sprintf(c->errcontext.tempErrStr, "%38s,imag} = %s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,0,0,0)+1); ppl_report(&c->errcontext,NULL); } } } // Print summary information ppl_report(&c->errcontext,"\n# Summary:\n# --------\n"); for (i=0; ireal)>1e-200) tmp3 = tmp1 / varObj[i]->real; // Set tmp3 to be the multiplicative size of this unit relative to its SI counterpart else if (fabs(varObj[i]->imag)>1e-200) tmp3 = tmp2 / varObj[i]->imag; // Can't do this if magnitude of best-fit value is zero, though... else { dummyTemp = *(varObj[i]); dummyTemp.real = 1.0; dummyTemp.imag = 0.0; dummyTemp.flagComplex = 0; // If best-fit value is zero, use the unit we would use for unity instead. cptr = ppl_printUnit(c, &dummyTemp, &tmp1, &tmp2, 0, 1, 0); tmp3 = tmp1; } pplObjNum(&dummyTemp,0,tmp1,tmp2); dummyTemp.refCount=1; if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { if (c->set->term_current.NumDisplay != SW_DISPLAY_L) sprintf(c->errcontext.tempErrStr, "%16s = (%s +/- %s) %s", fitVars[i], ppl_unitsNumericDisplay(c,&dummyTemp,1,0,0), ppl_numericDisplay(stdDev[i]*tmp3,c->numdispBuff[0],c->set->term_current.SignificantFigures,0), cptr); else { scratchPad[0]='$'; for (j=1,k=0; fitVars[i][k]!='\0'; k++) { if (fitVars[i][k]=='_') scratchPad[j++]='\\'; scratchPad[j++]=fitVars[i][k]; } scratchPad[j++]='\0'; sprintf(c->errcontext.tempErrStr, "%17s = (%s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,1,0,0)+1); j=strlen(c->errcontext.tempErrStr)-1; // Remove final $ sprintf(c->errcontext.tempErrStr+j, "\\pm%s)%s$", ppl_numericDisplay(stdDev[i]*tmp3,c->numdispBuff[0],c->set->term_current.SignificantFigures,0), cptr); } } else { if (c->set->term_current.NumDisplay == SW_DISPLAY_T) sprintf(c->errcontext.tempErrStr, "%16s = (%s +/- %s +/- %s*sqrt(-1))%s", fitVars[i], ppl_unitsNumericDisplay(c,&dummyTemp,1,0,0), ppl_numericDisplay(stdDev[2*i]*tmp3,c->numdispBuff[0],c->set->term_current.SignificantFigures,0), ppl_numericDisplay(stdDev[2*i+1]*tmp3,c->numdispBuff[2],c->set->term_current.SignificantFigures,0), cptr); else if (c->set->term_current.NumDisplay == SW_DISPLAY_L) { scratchPad[0]='$'; for (j=1,k=0; fitVars[i][k]!='\0'; k++) { if (fitVars[i][k]=='_') scratchPad[j++]='\\'; scratchPad[j++]=fitVars[i][k]; } scratchPad[j++]='\0'; sprintf(c->errcontext.tempErrStr, "%17s = (%s", scratchPad, ppl_unitsNumericDisplay(c,&dummyTemp,1,0,0)+1); j=strlen(c->errcontext.tempErrStr)-1; // Remove final $ sprintf(c->errcontext.tempErrStr+j, "\\pm %s\\pm %si)%s$", ppl_numericDisplay(stdDev[2*i]*tmp3,c->numdispBuff[0],c->set->term_current.SignificantFigures,0), ppl_numericDisplay(stdDev[2*i+1]*tmp3,c->numdispBuff[2],c->set->term_current.SignificantFigures,0), cptr); } else sprintf(c->errcontext.tempErrStr, "%16s = (%s +/- %s +/- %si) %s", fitVars[i], ppl_unitsNumericDisplay(c,&dummyTemp,1,0,0), ppl_numericDisplay(stdDev[2*i]*tmp3,c->numdispBuff[0],c->set->term_current.SignificantFigures,0), ppl_numericDisplay(stdDev[2*i+1]*tmp3,c->numdispBuff[2],c->set->term_current.SignificantFigures,0), cptr); } ppl_report(&c->errcontext,NULL); } // We're finished... can now free dataTable gsl_vector_free(bestFitParamVals); gsl_matrix_free(hessian_inv); gsl_matrix_free(hessian_lu); gsl_matrix_free(hessian); gsl_permutation_free(perm); ppl_memAlloc_AscendOutOfContext(contextLocalVec); cleanup: __sync_sub_and_fetch(&funcDef->refCount,1); return; } pyxplot-0.9.2/src/commands/interpolate_2d_engine.c0000664000175000017500000001416012026340554020622 0ustar dcf21dcf21// interpolate_2d_engine.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: interpolate_2d_engine.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _INTERPOLATION2D_C 1 #include #include #include #include #include "commands/interpolate_2d_engine.h" #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "settings/axes_fns.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/strConstants.h" #include "userspace/context.h" #include "datafile.h" void ppl_interp2d_eval(ppl_context *c, double *output, const pplset_graph *sg, const double *in, const long InSize, const int ColNum, const int NCols, const double x, const double y) { long i; const double *inX = in; const double *inY = in + InSize; const double *inZ = in + ColNum*InSize; const double Xscl = in[NCols*(InSize+1) ] - in[NCols*InSize ]; const double Yscl = in[NCols*(InSize+1) + 1 ] - in[NCols*InSize + 1 ]; switch (sg->Sample2DMethod) { case SW_SAMPLEMETHOD_NEAREST: { double DistBest=0; unsigned char first=1; *output = 0.0; for (i=0; i0.0) *output /= WeightSum; break; } case SW_SAMPLEMETHOD_ML: { double WeightSum = 0.0; double h = sqrt( 1.0/InSize ); *output = 0.0; for (i=0; i=2)?0.0:((v>=1)?(0.25*gsl_pow_3(2.0-v)):(1.0-1.5*gsl_pow_2(v)+0.75*gsl_pow_3(v))); if (!gsl_finite(w)) continue; *output += w * inZ[i]; WeightSum += w; } if (WeightSum>0.0) *output /= WeightSum; else *output = GSL_NAN; break; } default: { *output = 0.0; break; } } return; } void ppl_interp2d_grid(ppl_context *c, dataTable **output, const pplset_graph *sg, dataTable *in, pplset_axis *axis_x, pplset_axis *axis_y, unsigned char SampleToEdge, int *XSizeOut, int *YSizeOut) { int i, imax, j, jmax, ims, jms, ct, k, tempContext; double *indata, *MinList, *MaxList, *d[USING_ITEMS_MAX+4]; long p, p2, pc, InSize; dataBlock *blk; imax = (sg->SamplesXAuto == SW_BOOL_TRUE) ? sg->samples : sg->SamplesX; jmax = (sg->SamplesYAuto == SW_BOOL_TRUE) ? sg->samples : sg->SamplesY; *XSizeOut = imax; *YSizeOut = jmax; // If input data is NULL, return NULL if (in==NULL) { *output=NULL; return; } k = in->Ncolumns_real; *output = ppldata_NewDataTable(k, 0, ppl_memAlloc_GetMemContext(), imax*jmax); if (*output == NULL) return; // Memory fail InSize = in->Nrows; (*output)->firstEntries = in->firstEntries; p2 = (*output)->current->blockPosition = (*output)->Nrows = imax*jmax; for (pc=0; pccurrent->split [pc] = 0; for (pc=0; pccurrent->text [pc] = NULL; for (pc=0; pccurrent->fileLine_real[pc] = 0; // Extract data into a temporary array tempContext = ppl_memAlloc_DescendIntoNewContext(); indata = (double *)ppl_memAlloc(k * (InSize+2) * sizeof(double)); if (indata==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory whilst resampling data."); *output=NULL; return; } for (ct=0; ctfirst; while (blk != NULL) { for (ct=0; ctblockPosition; j++) *(d[ct]++) = blk->data_real[ct + k*j]; blk=blk->next; } // Fill out minimum and maximum of data for (jms=0; jmsindata[jms*InSize+ims])) MinList[jms] = indata[jms*InSize+ims]; if ((ims==0)||(MaxList[jms]current->data_real[p++] = x; (*output)->current->data_real[p++] = y; for (ct=2; ctcurrent->data_real[p++], sg, indata, InSize, ct, k, x, y); } } // Delete temporary array ppl_memAlloc_AscendOutOfContext(tempContext); return; } pyxplot-0.9.2/src/commands/show.h0000664000175000017500000000176612026340554015357 0ustar dcf21dcf21// show.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: show.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _SHOW_H #define _SHOW_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_show(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); #endif pyxplot-0.9.2/src/commands/tabulate.h0000664000175000017500000000203212026340554016163 0ustar dcf21dcf21// tabulate.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: tabulate.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _TABULATE_H #define _TABULATE_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_tabulate(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/commands/help.h0000664000175000017500000000176712026340554015330 0ustar dcf21dcf21// help.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: help.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _HELP_H #define _HELP_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_help(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); #endif pyxplot-0.9.2/src/commands/fft.h0000664000175000017500000000224412026340554015146 0ustar dcf21dcf21// fft.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fft.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _FFT_H #define _FFT_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" void ppl_directive_fft(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_fft_evaluate (ppl_context *c, char *FuncName, FFTDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout); #endif pyxplot-0.9.2/src/commands/set.c0000664000175000017500000033700112026340554015157 0ustar dcf21dcf21// set.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: set.c 1302 2012-09-05 17:30:27Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include "commands/set.h" #include "coreUtils/dict.h" #include "coreUtils/memAlloc.h" #include "coreUtils/list.h" #include "defaultObjs/moduleRandom.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/arrows_fns.h" #include "settings/axes_fns.h" #include "settings/colors.h" #include "settings/epsColors.h" #include "settings/labels_fns.h" #include "settings/papersizes.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "settings/withWords_fns.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/pplObjPrint.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "canvasItems.h" #include "children.h" #include "pplConstants.h" #define TBADD(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define GET_AXISLOG(OUT,AXIS,DEFAULT) \ { \ pplset_axis *ai = (AXIS); \ int C=0, *out=&ai->log; \ while ((ai->linked)&&(C<100)) \ { \ if (ai->LinkedAxisCanvasID > 0) { out=&(AXIS)->log; *out=0; } \ if (!DEFAULT) \ { \ if (ai->LinkedAxisToXYZ == 0) ai = xa + ai->LinkedAxisToNum; \ else if (ai->LinkedAxisToXYZ == 1) ai = ya + ai->LinkedAxisToNum; \ else ai = za + ai->LinkedAxisToNum; \ } \ else \ { \ if (ai->LinkedAxisToXYZ == 0) ai = c->set->XAxesDefault + ai->LinkedAxisToNum; \ else if (ai->LinkedAxisToXYZ == 1) ai = c->set->YAxesDefault + ai->LinkedAxisToNum; \ else ai = c->set->ZAxesDefault + ai->LinkedAxisToNum; \ } \ C++; \ if (!ai->enabled) { out=&(AXIS)->log; *out=0; break; } \ out=&ai->log; \ } \ OUT=out; \ } static void tics_rm(pplset_tics *a) { a->tickMinSet = a->tickMaxSet = a->tickStepSet = 0; if (a->tickList!=NULL) { free(a->tickList); a->tickList=NULL; } if (a->tickStrs!=NULL) { int i; for (i=0; a->tickStrs[i]!=NULL; i++) { free(a->tickStrs[i]); } free(a->tickStrs); a->tickStrs=NULL; } } static void tics_cp(pplset_tics *o, pplset_tics *i) { *o = *i; if (i->tickList!=NULL) { int j,l; for (l=0; i->tickStrs[l]!=NULL; l++); o->tickList = (double *)malloc((l+1)*sizeof(double)); o->tickStrs = (char **)malloc((l+1)*sizeof(char *)); if ((o->tickList==NULL)||(o->tickStrs==NULL)) { o->tickList=NULL; o->tickStrs=NULL; return; } memcpy(o->tickList, i->tickList, (l+1)*sizeof(double)); for (j=0; jtickStrs[j] = (char *)malloc(strlen(i->tickStrs[j])+1); if (o->tickStrs[j]==NULL) { o->tickList=NULL; o->tickStrs=NULL; return; } strcpy(o->tickStrs[j], i->tickStrs[j]); } } } #define SET_NOTICKS(T) \ { \ tics_rm(&(T)); \ T.tickList=(double *)malloc(sizeof(double)); \ T.tickStrs=(char **)malloc(sizeof(char *)); \ T.tickStrs[0]=NULL; \ } #define SET_TICKS(T,TO,U,US,amLog) \ { \ const int gotAuto = ((ptab[PARSE_INDEX_autofreq ]>0) && (command[ptab[PARSE_INDEX_autofreq ]].objType==PPLOBJ_STR)); \ const int gotRange = ((ptab[PARSE_INDEX_start ]>0) && (command[ptab[PARSE_INDEX_start ]].objType==PPLOBJ_NUM)); \ const int gotList = ((ptab[PARSE_INDEX_got_list ]>0) && (command[ptab[PARSE_INDEX_got_list ]].objType==PPLOBJ_STR)); \ if ((ptab[PARSE_INDEX_dir]>0) && (command[ptab[PARSE_INDEX_dir]].objType==PPLOBJ_STR)) \ { \ (T).tickDir = ppl_fetchSettingByName(&c->errcontext, (char *)command[ptab[PARSE_INDEX_dir]].auxil, SW_TICDIR_INT, SW_TICDIR_STR); \ } \ if (gotAuto || gotRange || gotList) tics_rm(&(T)); \ if (gotRange) \ { \ int gotStart = ((ptab[PARSE_INDEX_start ]>0) && (command[ptab[PARSE_INDEX_start ]].objType==PPLOBJ_NUM)); \ int gotIncr = ((ptab[PARSE_INDEX_increment ]>0) && (command[ptab[PARSE_INDEX_increment ]].objType==PPLOBJ_NUM)); \ int gotEnd = ((ptab[PARSE_INDEX_end ]>0) && (command[ptab[PARSE_INDEX_end ]].objType==PPLOBJ_NUM)); \ pplObj *objstart = &command[ptab[PARSE_INDEX_start ]]; \ pplObj *objincr = &command[ptab[PARSE_INDEX_increment ]]; \ pplObj *objend = &command[ptab[PARSE_INDEX_end ]]; \ double start = objstart->real; \ double incr = objincr ->real; \ double end = objend ->real; \ if (!gotIncr) { objincr=objstart; incr=start; gotIncr=1; gotStart=0; } /* if only one number given, it is increment */ \ \ if((gotStart && gotIncr && !amLog) && (!ppl_unitsDimEqual(objstart,objincr))) { sprintf(c->errcontext.tempErrStr, "Start value for axis ticks has conflicting units with step size. Units of the start value are <%s>; units of the step size are <%s>.", ppl_printUnit(c, objstart, NULL, NULL, 0, 1, 0), ppl_printUnit(c, objincr, NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ if((gotStart && gotEnd ) && (!ppl_unitsDimEqual(objstart,objend ))) { sprintf(c->errcontext.tempErrStr, "Start value for axis ticks has conflicting units with end value. Units of the start value are <%s>; units of the end value are <%s>.", ppl_printUnit(c, objstart, NULL, NULL, 0, 1, 0), ppl_printUnit(c, objend, NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ if (amLog && (!objincr->dimensionless)) { sprintf(c->errcontext.tempErrStr, "Invalid step size for axis ticks. On a log axis, step size should be a dimensionless multiplier; supplied step size has units of <%s>.", ppl_printUnit(c, objincr, NULL, NULL, 0, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ if (gotStart && (!gsl_finite(start))) { sprintf(c->errcontext.tempErrStr, "Invalid starting value for axis ticks. Value supplied is not finite."); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); return; } \ if (gotIncr && (!gsl_finite(incr ))) { sprintf(c->errcontext.tempErrStr, "Invalid step size for axis ticks. Value supplied is not finite."); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); return; } \ if (gotEnd && (!gsl_finite(end ))) { sprintf(c->errcontext.tempErrStr, "Invalid end value for axis ticks. Value supplied is not finite."); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); return; } \ if ((!amLog)||(gotStart)) \ { \ pplObj *o = amLog ? objstart : objincr; \ if ((US)&&(!ppl_unitsDimEqual(o,&(U)))) { sprintf(c->errcontext.tempErrStr, "Tick positions supplied to the '%s' command have units of <%s>, which conflicts with the axis range which has units of <%s>.", cmd, ppl_printUnit(c, o, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &(U), NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ if (!ppl_unitsDimEqual(o,&(U))) { tics_rm(&(TO)); U=*o; } \ } \ \ if (((T).tickMinSet = gotStart)) (T).tickMin = start; \ if (((T).tickStepSet = gotIncr )) (T).tickStep = incr; \ if (((T).tickMaxSet = gotEnd )) (T).tickMax = end; \ } \ else if (gotList) \ { \ int pos = ptab[PARSE_INDEX_0tick_list]; \ const int x = ptab[PARSE_INDEX_x]; \ const int lab = ptab[PARSE_INDEX_label]; \ int i=0; \ pplObj *first=NULL; \ \ while (command[pos].objType==PPLOBJ_NUM) \ { \ pplObj *ox, *ol; \ pos = (int)round(command[pos].real); \ if (pos<=0) break; \ ox = &command[pos+x]; \ ol = &command[pos+lab]; \ if((ox->objType == PPLOBJ_STR) && ((ol->objType==PPLOBJ_NUM)||(ol->objType==PPLOBJ_BOOL)||(ol->objType==PPLOBJ_DATE)) ) { pplObj *tmp=ol; ol=ox; ox=tmp; } \ if (ox->objType != PPLOBJ_NUM) { sprintf(c->errcontext.tempErrStr, "Ticks can only be set at numeric values; supplied value is of type <%s>.", pplObjTypeNames[ox->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } \ if ((ol->objType != PPLOBJ_ZOM) && (ol->objType != PPLOBJ_STR)) \ { sprintf(c->errcontext.tempErrStr, "Ticks labels must be strings; supplied value is of type <%s>.", pplObjTypeNames[ol->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } \ if (!gsl_finite(ox->real)) { sprintf(c->errcontext.tempErrStr, "Ticks can only be set at finite numeric values; supplied value is not finite."); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } \ if (ox->flagComplex) { sprintf(c->errcontext.tempErrStr, "Ticks can only be set at real numeric values; supplied value is complex."); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } \ if (i==0) \ { \ first=ox; \ if ((US)&&(!ppl_unitsDimEqual(first,&(U)))) { sprintf(c->errcontext.tempErrStr, "Tick positions supplied to the '%s' command have units of <%s>, which conflicts with the axis range which has units of <%s>.", cmd, ppl_printUnit(c, first, NULL, NULL, 0, 1, 0), ppl_printUnit(c, &(U), NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ if (!ppl_unitsDimEqual(first,&(U))) { tics_rm(&(TO)); U=*first; } \ } \ else if (!ppl_unitsDimEqual(first,ox)) { sprintf(c->errcontext.tempErrStr, "Tick positions supplied to the '%s' command must all have the same physical units; supplied list has multiple units, including <%s> and <%s>.", cmd, ppl_printUnit(c, first, NULL, NULL, 0, 1, 0), ppl_printUnit(c, ox, NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } \ i++; \ } \ (T).tickList = (double *)malloc((i+1)*sizeof(double)); \ (T).tickStrs = (char **)malloc((i+1)*sizeof(char *)); \ pos = ptab[PARSE_INDEX_0tick_list]; \ i=0; \ while (command[pos].objType==PPLOBJ_NUM) \ { \ pplObj *ox, *ol; \ char *label; \ pos = (int)round(command[pos].real); \ if (pos<=0) break; \ ox = &command[pos+x]; \ ol = &command[pos+lab]; \ if (ox->objType == PPLOBJ_STR) { pplObj *tmp=ol; ol=ox; ox=tmp; } \ (T).tickList[i] = ox->real; \ label = (ol->objType==PPLOBJ_STR) ? ((char *)ol->auxil) : ("\xFF"); \ (T).tickStrs[i] = (char *)malloc(strlen(label)+1); \ if ((T).tickStrs[i] == NULL) { sprintf(c->errcontext.tempErrStr, "Out of memory."); ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, NULL); return; } \ strcpy((T).tickStrs[i], label); \ i++; \ } \ (T).tickStrs[i] = NULL; \ } \ } void ppl_directive_set(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplset_graph *sg; pplarrow_object **al; ppllabel_object **ll; pplset_axis *xa, *ya, *za; pplObj *command = in->stk; int i, strcmp_set, strcmp_unset; int gotEditNo = (command[PARSE_arc_editno].objType == PPLOBJ_NUM); char *directive, *setoption; if (!gotEditNo) { sg = &c->set->graph_current; al = &c->set->pplarrow_list; ll = &c->set->ppllabel_list; xa = c->set->XAxes; ya = c->set->YAxes; za = c->set->ZAxes; } else { canvas_itemlist *canvas_items = (canvas_itemlist *)c->canvas_items; int editNo = (int)round(command[PARSE_arc_editno].real); canvas_item *ptr; if ((editNo < 1) || (editNo>MULTIPLOT_MAXINDEX) || (canvas_items == NULL)) {sprintf(c->errcontext.tempErrStr, "No multiplot item with index %d.", editNo); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return;} ptr = canvas_items->first; while ((ptr!=NULL)&&(ptr->id!=editNo)) ptr=ptr->next; if (ptr == NULL) { sprintf(c->errcontext.tempErrStr, "No multiplot item with index %d.", editNo); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } sg = &(ptr->settings); al = &(ptr->arrow_list); ll = &(ptr->label_list); xa = ptr->XAxes; ya = ptr->YAxes; za = ptr->ZAxes; if ((xa==NULL)||(ya==NULL)||(za==NULL)) { al=NULL; ll=NULL; } // Objects which do not store axes also do not store any text labels or arrows } directive = (char *)command[PARSE_arc_directive].auxil; setoption = (char *)command[PARSE_arc_set_option].auxil; strcmp_set = (strcmp(directive,"set")==0); strcmp_unset = (strcmp(directive,"unset")==0); if (strcmp_set && (strcmp(setoption,"arrow")==0)) /* set arrow */ { if (al!=NULL) pplarrow_add(c, al, in, pl, PARSE_TABLE_set_arrow_); } else if (strcmp_unset && (strcmp(setoption,"arrow")==0)) /* unset arrow */ { if (al!=NULL) pplarrow_unset(c, al, in, pl, PARSE_TABLE_unset_arrow_); } else if ((strcmp(setoption,"autoscale")==0)) /* set autoscale | unset autoscale */ { #define SET_AUTOSCALE_AXIS \ { \ pplset_axis *a, *ad; \ if (j==1) { a = &ya[i]; ad = &c->set->YAxesDefault[i]; } \ else if (j==2) { a = &za[i]; ad = &c->set->ZAxesDefault[i]; } \ else { a = &xa[i]; ad = &c->set->XAxesDefault[i]; } \ if (set && ((!SetAll) || (a->enabled))) \ { \ a->enabled = 1; \ a->MinSet = SW_BOOL_FALSE; \ a->MaxSet = SW_BOOL_FALSE; \ } else { \ a->MinSet = ad->MinSet; \ a->MaxSet = ad->MaxSet; \ } \ a->min = ad->min; \ a->max = ad->max; \ } if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { unsigned char set = strcmp_set; int pos = PARSE_set_autoscale_0axes; unsigned char SetAll = (command[pos].objType!=PPLOBJ_NUM); if (!SetAll) while (command[pos].objType==PPLOBJ_NUM) { int i,j; pos = (int)round(command[pos].real); if (pos<=0) break; i = (int)round(command[pos+PARSE_set_autoscale_axis_0axes].real); j = (int)round(command[pos+PARSE_set_autoscale_axis_0axes].exponent[0]); SET_AUTOSCALE_AXIS; } else { int i,j; for (j=0; j<2; j++) for (i=0; iset->YAxesDefault[anum]; } else if (i==2) { a=&za[anum]; ad = &c->set->ZAxesDefault[anum]; } else { a=&xa[anum]; ad = &c->set->XAxesDefault[anum]; } a->enabled=1; if (command[PARSE_set_axis_invisible].objType==PPLOBJ_STR) a->invisible=1; if (command[PARSE_set_axis_visible ].objType==PPLOBJ_STR) a->invisible=0; if (command[PARSE_set_axis_atzero ].objType==PPLOBJ_STR) a->atzero =1; if (command[PARSE_set_axis_notatzero].objType==PPLOBJ_STR) a->atzero =0; if (command[PARSE_set_axis_linked ].objType==PPLOBJ_STR) a->linked =1; if (command[PARSE_set_axis_notlinked].objType==PPLOBJ_STR) a->linked =0; if (command[PARSE_set_axis_xorient ].objType==PPLOBJ_STR) { if (i!=0) ppl_warning(&c->errcontext, ERR_SYNTAX, "Can only specify the positions 'top' or 'bottom' for x axes."); else a->topbottom=(strcmp((char *)command[PARSE_set_axis_xorient].auxil,"on")==0); } if (command[PARSE_set_axis_yorient ].objType==PPLOBJ_STR) { if (i!=1) ppl_warning(&c->errcontext, ERR_SYNTAX, "Can only specify the positions 'left' and 'right' for y axes."); else a->topbottom=(strcmp((char *)command[PARSE_set_axis_yorient].auxil,"on")==0); } if (command[PARSE_set_axis_zorient ].objType==PPLOBJ_STR) { if (i!=2) ppl_warning(&c->errcontext, ERR_SYNTAX, "Can only specify the positions 'front' and 'back' for z axes."); else a->topbottom=(strcmp((char *)command[PARSE_set_axis_zorient].auxil,"on")==0); } if (command[PARSE_set_axis_mirror ].objType==PPLOBJ_STR) a->MirrorType = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_axis_mirror ].auxil, SW_AXISMIRROR_INT, SW_AXISMIRROR_STR); if (command[PARSE_set_axis_axisdisp ].objType==PPLOBJ_STR) a->ArrowType = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_axis_axisdisp].auxil, SW_AXISDISP_INT, SW_AXISDISP_STR); if (command[PARSE_set_axis_linkaxis ].objType==PPLOBJ_NUM) { int j = (int)round(command[PARSE_set_axis_linkaxis].real); if (a->linkusing!=NULL) { pplExpr_free((pplExpr *)a->linkusing); a->linkusing=ad->linkusing; if (a->linkusing!=NULL) ((pplExpr *)a->linkusing)->refCount++; } a->LinkedAxisCanvasID = -1; a->LinkedAxisToNum = j; a->LinkedAxisToXYZ = (int)round(command[PARSE_set_axis_linkaxis].exponent[0]); } if (command[PARSE_set_axis_linktoid].objType==PPLOBJ_NUM) { a->LinkedAxisCanvasID = (int)round(command[PARSE_set_axis_linktoid].real); } if (command[PARSE_set_axis_usingexp].objType==PPLOBJ_EXP) { if (a->linkusing!=NULL) pplExpr_free((pplExpr *)a->linkusing); a->linkusing = (void *)pplExpr_cpy((pplExpr *)command[PARSE_set_axis_usingexp].auxil); } } } else if (strcmp_unset && (strcmp(setoption,"axis")==0)) /* unset axis */ { int pos = PARSE_unset_axis_0axes; if (command[pos].objType!=PPLOBJ_NUM) { int i; for (i=0; iset->XAxesDefault[i])); } for (i=0; iset->YAxesDefault[i])); } for (i=0; iset->ZAxesDefault[i])); } } else { int i, anum; while (command[pos].objType==PPLOBJ_NUM) { pos = (int)round(command[pos].real); if (pos<=0) break; anum = (int)round(command[pos+PARSE_unset_axis_axis_axes].real); i = (int)round(command[pos+PARSE_unset_axis_axis_axes].exponent[0]); if (i==1) { pplaxis_destroy(c, &(ya[anum]) ); pplaxis_copy(c, &(ya[anum]), &(c->set->YAxesDefault[anum])); } else if (i==2) { pplaxis_destroy(c, &(za[anum]) ); pplaxis_copy(c, &(za[anum]), &(c->set->ZAxesDefault[anum])); } else { pplaxis_destroy(c, &(xa[anum]) ); pplaxis_copy(c, &(xa[anum]), &(c->set->XAxesDefault[anum])); } } } } else if (strcmp_set && (strcmp(setoption,"axisunitstyle")==0)) /* set axisunitstyle */ { sg->AxisUnitStyle = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_axisunitstyle_unitstyle].auxil, SW_AXISUNITSTY_INT, SW_AXISUNITSTY_STR); } else if (strcmp_unset && (strcmp(setoption,"axisunitstyle")==0)) /* unset axisunitstyle */ { sg->AxisUnitStyle = c->set->graph_default.AxisUnitStyle; } else if (strcmp_set && (strcmp(setoption,"backup")==0)) /* set backup */ { c->set->term_current.backup = SW_ONOFF_ON; } else if (strcmp_unset && (strcmp(setoption,"backup")==0)) /* unset backup */ { c->set->term_current.backup = c->set->term_default.backup; } else if (strcmp_set && (strcmp(setoption,"bar")==0)) /* set bar */ { double barsize = command[PARSE_set_bar_bar_size ].real; int gotbarsize = (command[PARSE_set_bar_bar_size ].objType == PPLOBJ_NUM); int gotlarge = (command[PARSE_set_bar_bar_size_large].objType == PPLOBJ_STR); int gotsmall = (command[PARSE_set_bar_bar_size_small].objType == PPLOBJ_STR); if (gotbarsize && !gsl_finite(barsize)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set bar' command was not finite."); return; } if (gotsmall ) sg->bar = 0.0; else if (gotlarge ) sg->bar = 1.0; else if (gotbarsize) sg->bar = barsize; else sg->bar = 1.0; } else if (strcmp_unset && (strcmp(setoption,"bar")==0)) /* unset bar */ { sg->bar = c->set->graph_default.bar; } else if (strcmp_set && (strcmp(setoption,"binorigin")==0)) /* set binorigin */ { if (command[PARSE_set_binwidth_auto].objType==PPLOBJ_STR) { c->set->term_current.BinOriginAuto = 1; } else { double tempdbl = command[PARSE_set_binorigin_bin_origin].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set binorigin' command was not finite."); return; } c->set->term_current.BinOriginAuto = 0; c->set->term_current.BinOrigin = command[PARSE_set_binorigin_bin_origin]; } } else if (strcmp_unset && (strcmp(setoption,"binorigin")==0)) /* unset binorigin */ { c->set->term_current.BinOrigin = c->set->term_default.BinOrigin; c->set->term_current.BinOriginAuto = c->set->term_default.BinOriginAuto; } else if (strcmp_set && (strcmp(setoption,"binwidth")==0)) /* set binwidth */ { if (command[PARSE_set_binwidth_auto].objType==PPLOBJ_STR) { c->set->term_current.BinWidthAuto = 1; } else { double tempdbl = command[PARSE_set_binwidth_bin_width].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set binwidth' command was not finite."); return; } if (tempdbl<=0) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Width of histogram bins must be greater than zero."); return; } c->set->term_current.BinWidthAuto = 0; c->set->term_current.BinWidth = command[PARSE_set_binwidth_bin_width]; } } else if (strcmp_unset && (strcmp(setoption,"binwidth")==0)) /* unset binwidth */ { c->set->term_current.BinWidth = c->set->term_default.BinWidth; c->set->term_current.BinWidthAuto = c->set->term_default.BinWidthAuto; } else if (strcmp_set && (strcmp(setoption,"boxfrom")==0)) /* set boxfrom */ { if (command[PARSE_set_boxfrom_auto].objType==PPLOBJ_STR) { sg->BoxFromAuto = 1; } else { double tempdbl = command[PARSE_set_boxfrom_box_from].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set boxfrom' command was not finite."); return; } sg->BoxFromAuto = 0; sg->BoxFrom = command[PARSE_set_boxfrom_box_from]; } } else if (strcmp_unset && (strcmp(setoption,"boxfrom")==0)) /* unset boxfrom */ { sg->BoxFrom = c->set->graph_default.BoxFrom; sg->BoxFromAuto = c->set->graph_default.BoxFromAuto; } else if (strcmp_set && (strcmp(setoption,"boxwidth")==0)) /* set boxwidth */ { if (command[PARSE_set_boxwidth_auto].objType==PPLOBJ_STR) { sg->BoxWidthAuto = 1; } else { double tempdbl = command[PARSE_set_boxwidth_box_width].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set boxwidth' command was not finite."); return; } sg->BoxWidthAuto = 0; sg->BoxWidth = command[PARSE_set_boxwidth_box_width]; } } else if (strcmp_unset && (strcmp(setoption,"boxwidth")==0)) /* unset boxwidth */ { sg->BoxWidth = c->set->graph_default.BoxWidth; sg->BoxWidthAuto = c->set->graph_default.BoxWidthAuto; } else if (strcmp_set && (strcmp(setoption,"c1format")==0)) /* set c1format */ { if (command[PARSE_set_c1format_format_string].objType == PPLOBJ_EXP) { if (sg->c1format != NULL) pplExpr_free((pplExpr *)sg->c1format); sg->c1format = (void *)pplExpr_cpy((pplExpr *)command[PARSE_set_c1format_format_string].auxil); sg->c1formatset = 1; } if (command[PARSE_set_c1format_auto_format].objType == PPLOBJ_STR) { if (sg->c1format != NULL) pplExpr_free((pplExpr *)sg->c1format); sg->c1format = NULL; sg->c1formatset = 0; } if (command[PARSE_set_c1format_orient].objType == PPLOBJ_STR) { sg->c1TickLabelRotation = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_c1format_orient].auxil, SW_TICLABDIR_INT, SW_TICLABDIR_STR); sg->c1TickLabelRotate = c->set->graph_default.c1TickLabelRotate; } if (command[PARSE_set_c1format_rotation].objType == PPLOBJ_NUM) { double r = command[PARSE_set_c1format_rotation].real; if (!gsl_finite(r)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The rotation angle supplied to the 'set c1format' command was not finite."); return; } sg->c1TickLabelRotate = r; // TickLabelRotation will already have been set by "rotate" keyword mapping to "orient" } } else if (strcmp_unset && (strcmp(setoption,"c1format")==0)) /* unset c1format */ { if (sg->c1format != NULL) pplExpr_free((pplExpr *)sg->c1format); sg->c1format = (void *)pplExpr_cpy((pplExpr *)c->set->graph_default.c1format); sg->c1formatset = c->set->graph_default.c1formatset; sg->c1TickLabelRotate = c->set->graph_default.c1TickLabelRotate; sg->c1TickLabelRotation = c->set->graph_default.c1TickLabelRotation; } else if (strcmp_set && (strcmp(setoption,"c1label")==0)) /* set c1label */ { if (command[PARSE_set_c1label_label_text].objType == PPLOBJ_STR) { snprintf(sg->c1label, FNAME_LENGTH, "%s", (char *)command[PARSE_set_c1label_label_text].auxil); sg->c1label[FNAME_LENGTH-1]='\0'; } if (command[PARSE_set_c1label_rotation].objType == PPLOBJ_NUM) { double r = command[PARSE_set_c1label_rotation].real; if (!gsl_finite(r)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The rotation angle supplied to the 'set c1label' command was not finite."); return; } sg->c1LabelRotate = r; } } else if (strcmp_unset && (strcmp(setoption,"c1label")==0)) /* unset c1label */ { strcpy(sg->c1label, c->set->graph_default.c1label); sg->c1LabelRotate = c->set->graph_default.c1LabelRotate; } else if (strcmp_set && (strcmp(setoption,"c1tics")==0)) /* set c1tics */ { int m = (command[PARSE_set_c1tics_minor].objType==PPLOBJ_STR); const int *ptab = PARSE_TABLE_set_c1tics_; char *cmd = m ? "mc1tics" : "c1tics"; if (!m) { SET_TICKS( sg->ticsC , sg->ticsCM , sg->unitC , ((sg->Cminauto[0]!=SW_BOOL_TRUE)||(sg->Cmaxauto[0]!=SW_BOOL_TRUE)) , (sg->Clog[0]==SW_BOOL_TRUE) ); } else { SET_TICKS( sg->ticsCM , sg->ticsC , sg->unitC , ((sg->Cminauto[0]!=SW_BOOL_TRUE)||(sg->Cmaxauto[0]!=SW_BOOL_TRUE)) , (sg->Clog[0]==SW_BOOL_TRUE) ); } } else if (strcmp_unset && (strcmp(setoption,"c1tics")==0)) /* unset c1tics */ { int m = (command[PARSE_unset_c1tics_minor].objType==PPLOBJ_STR); if (!m) { tics_rm(&sg->ticsC ); if (ppl_unitsDimEqual(&sg->unitC , &c->set->graph_default.unitC)) tics_cp(&sg->ticsC ,&c->set->graph_default.ticsC ); } tics_rm(&sg->ticsCM); if (ppl_unitsDimEqual(&sg->unitC , &c->set->graph_default.unitC)) tics_cp(&sg->ticsCM,&c->set->graph_default.ticsCM); } else if (strcmp_set && (strcmp(setoption,"calendar")==0)) /* set calendar */ { char *tempstr = (char *)command[PARSE_set_calendar_calendar].auxil; int got = (command[PARSE_set_calendar_calendar].objType == PPLOBJ_STR); if (got) c->set->term_current.CalendarIn = c->set->term_current.CalendarOut = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_CALENDAR_INT, SW_CALENDAR_STR); tempstr = (char *)command[PARSE_set_calendar_calendarin].auxil; got = (command[PARSE_set_calendar_calendarin].objType == PPLOBJ_STR); if (got) c->set->term_current.CalendarIn = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_CALENDAR_INT, SW_CALENDAR_STR); tempstr = (char *)command[PARSE_set_calendar_calendarout].auxil; got = (command[PARSE_set_calendar_calendarout].objType == PPLOBJ_STR); if (got) c->set->term_current.CalendarOut = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_CALENDAR_INT, SW_CALENDAR_STR); } else if (strcmp_unset && (strcmp(setoption,"calendar")==0)) /* unset calendar */ { c->set->term_current.CalendarIn = c->set->term_default.CalendarIn; c->set->term_current.CalendarOut = c->set->term_default.CalendarOut; } else if (strcmp_set && (strcmp(setoption,"clip")==0)) /* set clip */ { sg->clip = SW_ONOFF_ON; } else if (strcmp_unset && (strcmp(setoption,"clip")==0)) /* unset clip */ { sg->clip = c->set->graph_default.clip; } else if (strcmp_set && (strcmp(setoption,"colkey")==0)) /* set colkey */ { char *tempstr = (char *)command[PARSE_set_colkey_pos].auxil; int got = (command[PARSE_set_colkey_pos].objType == PPLOBJ_STR); sg->ColKey = SW_ONOFF_ON; if (got) sg->ColKeyPos = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_COLKEYPOS_INT, SW_COLKEYPOS_STR); } else if (strcmp_unset && (strcmp(setoption,"colkey")==0)) /* unset colkey */ { sg->ColKey = c->set->graph_default.ColKey; sg->ColKeyPos = c->set->graph_default.ColKeyPos; } else if (strcmp_set && (strcmp(setoption,"colmap")==0)) /* set colmap */ { if (command[PARSE_set_colmap_color].objType == PPLOBJ_EXP) { if (sg->ColMapExpr != NULL) pplExpr_free((pplExpr *)sg->ColMapExpr); sg->ColMapExpr = (void *)pplExpr_cpy((pplExpr *)command[PARSE_set_colmap_color].auxil); } if (command[PARSE_set_colmap_mask].objType == PPLOBJ_EXP) { if (sg->MaskExpr != NULL) pplExpr_free((pplExpr *)sg->MaskExpr); sg->MaskExpr = (void *)pplExpr_cpy((pplExpr *)command[PARSE_set_colmap_mask].auxil); } if (command[PARSE_set_colmap_nomask].objType == PPLOBJ_STR) { if (sg->MaskExpr != NULL) pplExpr_free((pplExpr *)sg->MaskExpr); sg->MaskExpr = NULL; } } else if (strcmp_unset && (strcmp(setoption,"colmap")==0)) /* unset colmap */ { if (sg->ColMapExpr != NULL) pplExpr_free((pplExpr *)sg->ColMapExpr); sg->ColMapExpr = (void *)pplExpr_cpy((pplExpr *)c->set->graph_default.ColMapExpr); if (sg->MaskExpr != NULL) pplExpr_free((pplExpr *)sg->MaskExpr); sg->MaskExpr = (void *)pplExpr_cpy((pplExpr *)c->set->graph_default.MaskExpr); } else if (strcmp_set && (strcmp(setoption,"contours")==0)) /* set contours */ { if (command[PARSE_set_contours_label ].objType == PPLOBJ_STR) sg->ContoursLabel = SW_ONOFF_ON; if (command[PARSE_set_contours_nolabel ].objType == PPLOBJ_STR) sg->ContoursLabel = SW_ONOFF_OFF; if (command[PARSE_set_contours_contours].objType == PPLOBJ_NUM) { double n = command[PARSE_set_contours_contours].real; if (n<2) { sprintf(c->errcontext.tempErrStr, "Contour plots must have at least two contours."); ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, NULL); return; } if (n>MAX_CONTOURS) { sprintf(c->errcontext.tempErrStr, "Contour maps cannot be constucted with more than %d contours.", MAX_CONTOURS); ppl_error(&c->errcontext, ERR_GENERIC,-1,-1,NULL); return; } sg->ContoursN = (int)round(n); sg->ContoursListLen = -1; } else if (command[PARSE_set_contours_contour_list].objType == PPLOBJ_NUM) { int pos = PARSE_set_contours_contour_list, i=0; pplObj *first=NULL; while (command[pos].objType==PPLOBJ_NUM) { pplObj *o; pos = (int)round(command[pos].real); if (pos<=0) break; o = &command[pos+PARSE_set_contours_contour_contour_list]; if (o->objType != PPLOBJ_NUM) { sprintf(c->errcontext.tempErrStr, "Contours can only be set at numeric values; supplied value is of type <%s>.", pplObjTypeNames[o->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } if (!gsl_finite(o->real)) { sprintf(c->errcontext.tempErrStr, "Contours can only be set at finite numeric values; supplied value is not finite."); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } if (o->flagComplex) { sprintf(c->errcontext.tempErrStr, "Contours can only be set at real numeric values; supplied value is complex."); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } if (i==0) first=o; else if (!ppl_unitsDimEqual(first,o)) { sprintf(c->errcontext.tempErrStr, "Contour positions must all have the same physical units; supplied list has multiple units, including <%s> and <%s>.", ppl_printUnit(c, first, NULL, NULL, 0, 1, 0), ppl_printUnit(c, o, NULL, NULL, 1, 1, 0)); ppl_error(&c->errcontext, ERR_UNIT, -1, -1, NULL); return; } i++; } if (first==NULL) { ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, "Empty list of contours."); return; } sg->ContoursUnit = *first; sg->ContoursListLen = i; pos = PARSE_set_contours_contour_list; i=0; while (command[pos].objType==PPLOBJ_NUM) { pplObj *o; pos = (int)round(command[pos].real); if (pos<=0) break; o = &command[pos+PARSE_set_contours_contour_contour_list]; sg->ContoursList[i] = o->real; i++; } } } else if (strcmp_unset && (strcmp(setoption,"contours")==0)) /* unset contours */ { sg->ContoursN = c->set->graph_default.ContoursN; memcpy((void*)sg->ContoursList, (void*)c->set->graph_default.ContoursList, MAX_CONTOURS*sizeof(double)); sg->ContoursListLen = c->set->graph_default.ContoursListLen; sg->ContoursUnit = c->set->graph_default.ContoursUnit; sg->ContoursLabel = c->set->graph_default.ContoursLabel; } else if (strcmp_set && (strcmp(setoption,"crange")==0)) /* set crange */ { char *cstr = (char *)command[PARSE_set_crange_c_number].auxil; int C = (int)(cstr[0]-'1'); pplObj *min = &command[PARSE_set_crange_min]; pplObj *max = &command[PARSE_set_crange_max]; int mina = (command[PARSE_set_crange_minauto].objType == PPLOBJ_STR); int maxa = (command[PARSE_set_crange_maxauto].objType == PPLOBJ_STR); if (command[PARSE_set_crange_reverse ].objType == PPLOBJ_STR) sg->Creverse[C] = SW_BOOL_TRUE; if (command[PARSE_set_crange_noreverse ].objType == PPLOBJ_STR) sg->Creverse[C] = SW_BOOL_FALSE; if (command[PARSE_set_crange_renormalise ].objType == PPLOBJ_STR) sg->Crenorm [C] = SW_BOOL_TRUE; if (command[PARSE_set_crange_norenormalise].objType == PPLOBJ_STR) sg->Crenorm [C] = SW_BOOL_FALSE; if ((!mina)&&(min->objType!=PPLOBJ_NUM)&&(sg->Cminauto[C]==SW_BOOL_FALSE)) min = &sg->Cmin[C]; if ((!maxa)&&(max->objType!=PPLOBJ_NUM)&&(sg->Cmaxauto[C]==SW_BOOL_FALSE)) max = &sg->Cmax[C]; if ((min->objType==PPLOBJ_NUM)&&(!gsl_finite(min->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set crange' command had non-finite limits."); return; } if ((max->objType==PPLOBJ_NUM)&&(!gsl_finite(max->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set crange' command had non-finite limits."); return; } if ((min->objType==PPLOBJ_NUM)&&(max->objType==PPLOBJ_NUM)&&(!ppl_unitsDimEqual(min,max))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Attempt to set crange with dimensionally incompatible minimum and maximum."); return; } if (min->objType==PPLOBJ_NUM) { sg->Cmin[C] = *min; sg->Cminauto[C] = SW_BOOL_FALSE; } if (max->objType==PPLOBJ_NUM) { sg->Cmax[C] = *max; sg->Cmaxauto[C] = SW_BOOL_FALSE; } if (mina) sg->Cminauto[C] = SW_BOOL_TRUE; if (maxa) sg->Cmaxauto[C] = SW_BOOL_TRUE; if (C==0) { pplObj *newunit = (sg->Cminauto[0]!=SW_BOOL_TRUE) ? &sg->Cmin[0] : &sg->Cmax[0]; if ((sg->Cminauto[0]!=SW_BOOL_TRUE)||(sg->Cmaxauto[0]!=SW_BOOL_TRUE)) { if (!ppl_unitsDimEqual(&sg->unitC,newunit)) { sg->unitC = *newunit; } tics_rm(&sg->ticsC); tics_rm(&sg->ticsCM); } } } else if (strcmp_unset && (strcmp(setoption,"crange")==0)) /* unset crange */ { char *cstr = (char *)command[PARSE_set_crange_c_number].auxil; int C = (int)(cstr[0]-'1'); sg->Cmin[C] = c->set->graph_default.Cmin[C]; sg->Cminauto[C] = c->set->graph_default.Cminauto[C]; sg->Cmax[C] = c->set->graph_default.Cmax[C]; sg->Cmaxauto[C] = c->set->graph_default.Cmaxauto[C]; sg->Crenorm[C] = c->set->graph_default.Crenorm[C]; sg->Creverse[C] = c->set->graph_default.Creverse[C]; if (C==0) { pplObj *newunit = (sg->Cminauto[0]!=SW_BOOL_TRUE) ? &sg->Cmin[0] : &sg->Cmax[0]; if ((sg->Cminauto[0]!=SW_BOOL_TRUE)||(sg->Cmaxauto[0]!=SW_BOOL_TRUE)) { if (!ppl_unitsDimEqual(&sg->unitC,newunit)) { sg->unitC = *newunit; } tics_rm(&sg->ticsC); tics_rm(&sg->ticsCM); } } } else if (strcmp_set && (strcmp(setoption,"display")==0)) /* set display */ { c->set->term_current.display = SW_ONOFF_ON; } else if (strcmp_unset && (strcmp(setoption,"display")==0)) /* unset display */ { c->set->term_current.display = c->set->term_default.display; } else if (strcmp_set && (strcmp(setoption,"filter")==0)) /* set filter */ { char *tempstr = (char *)command[PARSE_set_filter_filename].auxil; char *tempstr2 = (char *)command[PARSE_set_filter_filter ].auxil; char *tempstr3 = (char *)malloc(strlen(tempstr2)+1); pplObj val; if (tempstr3==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory."); return; } strcpy(tempstr3, tempstr2); val.refCount=1; pplObjStr(&val,0,1,tempstr3); // declare object not to be malloced, since ppl_dictRemoveKey will free it ppl_dictAppendCpy(c->set->filters,tempstr,&val,sizeof(pplObj)); } else if (strcmp_unset && (strcmp(setoption,"filter")==0)) /* unset filter */ { char *tempstr = (char *)command[PARSE_set_filter_filename].auxil; pplObj *tempobj = (pplObj *)ppl_dictLookup(c->set->filters,tempstr); if (tempobj == NULL) { ppl_warning(&c->errcontext, ERR_GENERIC, "Attempt to unset a filter which did not exist."); return; } ppl_garbageObject(tempobj); ppl_dictRemoveKey(c->set->filters,tempstr); } else if (strcmp_set && (strcmp(setoption,"fontsize")==0)) /* set fontsize */ { double tempdbl = command[PARSE_set_fontsize_fontsize].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set fontsize' command was not finite."); return; } if (tempdbl <= 0.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Font sizes are not allowed to be less than or equal to zero."); return; } sg->FontSize = tempdbl; } else if (strcmp_unset && (strcmp(setoption,"fontsize")==0)) /* unset fontsize */ { sg->FontSize = c->set->graph_default.FontSize; } else if ((strcmp(setoption,"axescolor")==0) || (strcmp(setoption,"gridmajcolor")==0) || (strcmp(setoption,"gridmincolor")==0) || (strcmp(setoption,"textcolor")==0)) /* set axescolor | set gridmajcolor | set gridmincolor */ { if (strcmp_unset) { if (strcmp(setoption,"axescolor" )==0) { sg->AxesColor=c->set->graph_default.AxesColor; sg->AxesCol1234Space=c->set->graph_default.AxesCol1234Space; sg->AxesColor1=c->set->graph_default.AxesColor1; sg->AxesColor2=c->set->graph_default.AxesColor2; sg->AxesColor3=c->set->graph_default.AxesColor3; sg->AxesColor4=c->set->graph_default.AxesColor4; } if (strcmp(setoption,"gridmajcolor")==0) { sg->GridMajColor=c->set->graph_default.GridMajColor; sg->GridMajCol1234Space=c->set->graph_default.GridMajCol1234Space; sg->GridMajColor1=c->set->graph_default.GridMajColor1; sg->GridMajColor2=c->set->graph_default.GridMajColor2; sg->GridMajColor3=c->set->graph_default.GridMajColor3; sg->GridMajColor4=c->set->graph_default.GridMajColor4; } if (strcmp(setoption,"gridmincolor")==0) { sg->GridMinColor=c->set->graph_default.GridMinColor; sg->GridMinCol1234Space=c->set->graph_default.GridMinCol1234Space; sg->GridMinColor1=c->set->graph_default.GridMinColor1; sg->GridMinColor2=c->set->graph_default.GridMinColor2; sg->GridMinColor3=c->set->graph_default.GridMinColor3; sg->GridMinColor4=c->set->graph_default.GridMinColor4; } if (strcmp(setoption,"textcolor" )==0) { sg->TextColor=c->set->graph_default.TextColor; sg->TextCol1234Space=c->set->graph_default.TextCol1234Space; sg->TextColor1=c->set->graph_default.TextColor1; sg->TextColor2=c->set->graph_default.TextColor2; sg->TextColor3=c->set->graph_default.TextColor3; sg->TextColor4=c->set->graph_default.TextColor4; } } else { unsigned char useCol, use1234; if (strcmp(setoption,"axescolor" )==0) ppl_colorFromObj(c,&command[PARSE_set_axescolor_color ],&sg->AxesColor ,&sg->AxesCol1234Space ,NULL,&sg->AxesColor1 ,&sg->AxesColor2 ,&sg->AxesColor3 ,&sg->AxesColor4 ,&useCol,&use1234); if (strcmp(setoption,"gridmajcolor")==0) ppl_colorFromObj(c,&command[PARSE_set_gridmajcolor_color],&sg->GridMajColor,&sg->GridMajCol1234Space,NULL,&sg->GridMajColor1,&sg->GridMajColor2,&sg->GridMajColor3,&sg->GridMajColor4,&useCol,&use1234); if (strcmp(setoption,"gridmincolor")==0) ppl_colorFromObj(c,&command[PARSE_set_gridmincolor_color],&sg->GridMinColor,&sg->GridMinCol1234Space,NULL,&sg->GridMinColor1,&sg->GridMinColor2,&sg->GridMinColor3,&sg->GridMinColor4,&useCol,&use1234); if (strcmp(setoption,"textcolor" )==0) ppl_colorFromObj(c,&command[PARSE_set_textcolor_color ],&sg->TextColor ,&sg->TextCol1234Space ,NULL,&sg->TextColor1 ,&sg->TextColor2 ,&sg->TextColor3 ,&sg->TextColor4 ,&useCol,&use1234); } } else if (strcmp_set && (strcmp(setoption,"grid")==0)) /* set grid */ { int pos = PARSE_set_grid_0axes; if (command[pos].objType!=PPLOBJ_NUM) { int i; if (sg->grid != SW_ONOFF_ON) { for (i=0; iGridAxisX[i] = c->set->graph_default.GridAxisX[i]; for (i=0; iGridAxisY[i] = c->set->graph_default.GridAxisY[i]; for (i=0; iGridAxisZ[i] = c->set->graph_default.GridAxisZ[i]; } sg->grid = SW_ONOFF_ON; } else { int i, anum; if (sg->grid != SW_ONOFF_ON) { for (i=0; iGridAxisX[i] = 0; for (i=0; iGridAxisY[i] = 0; for (i=0; iGridAxisZ[i] = 0; } sg->grid = SW_ONOFF_ON; while (command[pos].objType==PPLOBJ_NUM) { pos = (int)round(command[pos].real); if (pos<=0) break; anum = (int)round(command[pos+PARSE_set_grid_axis_0axes].real); i = (int)round(command[pos+PARSE_set_grid_axis_0axes].exponent[0]); if (i==1) { sg->GridAxisY[anum] = 1; } else if (i==2) { sg->GridAxisZ[anum] = 1; } else { sg->GridAxisX[anum] = 1; } } } } else if (strcmp_unset && (strcmp(setoption,"grid")==0)) /* unset grid */ { int i; sg->grid = c->set->graph_default.grid; for (i=0; iGridAxisX[i] = c->set->graph_default.GridAxisX[i]; for (i=0; iGridAxisY[i] = c->set->graph_default.GridAxisY[i]; for (i=0; iGridAxisZ[i] = c->set->graph_default.GridAxisZ[i]; } else if (strcmp_set && (strcmp(setoption,"key")==0)) /* set key */ { sg->key = SW_ONOFF_ON; // Turn key on if (command[PARSE_set_key_offset].objType==PPLOBJ_NUM) // Horizontal offset { double tempdbl = command[PARSE_set_key_offset].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The horizontal offset supplied to the 'set key' command was not finite."); } else sg->KeyXOff.real = tempdbl; } if (command[PARSE_set_key_offset+1].objType==PPLOBJ_NUM) // Vertical offset { double tempdbl = command[PARSE_set_key_offset+1].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The vertical offset supplied to the 'set key' command was not finite."); } else sg->KeyYOff.real = tempdbl; } // Now work out position of key if (command[PARSE_set_key_pos].objType==PPLOBJ_STR) { sg->KeyPos = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_key_pos].auxil, SW_KEYPOS_INT, SW_KEYPOS_STR); } if (command[PARSE_set_key_xpos].objType==PPLOBJ_STR) { char *tempstr = command[PARSE_set_key_xpos].auxil; if (tempstr != NULL) { if (strcmp(tempstr,"left")==0) { if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_TM)||(sg->KeyPos==SW_KEYPOS_TL)) sg->KeyPos=SW_KEYPOS_TL; else if ((sg->KeyPos==SW_KEYPOS_BR)||(sg->KeyPos==SW_KEYPOS_BM)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_BL; else sg->KeyPos=SW_KEYPOS_ML; } if (strcmp(tempstr,"xcenter")==0) { if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_TM)||(sg->KeyPos==SW_KEYPOS_TL)) sg->KeyPos=SW_KEYPOS_TM; else if ((sg->KeyPos==SW_KEYPOS_BR)||(sg->KeyPos==SW_KEYPOS_BM)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_BM; else sg->KeyPos=SW_KEYPOS_MM; } if (strcmp(tempstr,"right")==0) { if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_TM)||(sg->KeyPos==SW_KEYPOS_TL)) sg->KeyPos=SW_KEYPOS_TR; else if ((sg->KeyPos==SW_KEYPOS_BR)||(sg->KeyPos==SW_KEYPOS_BM)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_BR; else sg->KeyPos=SW_KEYPOS_MR; } } } if (command[PARSE_set_key_ypos].objType==PPLOBJ_STR) { char *tempstr = command[PARSE_set_key_ypos].auxil; if (tempstr != NULL) { if (strcmp(tempstr,"top")==0) { if ((sg->KeyPos==SW_KEYPOS_TL)||(sg->KeyPos==SW_KEYPOS_ML)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_TL; else if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_MR)||(sg->KeyPos==SW_KEYPOS_BR)) sg->KeyPos=SW_KEYPOS_TR; else sg->KeyPos=SW_KEYPOS_TM; } if (strcmp(tempstr,"ycenter")==0) { if ((sg->KeyPos==SW_KEYPOS_TL)||(sg->KeyPos==SW_KEYPOS_ML)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_ML; else if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_MR)||(sg->KeyPos==SW_KEYPOS_BR)) sg->KeyPos=SW_KEYPOS_MR; else sg->KeyPos=SW_KEYPOS_MM; } if (strcmp(tempstr,"bottom")==0) { if ((sg->KeyPos==SW_KEYPOS_TL)||(sg->KeyPos==SW_KEYPOS_ML)||(sg->KeyPos==SW_KEYPOS_BL)) sg->KeyPos=SW_KEYPOS_BL; else if ((sg->KeyPos==SW_KEYPOS_TR)||(sg->KeyPos==SW_KEYPOS_MR)||(sg->KeyPos==SW_KEYPOS_BR)) sg->KeyPos=SW_KEYPOS_BR; else sg->KeyPos=SW_KEYPOS_BM; } } } } else if (strcmp_unset && (strcmp(setoption,"key")==0)) /* unset key */ { sg->key = c->set->graph_default.key; sg->KeyPos = c->set->graph_default.KeyPos; sg->KeyXOff = c->set->graph_default.KeyXOff; sg->KeyYOff = c->set->graph_default.KeyYOff; } else if (strcmp_set && (strcmp(setoption,"keycolumns")==0)) /* set keycolumns */ { if (command[PARSE_set_keycolumns_key_columns].objType==PPLOBJ_NUM) { double tempdbl = command[PARSE_set_keycolumns_key_columns].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set keycolumns' command was not finite."); return; } if (tempdbl <= 0.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Number of key columns is not allowed to be less than or equal to zero."); return; } sg->KeyColumns = (int)round(tempdbl); } else { sg->KeyColumns = c->set->graph_default.KeyColumns; // set keycolumns auto -- equivalent to unset } } else if (strcmp_unset && (strcmp(setoption,"keycolumns")==0)) /* unset keycolumns */ { sg->KeyColumns = c->set->graph_default.KeyColumns; } else if (strcmp_set && (strcmp(setoption,"label")==0)) /* set label */ { if (ll!=NULL) ppllabel_add(c, ll, in, pl, PARSE_TABLE_set_label_); } else if (strcmp_unset && (strcmp(setoption,"label")==0)) /* unset label */ { if (ll!=NULL) ppllabel_unset(c, ll, in, pl, PARSE_TABLE_unset_label_); } else if (strcmp_set && (strcmp(setoption,"linewidth")==0)) /* set linewidth */ { double tempdbl = command[PARSE_set_linewidth_linewidth].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set linewidth' command was not finite."); return; } if (tempdbl <= 0.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Line widths are not allowed to be less than or equal to zero."); return; } sg->LineWidth = tempdbl; } else if (strcmp_unset && (strcmp(setoption,"linewidth")==0)) /* unset linewidth */ { sg->LineWidth = c->set->graph_default.LineWidth; } else if ( (strcmp_set && (strcmp(setoption,"logscale")==0)) || /* set logscale */ (strcmp_unset && (strcmp(setoption,"logscale")==0)) || /* unset logscale */ (strcmp_set && (strcmp(setoption,"nologscale")==0)) ) { const int sl = (strcmp_set && (strcmp(setoption,"logscale")==0)); const int ul = (strcmp_unset && (strcmp(setoption,"logscale")==0)); const int snl= (strcmp_set && (strcmp(setoption,"nologscale")==0)); int b = 10; int pos= sl ? PARSE_set_logscale_0axes : (ul ? PARSE_unset_logscale_0axes : PARSE_set_nologscale_0axes); const int ap = sl ? PARSE_set_logscale_axis_0axes : (ul ? PARSE_unset_logscale_axis_0axes : PARSE_set_nologscale_axis_0axes); const int c1p= sl ? PARSE_set_logscale_c1log_0axes : (ul ? PARSE_unset_logscale_c1log_0axes : PARSE_set_nologscale_c1log_0axes); const int c2p= sl ? PARSE_set_logscale_c2log_0axes : (ul ? PARSE_unset_logscale_c2log_0axes : PARSE_set_nologscale_c2log_0axes); const int c3p= sl ? PARSE_set_logscale_c3log_0axes : (ul ? PARSE_unset_logscale_c3log_0axes : PARSE_set_nologscale_c3log_0axes); const int c4p= sl ? PARSE_set_logscale_c4log_0axes : (ul ? PARSE_unset_logscale_c4log_0axes : PARSE_set_nologscale_c4log_0axes); const int tp = sl ? PARSE_set_logscale_tlog_0axes : (ul ? PARSE_unset_logscale_tlog_0axes : PARSE_set_nologscale_tlog_0axes ); const int up = sl ? PARSE_set_logscale_ulog_0axes : (ul ? PARSE_unset_logscale_ulog_0axes : PARSE_set_nologscale_ulog_0axes ); const int vp = sl ? PARSE_set_logscale_vlog_0axes : (ul ? PARSE_unset_logscale_vlog_0axes : PARSE_set_nologscale_vlog_0axes ); const int setAll = (command[pos].objType!=PPLOBJ_NUM); if (sl && (command[PARSE_set_logscale_base].objType==PPLOBJ_NUM)) { b = (int)round(command[PARSE_set_logscale_base].real); if ((b<2)||(b>1024)) { sprintf(c->errcontext.tempErrStr, "Attempt to use log axis with base %d. Pyxplot only supports bases in the range 2 - 1024. Defaulting to base 10.", b); ppl_warning(&c->errcontext, ERR_GENERIC, NULL); b=10; } } if (!setAll) { while (command[pos].objType==PPLOBJ_NUM) { pos = (int)round(command[pos].real); if (pos<=0) break; if (command[pos+ap].objType==PPLOBJ_NUM) { int *alog, *adlog; int i = (int)round(command[pos+ap].real); int j = (int)round(command[pos+ap].exponent[0]); int newstate; pplset_axis *a, *ad; if (j==1) { a = &ya[i]; ad = &c->set->YAxesDefault[i]; } else if (j==2) { a = &za[i]; ad = &c->set->ZAxesDefault[i]; } else { a = &xa[i]; ad = &c->set->XAxesDefault[i]; } GET_AXISLOG(alog , a , 0); GET_AXISLOG(adlog, ad, 1); if (sl ) { a->enabled = 1; newstate = SW_BOOL_TRUE; } else if (snl) { a->enabled = 1; newstate = SW_BOOL_FALSE; } else { newstate = *adlog; } if (*alog != newstate) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog = newstate; a->tics .logBase = b; a->ticsM.logBase = b; } else { if (command[pos+c1p].objType==PPLOBJ_STR) { int newstate = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Clog[0] : SW_BOOL_FALSE); if (sg->Clog[0] != newstate) { tics_rm(&sg->ticsC); tics_rm(&sg->ticsCM); } sg->Clog[0] = newstate; sg->ticsC .logBase = b; sg->ticsCM.logBase = b; } if (command[pos+c2p].objType==PPLOBJ_STR) { sg->Clog[1] = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Clog[1] : SW_BOOL_FALSE); } if (command[pos+c3p].objType==PPLOBJ_STR) { sg->Clog[2] = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Clog[2] : SW_BOOL_FALSE); } if (command[pos+c4p].objType==PPLOBJ_STR) { sg->Clog[3] = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Clog[3] : SW_BOOL_FALSE); } if (command[pos+tp ].objType==PPLOBJ_STR) { sg->Tlog = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Tlog : SW_BOOL_FALSE); } if (command[pos+up ].objType==PPLOBJ_STR) { sg->Ulog = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Ulog : SW_BOOL_FALSE); } if (command[pos+vp ].objType==PPLOBJ_STR) { sg->Vlog = sl ? SW_BOOL_TRUE : (ul ? c->set->graph_default.Vlog : SW_BOOL_FALSE); } } } } else if (!ul) // set logscale or nologscale on all axes { int i, *alog; pplset_axis *a; int newstate = sl ? SW_BOOL_TRUE : SW_BOOL_FALSE; if (sg->Clog[0] != newstate) { tics_rm(&sg->ticsC); tics_rm(&sg->ticsCM); } sg->Clog[0] = sg->Clog[1] = sg->Clog[2] = sg->Clog[3] = sg->Tlog = sg->Ulog = sg->Vlog = newstate; for (i=0;ienabled) { GET_AXISLOG(alog,a,0); if (*alog != newstate) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=newstate; a->tics.logBase=a->ticsM.logBase=b; } } for (i=0;ienabled) { GET_AXISLOG(alog,a,0); if (*alog != newstate) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=newstate; a->tics.logBase=a->ticsM.logBase=b; } } for (i=0;ienabled) { GET_AXISLOG(alog,a,0); if (*alog != newstate) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=newstate; a->tics.logBase=a->ticsM.logBase=b; } } } else // unset logscale on all axes { int i, *alog, *adlog; pplset_axis *a, *ad; if (sg->Clog[0] != c->set->graph_default.Clog[0]) { tics_rm(&sg->ticsC); tics_rm(&sg->ticsCM); } sg->Clog[0] = c->set->graph_default.Clog[0]; sg->Clog[1] = c->set->graph_default.Clog[1]; sg->Clog[2] = c->set->graph_default.Clog[2]; sg->Clog[3] = c->set->graph_default.Clog[3]; sg->Tlog = c->set->graph_default.Tlog; sg->Ulog = c->set->graph_default.Ulog; sg->Vlog = c->set->graph_default.Vlog; for (i=0;iset->XAxesDefault[i]; if (a->enabled) { GET_AXISLOG(alog,a,0); GET_AXISLOG(adlog,ad,1); if (*alog != *adlog) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=*adlog; a->tics.logBase=a->ticsM.logBase=b; } } for (i=0;iset->YAxesDefault[i]; if (a->enabled) { GET_AXISLOG(alog,a,0); GET_AXISLOG(adlog,ad,1); if (*alog != *adlog) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=*adlog; a->tics.logBase=a->ticsM.logBase=b; } } for (i=0;iset->ZAxesDefault[i]; if (a->enabled) { GET_AXISLOG(alog,a,0); GET_AXISLOG(adlog,ad,1); if (*alog != *adlog) { tics_rm(&a->tics); tics_rm(&a->ticsM); } *alog=*adlog; a->tics.logBase=a->ticsM.logBase=b; } } } } else if (strcmp_set && (strcmp(setoption,"multiplot")==0)) /* set multiplot */ { c->set->term_current.multiplot = SW_ONOFF_ON; } else if (strcmp_unset && (strcmp(setoption,"multiplot")==0)) /* unset multiplot */ { if ((c->set->term_default.multiplot == SW_ONOFF_OFF) && (c->set->term_current.multiplot == SW_ONOFF_ON)) ppl_directive_clear(c,pl,in,interactive); c->set->term_current.multiplot = c->set->term_default.multiplot; } else if (strcmp_set && (strcmp(setoption,"noarrow")==0)) /* set noarrow */ { if (al!=NULL) pplarrow_remove(c, al, in, pl, PARSE_TABLE_set_noarrow_, 0); } else if (strcmp_set && (strcmp(setoption,"nobackup")==0)) /* set nobackup */ { c->set->term_current.backup = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"noc1format")==0)) /* set noc1format */ { sg->c1format = NULL; sg->c1formatset = 0; } else if (strcmp_set && (strcmp(setoption,"noc1label")==0)) /* set noc1label */ { sg->c1label[0] = '\0'; } else if (strcmp_set && (strcmp(setoption,"noc1tics")==0)) /* set noc1tics */ { int m = (command[PARSE_set_notics_minor].objType==PPLOBJ_STR); if (!m) { SET_NOTICKS(sg->ticsC); } SET_NOTICKS(sg->ticsCM); } else if (strcmp_set && (strcmp(setoption,"noclip")==0)) /* set noclip */ { sg->clip = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"nocolkey")==0)) /* set nocolkey */ { sg->ColKey = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"nodisplay")==0)) /* set nodisplay */ { c->set->term_current.display = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"nogrid")==0)) /* set nogrid */ { int pos = PARSE_set_nogrid_0axes; if (command[pos].objType!=PPLOBJ_NUM) { sg->grid = SW_ONOFF_OFF; } else { int i, anum; while (command[pos].objType==PPLOBJ_NUM) { pos = (int)round(command[pos].real); if (pos<=0) break; anum = (int)round(command[pos+PARSE_set_nogrid_axis_0axes].real); i = (int)round(command[pos+PARSE_set_nogrid_axis_0axes].exponent[0]); if (i==1) { sg->GridAxisY[anum] = 0; } else if (i==2) { sg->GridAxisZ[anum] = 0; } else { sg->GridAxisX[anum] = 0; } } } } else if (strcmp_set && (strcmp(setoption,"nokey")==0)) /* set nokey */ { sg->key = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"nolabel")==0)) /* set nolabel */ { if (ll!=NULL) ppllabel_remove(c, ll, in, pl, PARSE_TABLE_set_nolabel_, 0); } else if (strcmp_set && (strcmp(setoption,"nomultiplot")==0)) /* set nomultiplot */ { if (c->set->term_current.multiplot != SW_ONOFF_OFF) ppl_directive_clear(c,pl,in,interactive); c->set->term_current.multiplot = SW_ONOFF_OFF; } else if (strcmp_set && (strcmp(setoption,"notics")==0)) /* set notics */ { int m = (command[PARSE_set_notics_minor].objType==PPLOBJ_STR); if (command[PARSE_set_notics_axis].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_set_notics_axis].real); int j = (int)round(command[PARSE_set_notics_axis].exponent[0]); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { if (j==1) { pplset_axis *a = &ya[i]; if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } else if (j==2) { pplset_axis *a = &za[i]; if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } else { pplset_axis *a = &xa[i]; if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } } } else { int i; for (i=0; ienabled) { if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } } for (i=0; ienabled) { if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } } for (i=0; ienabled) { if (!m) { SET_NOTICKS(a->tics); } SET_NOTICKS(a->ticsM); } } } } else if (strcmp_set && (strcmp(setoption,"notitle")==0)) /* set notitle */ { strcpy(sg->title, ""); } else if (strcmp_set && (strcmp(setoption,"noxformat")==0)) /* set noxformat */ { int i = (int)round(command[PARSE_set_noxformat_axis].real); int j = (int)round(command[PARSE_set_noxformat_axis].exponent[0]); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplset_axis *a, *ad; if (j==1) { a = &ya[i]; ad = &c->set->YAxesDefault[i]; } else if (j==2) { a = &za[i]; ad = &c->set->ZAxesDefault[i]; } else { a = &xa[i]; ad = &c->set->XAxesDefault[i]; } a->enabled = 1; if (a->format != NULL) { pplExpr_free((pplExpr *)a->format); a->format=NULL; } a->TickLabelRotation = ad->TickLabelRotation; a->TickLabelRotate = ad->TickLabelRotate; } } else if (strcmp_set && (strcmp(setoption,"noxlabel")==0)) /* set noxlabel */ { int i = (int)round(command[PARSE_set_noxlabel_axis].real); int j = (int)round(command[PARSE_set_noxlabel_axis].exponent[0]); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplset_axis *a; if (j==1) a = &ya[i]; else if (j==2) a = &za[i]; else a = &xa[i]; a->enabled=1; if (a->label!=NULL) free(a->label); a->label=NULL; } } else if (strcmp_set && (strcmp(setoption,"numerics")==0)) /* set numerics */ { char *tempstr = (char *)command[PARSE_set_numerics_complex].auxil; int got = (command[PARSE_set_numerics_complex].objType == PPLOBJ_STR); if (got) c->set->term_current.ComplexNumbers = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_numerics_errortype].auxil; got = (command[PARSE_set_numerics_errortype].objType == PPLOBJ_STR); if (got) c->set->term_current.ExplicitErrors = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); got = (command[PARSE_set_numerics_number_significant_figures].objType == PPLOBJ_NUM); if (got) { int tempint = (int)round(command[PARSE_set_numerics_number_significant_figures].real); if (tempint < 1) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Numbers cannot be displayed to fewer than one significant figure."); return; } if (tempint > 30) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "It is not sensible to try to display numbers to more than 30 significant figures. Calculations in Pyxplot are only accurate to double precision."); return; } c->set->term_current.SignificantFigures = tempint; } tempstr = (char *)command[PARSE_set_numerics_display].auxil; got = (command[PARSE_set_numerics_display].objType == PPLOBJ_STR); if (got) c->set->term_current.NumDisplay = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_DISPLAY_INT, SW_DISPLAY_STR); } else if (strcmp_unset && (strcmp(setoption,"numerics")==0)) /* unset numerics */ { c->set->term_current.ComplexNumbers = c->set->term_default.ComplexNumbers; c->set->term_current.ExplicitErrors = c->set->term_default.ExplicitErrors; c->set->term_current.NumDisplay = c->set->term_default.NumDisplay; c->set->term_current.SignificantFigures = c->set->term_default.SignificantFigures; } else if (strcmp_unset && (strcmp(setoption,"numerics_sigfig")==0)) /* unset numerics sigfig */ { c->set->term_current.SignificantFigures = c->set->term_default.SignificantFigures; } else if (strcmp_unset && (strcmp(setoption,"numerics_errors")==0)) /* unset numerics errors */ { c->set->term_current.ExplicitErrors = c->set->term_default.ExplicitErrors; } else if (strcmp_unset && (strcmp(setoption,"numerics_sigfig")==0)) /* unset numerics complex */ { c->set->term_current.ComplexNumbers = c->set->term_default.ComplexNumbers; } else if (strcmp_unset && (strcmp(setoption,"numerics_display")==0)) /* unset numerics display */ { c->set->term_current.NumDisplay = c->set->term_default.NumDisplay; } else if (strcmp_set && (strcmp(setoption,"origin")==0)) /* set origin */ { double x = command[PARSE_set_origin_origin ].real; double y = command[PARSE_set_origin_origin+1].real; sg->OriginX.real = x; sg->OriginY.real = y; } else if (strcmp_unset && (strcmp(setoption,"origin")==0)) /* unset origin */ { sg->OriginX = c->set->graph_default.OriginX; sg->OriginY = c->set->graph_default.OriginY; } else if (strcmp_set && (strcmp(setoption,"output")==0)) /* set output */ { char *tempstr = (char *)command[PARSE_set_output_filename].auxil; strncpy(c->set->term_current.output, tempstr, FNAME_LENGTH-1); c->set->term_current.output[FNAME_LENGTH-1]='\0'; } else if (strcmp_unset && (strcmp(setoption,"output")==0)) /* unset output */ { strncpy(c->set->term_current.output, c->set->term_default.output, FNAME_LENGTH-1); c->set->term_current.output[FNAME_LENGTH-1]='\0'; } else if (strcmp_set && (strcmp(setoption,"palette")==0)) /* set palette */ { if (command[PARSE_set_palette_palette].objType==PPLOBJ_NUM) { int pos = PARSE_set_palette_palette, count=0; while (command[pos].objType==PPLOBJ_NUM) { unsigned char d1,d2; pplObj *co; pos = (int)round(command[pos].real); if (pos<=0) break; if (count>=PALETTE_LENGTH-1) { ppl_warning(&c->errcontext, ERR_GENERIC, "The 'set palette' command has been passed a palette which is too long; truncating it."); break; } co = &command[pos+PARSE_set_palette_color_palette]; c->set->palette_current[count] = -1; ppl_colorFromObj(c,co,&c->set->palette_current[count],&c->set->paletteS_current[count],NULL,&c->set->palette1_current[count],&c->set->palette2_current[count],&c->set->palette3_current[count],&c->set->palette4_current[count],&d1,&d2); count++; } c->set->palette_current[count] = -1; } else { pplObj *lo = &command[PARSE_set_palette_list]; list *l = (list *)lo->auxil; int ll,i; if (lo->objType!=PPLOBJ_LIST) { sprintf(c->errcontext.tempErrStr, "The 'set palette' command can only generate palettes from objects of type list; supplied object has type <%s>.", pplObjTypeNames[lo->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } ll = ppl_listLen(l); if (ll<1) { sprintf(c->errcontext.tempErrStr, "The 'set palette' command was passed a palette of zero length."); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } for (i=0; iobjType!=PPLOBJ_NUM)&&(o->objType!=PPLOBJ_COL)) { sprintf(c->errcontext.tempErrStr, "Object of type <%s> in list supplied to the 'set palette' command could not be converted to a color.", pplObjTypeNames[o->objType]); ppl_error(&c->errcontext, ERR_TYPE, -1, -1, NULL); return; } } for (i=0; i=PALETTE_LENGTH-1) { ppl_warning(&c->errcontext, ERR_GENERIC, "The 'set palette' command has been passed a palette which is too long; truncating it."); break; } c->set->palette_current[i] = -1; ppl_colorFromObj(c,o,&c->set->palette_current[i],&c->set->paletteS_current[i],NULL,&c->set->palette1_current[i],&c->set->palette2_current[i],&c->set->palette3_current[i],&c->set->palette4_current[i],&d1,&d2); } c->set->palette_current[i] = -1; } } else if (strcmp_unset && (strcmp(setoption,"palette")==0)) /* unset palette */ { for (i=0; iset->palette_current [i] = c->set->palette_default [i]; for (i=0; iset->paletteS_current[i] = c->set->paletteS_default[i]; for (i=0; iset->palette1_current[i] = c->set->palette1_default[i]; for (i=0; iset->palette2_current[i] = c->set->palette2_default[i]; for (i=0; iset->palette3_current[i] = c->set->palette3_default[i]; for (i=0; iset->palette4_current[i] = c->set->palette4_default[i]; } else if (strcmp_set && (strcmp(setoption,"papersize")==0)) /* set papersize */ { if (command[PARSE_set_papersize_paper_name].objType==PPLOBJ_STR) { double d1,d2; char *paperName = (char *)command[PARSE_set_papersize_paper_name].auxil; ppl_PaperSizeByName(paperName, &d1, &d2); if (d1>0) { c->set->term_current.PaperHeight.real = d1/1000; c->set->term_current.PaperWidth.real = d2/1000; ppl_GetPaperName(c->set->term_current.PaperName, &d1, &d2); } else { sprintf(c->errcontext.tempErrStr, "Unrecognised paper size '%s'.", paperName); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } } else { double d1 = command[PARSE_set_papersize_size ].real; double d2 = command[PARSE_set_papersize_size+1].real; if ((!gsl_finite(d1))||(!gsl_finite(d2))) { sprintf(c->errcontext.tempErrStr, "The size coordinates supplied to the 'set papersize' command was not finite."); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } c->set->term_current.PaperWidth .real = d1; c->set->term_current.PaperHeight.real = d2; d1 *= 1000; // Function below takes size input in mm d2 *= 1000; ppl_GetPaperName(c->set->term_current.PaperName, &d1, &d2); } } else if (strcmp_unset && (strcmp(setoption,"papersize")==0)) /* unset papersize */ { c->set->term_current.PaperHeight.real = c->set->term_default.PaperHeight.real; c->set->term_current.PaperWidth .real = c->set->term_default.PaperWidth .real; strcpy(c->set->term_current.PaperName, c->set->term_default.PaperName); } else if (strcmp_set && (strcmp(setoption,"pointlinewidth")==0)) /* set pointlinewidth */ { double tempdbl = command[PARSE_set_pointlinewidth_pointlinewidth].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set pointlinewidth' command was not finite."); return; } if (tempdbl <= 0.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Line widths are not allowed to be less than or equal to zero."); return; } sg->PointLineWidth = tempdbl; } else if (strcmp_unset && (strcmp(setoption,"pointlinewidth")==0)) /* unset pointlinewidth */ { sg->PointLineWidth = c->set->graph_default.PointLineWidth; } else if (strcmp_set && (strcmp(setoption,"pointsize")==0)) /* set pointsize */ { double tempdbl = command[PARSE_set_pointsize_pointsize].real; if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set pointsize' command was not finite."); return; } if (tempdbl <= 0.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Point sizes are not allowed to be less than or equal to zero."); return; } sg->PointSize = tempdbl; } else if (strcmp_unset && (strcmp(setoption,"pointsize")==0)) /* unset pointsize */ { sg->PointSize = c->set->graph_default.PointSize; } else if (strcmp_set && (strcmp(setoption,"preamble")==0)) /* set preamble */ { char *tempstr = (char *)command[PARSE_set_preamble_preamble].auxil; strncpy(c->set->term_current.LatexPreamble, tempstr, FNAME_LENGTH-1); c->set->term_current.LatexPreamble[FNAME_LENGTH-1]='\0'; } else if (strcmp_unset && (strcmp(setoption,"preamble")==0)) /* unset preamble */ { strncpy(c->set->term_current.LatexPreamble, c->set->term_default.LatexPreamble, FNAME_LENGTH-1); c->set->term_current.LatexPreamble[FNAME_LENGTH-1]='\0'; } else if (strcmp_set && (strcmp(setoption,"samples")==0)) /* set samples */ { if (command[PARSE_set_samples_samples].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_set_samples_samples].real); if (i<2) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Graphs cannot be constucted based on fewer than two samples."); i=2; } sg->samples = i; } if (command[PARSE_set_samples_samplesX].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_set_samples_samplesX].real); if (i<2) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Graphs cannot be constucted based on fewer than two samples."); i=2; } sg->SamplesX = i; sg->SamplesXAuto = SW_BOOL_FALSE; } if (command[PARSE_set_samples_samplesY].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_set_samples_samplesY].real); if (i<2) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Graphs cannot be constucted based on fewer than two samples."); i=2; } sg->SamplesY = i; sg->SamplesYAuto = SW_BOOL_FALSE; } if (command[PARSE_set_samples_samplesXauto].objType==PPLOBJ_STR) sg->SamplesXAuto = SW_BOOL_TRUE; if (command[PARSE_set_samples_samplesYauto].objType==PPLOBJ_STR) sg->SamplesYAuto = SW_BOOL_TRUE; if (command[PARSE_set_samples_method].objType==PPLOBJ_STR) { sg->Sample2DMethod = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_samples_method].auxil, SW_SAMPLEMETHOD_INT, SW_SAMPLEMETHOD_STR); } } else if (strcmp_unset && (strcmp(setoption,"samples")==0)) /* unset samples */ { sg->samples = c->set->graph_default.samples; sg->SamplesX = c->set->graph_default.SamplesX; sg->SamplesXAuto = c->set->graph_default.SamplesXAuto; sg->SamplesY = c->set->graph_default.SamplesY; sg->SamplesYAuto = c->set->graph_default.SamplesYAuto; sg->Sample2DMethod = c->set->graph_default.Sample2DMethod; } else if (strcmp_set && (strcmp(setoption,"seed")==0)) /* set seed */ { long li; double d = command[PARSE_set_seed_seed].real; if (!gsl_finite(d)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The value supplied to the 'set seed' command was not finite."); return; } if (d < LONG_MIN) li = LONG_MIN; else if (d > LONG_MAX) li = LONG_MAX; else li = (long)d; c->set->term_current.RandomSeed = li; pplfunc_setRandomSeed(li); } else if (strcmp_unset && (strcmp(setoption,"seed")==0)) /* unset seed */ { c->set->term_current.RandomSeed = c->set->term_default.RandomSeed; pplfunc_setRandomSeed(c->set->term_current.RandomSeed); } else if (strcmp_set && (strcmp(setoption,"size")==0)) /* set size */ { if (command[PARSE_set_size_width].objType==PPLOBJ_NUM) { if (!gsl_finite(command[PARSE_set_size_width].real)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The width supplied to the 'set size' command was not finite."); return; } sg->width.real=command[PARSE_set_size_width].real; } if (command[PARSE_set_size_height].objType==PPLOBJ_NUM) { double r = command[PARSE_set_size_height].real / sg->width.real; if ((!gsl_finite(r)) || (fabs(r) < 1e-6) || (fabs(r) > 1e4)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The requested y/x aspect ratios for graphs must be in the range 1e-6 to 10000."); return; } sg->aspect = r; sg->AutoAspect = SW_ONOFF_OFF; } if (command[PARSE_set_size_depth].objType==PPLOBJ_NUM) { double r = command[PARSE_set_size_depth].real / sg->width.real; if ((!gsl_finite(r)) || (fabs(r) < 1e-6) || (fabs(r) > 1e4)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The requested z/x aspect ratios for graphs must be in the range 1e-6 to 10000."); return; } sg->zaspect = r; sg->AutoZAspect = SW_ONOFF_OFF; } if (command[PARSE_set_size_ratio].objType==PPLOBJ_NUM) { double r = command[PARSE_set_size_ratio].real; if ((!gsl_finite(r)) || (fabs(r) < 1e-6) || (fabs(r) > 1e4)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The requested y/x aspect ratios for graphs must be in the range 1e-6 to 10000."); return; } sg->aspect = r; sg->AutoAspect = SW_ONOFF_OFF; } if (command[PARSE_set_size_zratio].objType==PPLOBJ_NUM) { double r = command[PARSE_set_size_zratio].real; if ((!gsl_finite(r)) || (fabs(r) < 1e-6) || (fabs(r) > 1e4)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The requested z/x aspect ratios for graphs must be in the range 1e-6 to 10000."); return; } sg->zaspect = r; sg->AutoZAspect = SW_ONOFF_OFF; } if (command[PARSE_set_size_square ].objType==PPLOBJ_STR) { sg->aspect = 1; sg->AutoAspect = SW_ONOFF_OFF; sg->zaspect = 1; sg->AutoZAspect = SW_ONOFF_OFF; } if (command[PARSE_set_size_noratio ].objType==PPLOBJ_STR) { sg->aspect = c->set->graph_default.aspect; sg->AutoAspect = 1; } if (command[PARSE_set_size_nozratio].objType==PPLOBJ_STR) { sg->zaspect = c->set->graph_default.zaspect; sg->AutoZAspect = 1; } } else if (strcmp_unset && (strcmp(setoption,"size")==0)) /* unset size */ { sg->width.real = c->set->graph_default.width.real; sg->aspect = c->set->graph_default.aspect; sg->AutoAspect = c->set->graph_default.AutoAspect; sg->zaspect = c->set->graph_default.zaspect; sg->AutoZAspect = c->set->graph_default.AutoZAspect; } else if (strcmp_set && (strcmp(setoption,"style")==0)) /* set style data / function */ { char *type = (char *)command[PARSE_set_style_numbered_dataset_type].auxil; withWords *outstyle = (type[0]=='d') ? &sg->dataStyle : &sg->funcStyle; withWords ww_tmp, ww_tmp2; ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_set_style_numbered_, 0, &ww_tmp); // this is correct! ppl_withWordsMerge (c, &ww_tmp2, &ww_tmp, outstyle, NULL, NULL, NULL, 0); ppl_withWordsDestroy (c, &ww_tmp); *outstyle = ww_tmp2; ppl_withWordsDestroy (c, &ww_tmp2); } else if (strcmp_set && (strcmp(setoption,"style_numbered")==0)) /* set style */ { double nd = command[PARSE_set_style_numbered_style_set_number].real; int n; withWords *outstyle, ww_tmp, ww_tmp2; if ((nd<0)||(nd>=MAX_PLOTSTYLES)) { sprintf(c->errcontext.tempErrStr, "plot style numbers must be in the range 0-%d", MAX_PLOTSTYLES-1); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } n = (int)floor(nd); outstyle = &(c->set->plot_styles[n]); ppl_withWordsFromDict(c, in, pl, PARSE_TABLE_set_style_numbered_, 0, &ww_tmp); ppl_withWordsMerge (c, &ww_tmp2, &ww_tmp, outstyle, NULL, NULL, NULL, 0); ppl_withWordsDestroy (c, &ww_tmp); ppl_withWordsDestroy (c, outstyle); *outstyle = ww_tmp2; } else if ( (strcmp_unset && (strcmp(setoption,"style")==0)) || /* unset style */ (strcmp_set && (strcmp(setoption,"nostyle")==0)) ) { const int dataset_type = strcmp_set ? PARSE_set_nostyle_dataset_type : PARSE_unset_style_dataset_type; const int style_ids = strcmp_set ? PARSE_set_nostyle_0style_ids : PARSE_unset_style_0style_ids; const int id_style_ids = strcmp_set ? PARSE_set_nostyle_id_0style_ids : PARSE_unset_style_id_0style_ids; if (command[dataset_type].objType==PPLOBJ_STR) { char *type = (char *)command[dataset_type].auxil; withWords *instyle = (type[0]=='d') ? &c->set->graph_default.dataStyle : &c->set->graph_default.funcStyle; withWords *outstyle = (type[0]=='d') ? &sg->dataStyle : &sg->funcStyle; ppl_withWordsDestroy (c, outstyle); ppl_withWordsCpy (c, outstyle, instyle); } else { int pos = style_ids; while (command[pos].objType == PPLOBJ_NUM) { double nd; int n; withWords *outstyle, *instyle; pos = (int)round(command[pos].real); if (pos<=0) break; nd = command[pos+id_style_ids].real; if ((nd<0)||(nd>=MAX_PLOTSTYLES)) { sprintf(c->errcontext.tempErrStr, "plot style numbers must be in the range 0-%d", MAX_PLOTSTYLES-1); ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, NULL); return; } n = (int)floor(nd); outstyle = &(c->set->plot_styles[n]); instyle = &(c->set->plot_styles_default[n]); ppl_withWordsDestroy (c, outstyle); ppl_withWordsCpy (c, outstyle, instyle); } } } else if (strcmp_set && (strcmp(setoption,"terminal")==0)) /* set terminal */ { double tempdbl; char *tempstr = (char *)command[PARSE_set_terminal_term].auxil; int got = (command[PARSE_set_terminal_term].objType == PPLOBJ_STR); if (got) c->set->term_current.TermType = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_TERMTYPE_INT, SW_TERMTYPE_STR); tempstr = (char *)command[PARSE_set_terminal_antiali].auxil; got = (command[PARSE_set_terminal_antiali].objType == PPLOBJ_STR); if (got) c->set->term_current.TermAntiAlias = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_terminal_col].auxil; got = (command[PARSE_set_terminal_col].objType == PPLOBJ_STR); if (got) c->set->term_current.color = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempdbl = command[PARSE_set_terminal_dpi].real; got = (command[PARSE_set_terminal_dpi].objType == PPLOBJ_NUM); if (got) { if (!gsl_finite(tempdbl)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The DPI resolution supplied to the 'set terminal' command was not finite."); } else if (tempdbl <= 2.0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Output image resolutions below two dots per inch are not supported."); } else { c->set->term_current.dpi = tempdbl; } } tempstr = (char *)command[PARSE_set_terminal_enlarge].auxil; got = (command[PARSE_set_terminal_enlarge].objType == PPLOBJ_STR); if (got) c->set->term_current.TermEnlarge = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_terminal_land].auxil; got = (command[PARSE_set_terminal_land].objType == PPLOBJ_STR); if (got) c->set->term_current.landscape = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_terminal_trans].auxil; got = (command[PARSE_set_terminal_trans].objType == PPLOBJ_STR); if (got) c->set->term_current.TermTransparent = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_terminal_invert].auxil; got = (command[PARSE_set_terminal_invert].objType == PPLOBJ_STR); if (got) c->set->term_current.TermInvert = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); } else if (strcmp_unset && (strcmp(setoption,"terminal")==0)) /* unset terminal */ { c->set->term_current.color = c->set->term_default.color; c->set->term_current.dpi = c->set->term_default.dpi; c->set->term_current.landscape = c->set->term_default.landscape; c->set->term_current.TermAntiAlias = c->set->term_default.TermAntiAlias; c->set->term_current.TermType = c->set->term_default.TermType; c->set->term_current.TermEnlarge = c->set->term_default.TermEnlarge; c->set->term_current.TermInvert = c->set->term_default.TermInvert; c->set->term_current.TermTransparent= c->set->term_default.TermTransparent; } else if (strcmp_set && (strcmp(setoption,"texthalign")==0)) /* set texthalign */ { if (command[PARSE_set_texthalign_left ].objType == PPLOBJ_STR) sg->TextHAlign = SW_HALIGN_LEFT; if (command[PARSE_set_texthalign_center].objType == PPLOBJ_STR) sg->TextHAlign = SW_HALIGN_CENT; if (command[PARSE_set_texthalign_right ].objType == PPLOBJ_STR) sg->TextHAlign = SW_HALIGN_RIGHT; } else if (strcmp_unset && (strcmp(setoption,"texthalign")==0)) /* unset texthalign */ { sg->TextHAlign = c->set->graph_default.TextHAlign; } else if (strcmp_set && (strcmp(setoption,"textvalign")==0)) /* set textvalign */ { if (command[PARSE_set_textvalign_top ].objType == PPLOBJ_STR) sg->TextVAlign = SW_VALIGN_TOP; if (command[PARSE_set_textvalign_center].objType == PPLOBJ_STR) sg->TextVAlign = SW_VALIGN_CENT; if (command[PARSE_set_textvalign_bottom].objType == PPLOBJ_STR) sg->TextVAlign = SW_VALIGN_BOT; } else if (strcmp_unset && (strcmp(setoption,"textvalign")==0)) /* unset textvalign */ { sg->TextVAlign = c->set->graph_default.TextVAlign; } else if (strcmp_set && (strcmp(setoption,"tics")==0)) /* set tics */ { int m = (command[PARSE_set_tics_minor].objType==PPLOBJ_STR); const int *ptab = PARSE_TABLE_set_tics_; if (command[PARSE_unset_tics_axis].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_unset_tics_axis].real); int j = (int)round(command[PARSE_unset_tics_axis].exponent[0]); char cmd[16]; sprintf(cmd, "%s%c%d", m?"m":"", 'x'+j, i); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { int *alog; pplset_axis *a; if (j==1) a=&ya[i]; else if (j==2) a=&za[i]; else a=&xa[i]; GET_AXISLOG(alog,a,0); if (!m) { tics_rm(&a->tics ); SET_TICKS(a->tics ,a->ticsM,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } else { tics_rm(&a->ticsM); SET_TICKS(a->ticsM,a->tics ,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } } } else { int i; char *cmd = m ? "mtics" : "tics"; for (i=0; ienabled) { int *alog; GET_AXISLOG(alog,a,0); if (!m) { tics_rm(&a->tics ); SET_TICKS(a->tics ,a->ticsM,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } else { tics_rm(&a->ticsM); SET_TICKS(a->ticsM,a->tics ,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } }} for (i=0; ienabled) { int *alog; GET_AXISLOG(alog,a,0); if (!m) { tics_rm(&a->tics ); SET_TICKS(a->tics ,a->ticsM,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } else { tics_rm(&a->ticsM); SET_TICKS(a->ticsM,a->tics ,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } }} for (i=0; ienabled) { int *alog; GET_AXISLOG(alog,a,0); if (!m) { tics_rm(&a->tics ); SET_TICKS(a->tics ,a->ticsM,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } else { tics_rm(&a->ticsM); SET_TICKS(a->ticsM,a->tics ,a->unit,((a->MinSet==SW_BOOL_TRUE)||(a->MaxSet==SW_BOOL_TRUE)),(*alog==SW_BOOL_TRUE)); } }} } } else if (strcmp_unset && (strcmp(setoption,"tics")==0)) /* unset tics */ { int m = (command[PARSE_unset_tics_minor].objType==PPLOBJ_STR); #define IDE if (ppl_unitsDimEqual(&a->unit , &ad->unit)) if (command[PARSE_unset_tics_axis].objType==PPLOBJ_NUM) { int i = (int)round(command[PARSE_unset_tics_axis].real); int j = (int)round(command[PARSE_unset_tics_axis].exponent[0]); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { if (j==1) { pplset_axis *a=&ya[i], *ad=&c->set->YAxesDefault[i]; if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } else if (j==2) { pplset_axis *a=&za[i], *ad=&c->set->ZAxesDefault[i]; if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } else { pplset_axis *a=&xa[i], *ad=&c->set->XAxesDefault[i]; if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } } } else { int i; for (i=0; iset->XAxesDefault[i]; if (a->enabled) { if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } } for (i=0; iset->YAxesDefault[i]; if (a->enabled) { if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } } for (i=0; iset->ZAxesDefault[i]; if (a->enabled) { if (!m) { tics_rm(&a->tics); IDE tics_cp(&a->tics,&ad->tics); } tics_rm(&a->ticsM); IDE tics_cp(&a->ticsM,&ad->ticsM); } } } } else if (strcmp_set && (strcmp(setoption,"timezone")==0)) /* set timezone */ { char *tempstr = (char *)command[PARSE_set_timezone_timezone].auxil; snprintf(c->set->term_current.timezone, FNAME_LENGTH, "%s", tempstr); c->set->term_current.timezone[FNAME_LENGTH-1]='\0'; } else if (strcmp_unset && (strcmp(setoption,"timezone")==0)) /* unset timezone */ { strcpy(c->set->term_current.timezone, c->set->term_default.timezone); } else if (strcmp_set && (strcmp(setoption,"title")==0)) /* set title */ { if (command[PARSE_set_title_title].objType==PPLOBJ_STR) { char *tempstr = (char *)command[PARSE_set_title_title].auxil; strncpy(sg->title, tempstr, FNAME_LENGTH-1); sg->title[FNAME_LENGTH-1]='\0'; } if (command[PARSE_set_title_offset ].objType==PPLOBJ_NUM) sg->TitleXOff.real = command[PARSE_set_title_offset ].real; if (command[PARSE_set_title_offset+1].objType==PPLOBJ_NUM) sg->TitleYOff.real = command[PARSE_set_title_offset+1].real; } else if (strcmp_unset && (strcmp(setoption,"title")==0)) /* unset title */ { strncpy(sg->title, c->set->graph_default.title, FNAME_LENGTH-1); sg->title[FNAME_LENGTH-1]='\0'; sg->TitleXOff = c->set->graph_default.TitleXOff; sg->TitleYOff = c->set->graph_default.TitleYOff; } else if (strcmp_set && (strcmp(setoption,"trange")==0)) /* set trange */ { if (command[PARSE_set_trange_range].objType==PPLOBJ_STR) { pplObj *min = &command[PARSE_set_trange_min]; pplObj *max = &command[PARSE_set_trange_max]; if ((min->objType!=PPLOBJ_NUM)) min = &sg->Tmin; if ((max->objType!=PPLOBJ_NUM)) max = &sg->Tmax; if ((!gsl_finite(min->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set trange' command had non-finite limits."); return; } if ((!gsl_finite(max->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set trange' command had non-finite limits."); return; } if ((!ppl_unitsDimEqual(min,max))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Attempt to set trange with dimensionally incompatible minimum and maximum."); return; } sg->Tmin = *min; sg->Tmax = *max; } if (command[PARSE_set_trange_reverse].objType==PPLOBJ_STR) { pplObj tmp = sg->Tmin; sg->Tmin = sg->Tmax; sg->Tmax = tmp; } sg->USE_T_or_uv = 1; } else if (strcmp_unset && (strcmp(setoption,"trange")==0)) /* unset trange */ { sg->USE_T_or_uv = c->set->graph_default.USE_T_or_uv; sg->Tmin = c->set->graph_default.Tmin; sg->Tmax = c->set->graph_default.Tmax; } else if (strcmp_set && (strcmp(setoption,"unit")==0)) /* set unit */ { int got, got2, got3; char *tempstr, *tempstr2=NULL, *tempstr3=NULL; tempstr = (char *)command[PARSE_set_unit_abbrev].auxil; got = (command[PARSE_set_unit_abbrev].objType == PPLOBJ_STR); if (got) c->set->term_current.UnitDisplayAbbrev = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_unit_angle].auxil; got = (command[PARSE_set_unit_angle].objType == PPLOBJ_STR); if (got) c->set->term_current.UnitAngleDimless = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_unit_prefix].auxil; got = (command[PARSE_set_unit_prefix].objType == PPLOBJ_STR); if (got) c->set->term_current.UnitDisplayPrefix = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_ONOFF_INT, SW_ONOFF_STR); tempstr = (char *)command[PARSE_set_unit_scheme].auxil; got = (command[PARSE_set_unit_scheme].objType == PPLOBJ_STR); if (got) c->set->term_current.UnitScheme = ppl_fetchSettingByName(&c->errcontext, tempstr, SW_UNITSCH_INT, SW_UNITSCH_STR); got2 = (command[PARSE_set_unit_preferred_unit].objType == PPLOBJ_EXP); if (got2) tempstr2 = ((pplExpr *)command[PARSE_set_unit_preferred_unit].auxil)->ascii; got3 = (command[PARSE_set_unit_unpreferred_unit].objType == PPLOBJ_EXP); if (got3) tempstr3 = ((pplExpr *)command[PARSE_set_unit_unpreferred_unit].auxil)->ascii; if (got2 || got3) { int i; char *buf = (char *)ppl_memAlloc(LSTR_LENGTH); PreferredUnit *pu, *pui; if (buf==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory."); } else for (i=0; i<2; i++) { int errpos=-1; listIterator *listiter; if (i==0) { if (!got2) continue; tempstr=tempstr2; } else { if (!got3) continue; tempstr=tempstr3; } ppl_newPreferredUnit(c, &pu, tempstr, 0, &errpos, buf); if (errpos>=0) { ppl_error(&c->errcontext, ERR_NUMERICAL,-1,-1,buf); continue; } // Remove any preferred unit which is dimensionally equal to new preferred unit listiter = ppl_listIterateInit(c->unit_PreferredUnits); while (listiter != NULL) { pui = (PreferredUnit *)listiter->data; ppl_listIterate(&listiter); if (ppl_unitsDimEqual(&pui->value , &pu->value) && (pui->value.tempType == pu->value.tempType)) ppl_listRemove(c->unit_PreferredUnits, (void *)pui ); } // Add new preferred unit if (i==0) ppl_listAppendCpy(c->unit_PreferredUnits, (void *)pu, sizeof(PreferredUnit)); } } // set unit of length meter { int pos = PARSE_set_unit_preferred_units; while (command[pos].objType == PPLOBJ_NUM) { int i=0, j=0, k=0, l=0, m=0, multiplier; int p=0; int pp=0; char *quantity, *unit; pos = (int)round(command[pos].real); if (pos<=0) break; quantity = (char *)command[pos+PARSE_set_unit_quantity_preferred_units].auxil; unit = (char *)command[pos+PARSE_set_unit_unit_preferred_units].auxil; for (j=0; junit_pos; j++) { if (i>1) i=1; if ((c->unit_database[j].quantity != NULL) && (ppl_strCmpNoCase(c->unit_database[j].quantity, quantity) == 0)) { i=2; c->unit_database[j].userSel = 0; } if (pp!=0) continue; multiplier = 8; if ((k = ppl_unitNameCmp(unit, c->unit_database[j].nameAp,1))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].nameAs,1))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].nameFs,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].nameFp,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].alt1 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].alt2 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].alt3 ,0))!=0) p=1; else if ((k = ppl_unitNameCmp(unit, c->unit_database[j].alt4 ,0))!=0) p=1; else { for (l=c->unit_database[j].minPrefix/3+8; l<=c->unit_database[j].maxPrefix/3+8; l++) { if (l==8) continue; for (k=0; ((SIprefixes_full[l][k]!='\0') && (toupper(SIprefixes_full[l][k])==toupper(unit[k]))); k++); if (SIprefixes_full[l][k]=='\0') { if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].nameFp,0))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].nameFs,0))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].alt1 ,0))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].alt2 ,0))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].alt3 ,0))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].alt4 ,0))!=0) { p=1; k+=m; multiplier=l; break; } } for (k=0; ((SIprefixes_abbrev[l][k]!='\0') && (SIprefixes_abbrev[l][k]==unit[k])); k++); if (SIprefixes_abbrev[l][k]=='\0') { if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].nameAp,1))!=0) { p=1; k+=m; multiplier=l; break; } else if ((m = ppl_unitNameCmp(unit+k, c->unit_database[j].nameAs,1))!=0) { p=1; k+=m; multiplier=l; break; } } } } if (p==0) continue; if (i!=2) { if ((c->unit_database[j].quantity!=NULL) && (c->unit_database[j].quantity[0]!='\0')) { sprintf(c->errcontext.tempErrStr, "'%s' is not a unit of '%s', but of '%s'.", unit, quantity, c->unit_database[j].quantity); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); } else { sprintf(c->errcontext.tempErrStr, "'%s' is not a unit of '%s'.", unit, quantity); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); } } c->unit_database[j].userSel = 1; c->unit_database[j].userSelPrefix = multiplier; pp=1; } if (i==0) { sprintf(c->errcontext.tempErrStr, "No such quantity as a '%s'.", quantity); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); } if (p==0) { sprintf(c->errcontext.tempErrStr, "No such unit as a '%s'.", unit); ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); } } } } else if (strcmp_unset && (strcmp(setoption,"unit")==0)) /* unset unit */ { c->set->term_current.UnitAngleDimless = c->set->term_default.UnitAngleDimless; c->set->term_current.UnitDisplayAbbrev = c->set->term_default.UnitDisplayAbbrev; c->set->term_current.UnitDisplayPrefix = c->set->term_default.UnitDisplayPrefix; c->set->term_current.UnitScheme = c->set->term_default.UnitScheme; for (i=0; iunit_pos; i++) c->unit_database[i].userSel = 0; ppl_listFree(c->unit_PreferredUnits); c->unit_PreferredUnits = ppl_listCpy(c->unit_PreferredUnits_default, 1, sizeof(PreferredUnit)); } else if (strcmp_unset && (strcmp(setoption,"unit_angle")==0)) /* unset unit angle */ { c->set->term_current.UnitAngleDimless = c->set->term_default.UnitAngleDimless; } else if (strcmp_unset && (strcmp(setoption,"unit_display")==0)) /* unset unit display */ { c->set->term_current.UnitDisplayAbbrev = c->set->term_default.UnitDisplayAbbrev; c->set->term_current.UnitDisplayPrefix = c->set->term_default.UnitDisplayPrefix; } else if (strcmp_unset && (strcmp(setoption,"unit_scheme")==0)) /* unset unit scheme */ { c->set->term_current.UnitScheme = c->set->term_default.UnitScheme; } else if (strcmp_set && (strcmp(setoption,"urange")==0)) /* set urange */ { if (command[PARSE_set_urange_range].objType==PPLOBJ_STR) { pplObj *min = &command[PARSE_set_urange_min]; pplObj *max = &command[PARSE_set_urange_max]; if ((min->objType!=PPLOBJ_NUM)) min = &sg->Umin; if ((max->objType!=PPLOBJ_NUM)) max = &sg->Umax; if ((!gsl_finite(min->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set urange' command had non-finite limits."); return; } if ((!gsl_finite(max->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set urange' command had non-finite limits."); return; } if ((!ppl_unitsDimEqual(min,max))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Attempt to set urange with dimensionally incompatible minimum and maximum."); return; } sg->Umin = *min; sg->Umax = *max; } if (command[PARSE_set_urange_reverse].objType==PPLOBJ_STR) { pplObj tmp = sg->Umin; sg->Umin = sg->Umax; sg->Umax = tmp; } sg->USE_T_or_uv = 0; } else if (strcmp_unset && (strcmp(setoption,"urange")==0)) /* unset urange */ { sg->USE_T_or_uv = c->set->graph_default.USE_T_or_uv; sg->Umin = c->set->graph_default.Umin; sg->Umax = c->set->graph_default.Umax; } else if (strcmp_set && (strcmp(setoption,"vrange")==0)) /* set vrange */ { if (command[PARSE_set_vrange_range].objType==PPLOBJ_STR) { pplObj *min = &command[PARSE_set_vrange_min]; pplObj *max = &command[PARSE_set_vrange_max]; if ((min->objType!=PPLOBJ_NUM)) min = &sg->Tmin; if ((max->objType!=PPLOBJ_NUM)) max = &sg->Tmax; if ((!gsl_finite(min->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set vrange' command had non-finite limits."); return; } if ((!gsl_finite(max->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set vrange' command had non-finite limits."); return; } if ((!ppl_unitsDimEqual(min,max))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Attempt to set vrange with dimensionally incompatible minimum and maximum."); return; } sg->Vmin = *min; sg->Vmax = *max; } if (command[PARSE_set_vrange_reverse].objType==PPLOBJ_STR) { pplObj tmp = sg->Vmin; sg->Vmin = sg->Vmax; sg->Vmax = tmp; } sg->USE_T_or_uv = 0; } else if (strcmp_unset && (strcmp(setoption,"vrange")==0)) /* unset vrange */ { sg->USE_T_or_uv = c->set->graph_default.USE_T_or_uv; sg->Vmin = c->set->graph_default.Vmin; sg->Vmax = c->set->graph_default.Vmax; } else if (strcmp_set && (strcmp(setoption,"view")==0)) /* set view */ { if (command[PARSE_set_view_xy_angle].objType==PPLOBJ_NUM) { double d=command[PARSE_set_view_xy_angle].real; if (!gsl_finite(d)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The viewing angles supplied to the 'set view' command were not finite."); return; } sg->XYview.real = d; } if (command[PARSE_set_view_yz_angle].objType==PPLOBJ_NUM) { double d=command[PARSE_set_view_yz_angle].real; if (!gsl_finite(d)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The viewing angles supplied to the 'set view' command were not finite."); return; } sg->YZview.real = d; } sg->XYview.real = fmod(sg->XYview.real , 2*M_PI); sg->YZview.real = fmod(sg->YZview.real , 2*M_PI); while (sg->XYview.real < 0.0) sg->XYview.real += 2*M_PI; while (sg->YZview.real < 0.0) sg->YZview.real += 2*M_PI; } else if (strcmp_unset && (strcmp(setoption,"view")==0)) /* unset view */ { sg->XYview.real = c->set->graph_default.XYview.real; sg->YZview.real = c->set->graph_default.YZview.real; } else if (strcmp_set && (strcmp(setoption,"width")==0)) /* set width */ { if (command[PARSE_set_width_width].objType==PPLOBJ_NUM) { if (!gsl_finite(command[PARSE_set_width_width].real)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "The width supplied to the 'set width' command was not finite."); return; } sg->width.real=command[PARSE_set_width_width].real; } } else if (strcmp_unset && (strcmp(setoption,"width")==0)) /* unset width */ { sg->width.real = c->set->graph_default.width.real; } else if (strcmp_set && (strcmp(setoption,"viewer")==0)) /* set viewer */ { int changedViewer = 0; if (command[PARSE_set_viewer_auto_viewer].objType == PPLOBJ_STR) { int viewerOld = c->set->term_current.viewer; if (strcmp(GHOSTVIEW_COMMAND, "/bin/false")!=0) c->set->term_current.viewer = SW_VIEWER_GV; else if (strcmp(GGV_COMMAND , "/bin/false")!=0) c->set->term_current.viewer = SW_VIEWER_GGV; else c->set->term_current.viewer = SW_VIEWER_NULL; changedViewer = (viewerOld != c->set->term_current.viewer); } else { char *nv = (char *)command[PARSE_set_viewer_viewer].auxil; if (c->set->term_current.viewer != SW_VIEWER_CUSTOM) { changedViewer=1; c->set->term_current.viewer = SW_VIEWER_CUSTOM; } if (strcmp(c->set->term_current.ViewerCmd, nv)!=0) { changedViewer=1; snprintf(c->set->term_current.ViewerCmd, FNAME_LENGTH, "%s", nv); } c->set->term_current.ViewerCmd[FNAME_LENGTH-1]='\0'; } if (changedViewer) pplcsp_sendCommand(c,"A\n"); // Clear away SingleWindow viewer } else if (strcmp_unset && (strcmp(setoption,"viewer")==0)) /* unset viewer */ { int changedViewer = ( (c->set->term_current.viewer != c->set->term_default.viewer) || (strcmp(c->set->term_current.ViewerCmd,c->set->term_default.ViewerCmd)!=0) ); c->set->term_current.viewer = c->set->term_default.viewer; strcpy(c->set->term_current.ViewerCmd, c->set->term_default.ViewerCmd); if (changedViewer) pplcsp_sendCommand(c,"A\n"); // Clear away SingleWindow viewer } else if (strcmp(setoption,"xformat")==0) /* set xformat | unset xformat */ { int i,j; if (strcmp_set) { i = (int)round(command[PARSE_set_xformat_axis ].real); j = (int)round(command[PARSE_set_xformat_axis ].exponent[0]); } else { i = (int)round(command[PARSE_unset_xformat_axis].real); j = (int)round(command[PARSE_unset_xformat_axis].exponent[0]); } if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplset_axis *a, *ad; if (j==1) { a = &ya[i]; ad = &c->set->YAxesDefault[i]; } else if (j==2) { a = &za[i]; ad = &c->set->ZAxesDefault[i]; } else { a = &xa[i]; ad = &c->set->XAxesDefault[i]; } if (strcmp_set) { a->enabled = 1; if (command[PARSE_set_xformat_format_string].objType == PPLOBJ_EXP) { if (a->format != NULL) pplExpr_free((pplExpr *)a->format); a->format = (void *)pplExpr_cpy((pplExpr *)command[PARSE_set_xformat_format_string].auxil); } if (command[PARSE_set_xformat_auto_format].objType == PPLOBJ_STR) { if (a->format != NULL) { pplExpr_free((pplExpr *)a->format); a->format=NULL; } } if (command[PARSE_set_xformat_orient].objType == PPLOBJ_STR) { a->TickLabelRotation = ppl_fetchSettingByName(&c->errcontext, (char *)command[PARSE_set_xformat_orient].auxil, SW_TICLABDIR_INT, SW_TICLABDIR_STR); a->TickLabelRotate = ad->TickLabelRotate; } if (command[PARSE_set_xformat_rotation].objType == PPLOBJ_NUM) { double r = command[PARSE_set_xformat_rotation].real; if (!gsl_finite(r)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The rotation angle supplied to the 'set format' command was not finite."); return; } a->TickLabelRotate = r; // TickLabelRotation will already have been set by "rotate" keyword mapping to "orient" } } else { if (a->format != NULL) { pplExpr_free((pplExpr *)a->format); a->format=NULL; } a->format = (void *)pplExpr_cpy((pplExpr *)ad->format); a->TickLabelRotation = ad->TickLabelRotation; a->TickLabelRotate = ad->TickLabelRotate; } } } else if (strcmp(setoption,"xlabel")==0) /* set xlabel */ { int i = (int)round(command[strcmp_set ? PARSE_set_xlabel_axis : PARSE_unset_xlabel_axis].real); int j = (int)round(command[strcmp_set ? PARSE_set_xlabel_axis : PARSE_unset_xlabel_axis].exponent[0]); if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplset_axis *a; if (j==1) a = &ya[i]; else if (j==2) a = &za[i]; else a = &xa[i]; if (strcmp_set) { a->enabled = 1; if (command[PARSE_set_xlabel_label_text].objType == PPLOBJ_STR) { char *in = (char *)command[PARSE_set_xlabel_label_text].auxil; char *l = (char *)malloc(strlen(in)+1); if (l!=NULL) strcpy(l,in); if (a->label!=NULL) free(a->label); a->label=l; } if (command[PARSE_set_xlabel_rotation].objType == PPLOBJ_NUM) { double r = command[PARSE_set_xlabel_rotation].real; if (!gsl_finite(r)) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The rotation angle supplied to the set axis label command was not finite."); return; } a->LabelRotate = r; } } else { char *in = c->set->axis_default.label; char *l = (in==NULL) ? NULL : (char *)malloc(strlen(in)+1); if (l!=NULL) strcpy(l,in); if (a->label!=NULL) free(a->label); a->label=l; a->LabelRotate = c->set->axis_default.LabelRotate; } } } else if (strcmp(setoption,"range")==0) /* set xrange | unset xrange */ { int i,j; if (strcmp_set) { i = (int)round(command[PARSE_set_range_axis ].real); j = (int)round(command[PARSE_set_range_axis ].exponent[0]); } else { i = (int)round(command[PARSE_unset_range_axis].real); j = (int)round(command[PARSE_unset_range_axis].exponent[0]); } if ( !((xa==NULL)||(ya==NULL)||(za==NULL)) ) { pplset_axis *a, *ad; pplObj *unitNew, unitOld; if (j==1) { a = &ya[i]; ad = &c->set->YAxesDefault[i]; } else if (j==2) { a = &za[i]; ad = &c->set->ZAxesDefault[i]; } else { a = &xa[i]; ad = &c->set->XAxesDefault[i]; } unitOld = a->unit; if (strcmp_set) { pplObj *min = &command[PARSE_set_range_min], d1, d2; pplObj *max = &command[PARSE_set_range_max]; int mina = (command[PARSE_set_range_minauto].objType == PPLOBJ_STR); int maxa = (command[PARSE_set_range_maxauto].objType == PPLOBJ_STR); if (command[PARSE_set_range_reverse ].objType == PPLOBJ_STR) a->RangeReversed = 1; if (command[PARSE_set_range_noreverse ].objType == PPLOBJ_STR) a->RangeReversed = 0; if ((!mina)&&(min->objType!=PPLOBJ_NUM)&&(a->MinSet==SW_BOOL_TRUE)) { min=&d1; d1=a->unit; d1.real=a->min; } if ((!maxa)&&(max->objType!=PPLOBJ_NUM)&&(a->MaxSet==SW_BOOL_TRUE)) { max=&d2; d2=a->unit; d2.real=a->max; } if ((min->objType==PPLOBJ_NUM)&&(!gsl_finite(min->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set range' command had non-finite limits."); return; } if ((max->objType==PPLOBJ_NUM)&&(!gsl_finite(max->real))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "The range supplied to the 'set range' command had non-finite limits."); return; } if ((min->objType==PPLOBJ_NUM)&&(max->objType==PPLOBJ_NUM)&&(!ppl_unitsDimEqual(min,max))) { ppl_error(&c->errcontext, ERR_NUMERICAL, -1, -1, "Attempt to set range with dimensionally incompatible minimum and maximum."); return; } if (min->objType==PPLOBJ_NUM) { a->unit = *min; a->min = min->real; a->MinSet = SW_BOOL_TRUE; } if (max->objType==PPLOBJ_NUM) { a->unit = *max; a->max = max->real; a->MaxSet = SW_BOOL_TRUE; } if (mina) { a->MinSet = SW_BOOL_FALSE; a->min = ad->min; } if (maxa) { a->MaxSet = SW_BOOL_FALSE; a->max = ad->max; } a->enabled = 1; } else { a->unit = ad->unit; a->max = ad->max; a->MaxSet = ad->MaxSet; a->min = ad->min; a->MinSet = ad->MinSet; a->RangeReversed = ad->RangeReversed; } // Check whether ticks need removing, if units of axis have changed unitNew = &a->unit; if (!ppl_unitsDimEqual(unitNew,&unitOld)) { tics_rm(&a->tics); tics_rm(&a->ticsM); } } } else { sprintf(c->errcontext.tempErrStr, "Pyxplot's set command could not find handler for the set option <%s>.", setoption); ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, NULL); } return; } pyxplot-0.9.2/src/commands/funcset.c0000664000175000017500000002774412026340554016045 0ustar dcf21dcf21// funcset.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: funcset.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/dict.h" #include "coreUtils/errorReport.h" #include "expressions/expCompile_fns.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "pplConstants.h" #define TBADD(et,charpos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,charpos,pl->linetxt,"") void ppl_directive_funcset(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplObj *stk = in->stk; pplFunc *f = NULL; int i, j, nArgs=0, pos, posR, argListLen=0; int needToStoreNan=0, nullDefn=0; pplObj *tmpObj; // Count number of arguments pos = PARSE_func_set_0argument_list; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { char *name; pos = (int)round(stk[pos].real); name = (char *)stk[pos+PARSE_func_set_argument_name_0argument_list].auxil; nArgs++; argListLen+=strlen(name)+1; } if (nArgs > FUNC_MAXARGS) { sprintf(c->errStat.errBuff, "Too many arguments to function; the maximum allowed number is %d.", FUNC_MAXARGS); TBADD(ERR_OVERFLOW,0); return; } // Are we defining or undefining this function? nullDefn = (stk[PARSE_func_set_definition].objType != PPLOBJ_EXP); // Allocate function descriptor f = (pplFunc *)malloc(sizeof(pplFunc)); if (f==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY,0); return; } f->functionType = PPL_FUNC_USERDEF; f->refCount = 1; f->minArgs = nArgs; f->maxArgs = nArgs; f->functionPtr = nullDefn ? NULL : pplExpr_cpy((pplExpr *)stk[PARSE_func_set_definition].auxil); f->argList = (char *)malloc(argListLen); f->min = (pplObj *)malloc(nArgs*sizeof(pplObj)); f->max = (pplObj *)malloc(nArgs*sizeof(pplObj)); f->minActive = (unsigned char *)malloc(nArgs); f->maxActive = (unsigned char *)malloc(nArgs); f->numOnly = 0; f->notNan = 0; f->realOnly = 0; f->dimlessOnly = 0; f->needSelfThis = 0; f->next = NULL; f->LaTeX = NULL; f->description = NULL; f->descriptionShort = NULL; if ((f->argList==NULL)||((!nullDefn)&&(f->functionPtr==NULL))||(f->min==NULL)||(f->max==NULL)||(f->minActive==NULL)||(f->maxActive==NULL)) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY,0); goto fail; } // Put ranges and argument names into structures pos = PARSE_func_set_0argument_list; posR = PARSE_func_set_0range_list; i = 0; j = 0; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { char *name; pos = (int)round(stk[pos].real); name = (char *)stk[pos+PARSE_func_set_argument_name_0argument_list].auxil; strcpy(f->argList+i, name); i+= strlen(name)+1; if ((stk[posR].objType == PPLOBJ_NUM) && (stk[posR].real > 0)) { pplObj *min, *max; posR = (int)round(stk[posR].real); min = &stk[posR+PARSE_func_set_min_0range_list]; max = &stk[posR+PARSE_func_set_max_0range_list]; // Check that the specified minimum is not complex if (min->objType != PPLOBJ_NUM) { pplObjZom(f->min+j,0); f->minActive[j]=0; } else { if (min->flagComplex) { sprintf(c->errStat.errBuff, "Where ranges are specified for function arguments, these must be real numbers. Ranges may not be imposed upon complex arguments to functions."); TBADD(ERR_NUMERICAL,in->stkCharPos[posR+PARSE_func_set_min_0range_list]); goto fail; } pplObjCpy(f->min+j,min,0,0,1); f->minActive[j]=1; } // Check that specified maximum is not complex, and does not conflict with units of minimum if (max->objType != PPLOBJ_NUM) { pplObjZom(f->max+j,0); f->maxActive[j]=0; } else { if (max->flagComplex) { sprintf(c->errStat.errBuff, "Where ranges are specified for function arguments, these must be real numbers. Ranges may not be imposed upon complex arguments to functions."); TBADD(ERR_NUMERICAL,in->stkCharPos[posR+PARSE_func_set_max_0range_list]); goto fail; } if (f->minActive[j] && !ppl_unitsDimEqual(min,max)) { sprintf(c->errStat.errBuff, "The minimum and maximum values specified for argument number %d are dimensionally incompatible: the minimum has dimensions of <%s>, while the maximum has dimensions of <%s>.",j+1,ppl_printUnit(c,min,NULL,NULL,0,1,0),ppl_printUnit(c,min,NULL,NULL,1,1,0)); TBADD(ERR_NUMERICAL,in->stkCharPos[posR+PARSE_func_set_max_0range_list]); goto fail; } pplObjCpy(f->max+j,max,0,0,1); f->maxActive[j]=1; } // If maximum and minimum are the wrong way around, swap them if (f->minActive[j] && f->maxActive[j] && (min->real > max->real)) { double tmp = f->max[j].real; f->max[j].real = f->min[j].real; f->min[j].real = tmp; } } else { f->minActive[j] = f->maxActive[j] = 0; } j++; } // Look up function or variable we are superseding ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &tmpObj, PARSE_func_set_function_names, PARSE_func_set_function_name_function_names); if ((c->errStat.status) || (tmpObj==NULL)) goto fail; if (tmpObj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD(ERR_NAMESPACE,0); goto fail; } // If not a function, we delete it and supersede it if ( (tmpObj->objType!=PPLOBJ_FUNC) || (((pplFunc*)tmpObj->auxil)->functionType!=PPL_FUNC_USERDEF) || (((pplFunc*)tmpObj->auxil)->minArgs!=nArgs) ) goto supersede; // If old function has dimensionally incompatible limits with us, we cannot splice with it; supersede it { int k; pplFunc *fIter; for (fIter = (pplFunc*)tmpObj->auxil ; fIter!=NULL ; fIter=fIter->next) for (k=0; kminActive[k])&&(fIter->minActive[k])&&(!ppl_unitsDimEqual(f->min+k , fIter->min+k))) || ((f->minActive[k])&&(fIter->maxActive[k])&&(!ppl_unitsDimEqual(f->min+k , fIter->max+k))) || ((f->maxActive[k])&&(fIter->minActive[k])&&(!ppl_unitsDimEqual(f->max+k , fIter->min+k))) || ((f->maxActive[k])&&(fIter->maxActive[k])&&(!ppl_unitsDimEqual(f->max+k , fIter->max+k))) ) goto supersede; } // If old function has ranges which extend outside our range, we should not supersede it { pplFunc **fIterPtr = (pplFunc **)&tmpObj->auxil; pplFunc *fIter = *fIterPtr; for ( ; fIter!=NULL ; ) { int k, Nsupersede=0, Noverlap=0, Nmiss=0, lastOverlapType=0, lastOverlapK=0; for (k=0; kminActive[k])|| (( fIter->minActive[k])&&(fIter->min[k].real>=f->min[k].real))) && ((!f->maxActive[k])|| (( fIter->maxActive[k])&&(fIter->max[k].real<=f->max[k].real))) ) Nsupersede++; // New min/max range completely encompasses old else if ( (( f->minActive[k])&& ( fIter->maxActive[k])&&(fIter->max[k].real<=f->min[k].real) ) || (( f->maxActive[k])&& ( fIter->minActive[k])&&(fIter->min[k].real>=f->max[k].real) ) ) Nmiss++; // New min/max range completely outside old else if ( ( f->minActive[k])&& ((!fIter->minActive[k])||(fIter->min[k].real< f->min[k].real)) && ( f->maxActive[k])&& ((!fIter->maxActive[k])||(fIter->max[k].real> f->max[k].real)) ) { Noverlap++; lastOverlapType = 2; lastOverlapK = k; } // New range in middle of old else if ( ( f->minActive[k])&&((( fIter->maxActive[k])&&(fIter->max[k].real> f->min[k].real) && ((!f ->maxActive[k])||(fIter->max[k].real<=f->max[k].real)))|| ((!fIter->maxActive[k])&&(!f->maxActive[k] )) )) { Noverlap++; lastOverlapType = 3; lastOverlapK = k; } // New range goes off top of old else if ( ( f->maxActive[k])&&((( fIter->minActive[k])&&(fIter->min[k].real< f->max[k].real) && ((!f ->minActive[k])||(fIter->min[k].real>=f->min[k].real)))|| ((!fIter->minActive[k])&&(!f->minActive[k] )) )) { Noverlap++; lastOverlapType = 1; lastOverlapK = k; } // New range goes off bottom of old else ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Could not work out how the ranges of two functions overlap"); } if ((Nmiss==0) && (Noverlap==0)) // Remove entry from linked list; we supersede its range on all axes { *fIterPtr = fIter->next; pplObjFuncDestroy(fIter); fIter = *fIterPtr; continue; } else if ((Nmiss==0) && (Noverlap==1)) // we should reduce the range of the function we overlap with { if (lastOverlapType == 1) // Bring lower limit of old definition up above maximum for this new definition { fIter->min[lastOverlapK] = f->max[lastOverlapK]; fIter->minActive[lastOverlapK] = 1; } else if (lastOverlapType == 3) // Bring upper limit of old definition down below minimum for this new definition { fIter->max[lastOverlapK] = f->min[lastOverlapK]; fIter->maxActive[lastOverlapK] = 1; } else // Old definition is cut in two by the new definition; duplicate it. { pplFunc *dup=pplObjFuncCpy(fIter); fIter->max[lastOverlapK] = f->min[lastOverlapK]; fIter->maxActive[lastOverlapK] = 1; dup ->min[lastOverlapK] = f->max[lastOverlapK]; dup ->minActive[lastOverlapK] = 1; dup ->next = fIter->next; fIter->next = dup; } } else if (nullDefn && (Nmiss==0) && (Noverlap>1)) // We are undefining the function, but overlap is complicated. Best we can do is store undefinition. { needToStoreNan = 1; } // Move along linked list fIterPtr = &fIter->next; fIter = fIter->next; } } // If definition is null, only insert it if it has complicated overlap if (nullDefn && !needToStoreNan) { if (tmpObj->auxil==NULL) pplObjZom(tmpObj,1); return; } // Add new function definition to chain of other definitions f->next = (pplFunc *)tmpObj->auxil; tmpObj->auxil = (void *)f; return; supersede: { int rc = tmpObj->refCount; int om = tmpObj->amMalloced; tmpObj->refCount =1; tmpObj->amMalloced=0; ppl_garbageObject(tmpObj); tmpObj->refCount = rc; pplObjFunc(tmpObj,om,1,f); } return; fail: if (f!=NULL) { if (f->argList != NULL) free(f->argList); if (f->min != NULL) free(f->min); if (f->max != NULL) free(f->max); if (f->minActive != NULL) free(f->minActive); if (f->maxActive != NULL) free(f->maxActive); if (f->functionPtr != NULL) pplExpr_free((pplExpr *)f->functionPtr); free(f); } return; } pyxplot-0.9.2/src/commands/fft.c0000664000175000017500000006513012026340554015144 0ustar dcf21dcf21// fft.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: fft.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _FFT_C 1 #include #include #include #include #include #ifdef HAVE_FFTW3 #include #else #include #endif #include "commands/fft.h" #include "coreUtils/memAlloc.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { sprintf(c->errcontext.tempErrStr,"Stack forward reference detected."); TBADD2(ERR_INTERNAL,0); return; } \ } #define STACK_CLEAN while (c->stackPtr>stkLevelOld) { STACK_POP; } #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define COUNTEDERR1 if (errCount >0) { errCount--; #define COUNTEDERR2 if (errCount==0) { sprintf(c->errcontext.tempErrStr, "%s: Too many errors: no more errors will be shown.",filenameOut); ppl_warning(&c->errcontext,ERR_STACKED,NULL); } } // Window functions for FFTs static void fftwindow_rectangular (pplObj *x, int Ndim, int *Npos, int *Nstep) { } static void fftwindow_hamming (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_hann (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_cosine (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_lanczos (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0,z; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_bartlett (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_triangular (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_gauss (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; const double sigma=0.5; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_bartletthann(pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } static void fftwindow_blackman (pplObj *x, int Ndim, int *Npos, int *Nstep) { double y=1.0; const double alpha=0.16; int i; for (i=0; ireal*=y; x->imag*=y; if (x->imag==0.0) { x->imag=0.0; x->flagComplex=0; } } // Main entry point for the FFT command void ppl_directive_fft(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; dataTable *data; dataBlock *blk; long int i=0, k; int contextLocalVec, contextDataTab, errCount=DATAFILE_NERRS; int Ndims=0, inverse, Nsamples, Nsteps[USING_ITEMS_MAX]; pplFunc *funcPtr; pplObj firstEntry; char filenameOut[FNAME_LENGTH]=""; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX], step[USING_ITEMS_MAX]; parserLine *spool=NULL, **dataSpool = &spool; fftw_complex *datagrid; FFTDescriptor *output; void (*WindowType)(pplObj *,int,int *,int *); #ifdef HAVE_FFTW3 fftw_plan fftwplan; // FFTW 3.x #else fftwnd_plan fftwplan; // FFTW 2.x #endif // Check whether we are doing a forward or a backward FFT if (strcmp((char *)stk[PARSE_ifft_directive].auxil,"ifft")==0) inverse=1; else inverse=0; // Read ranges { int i,pos=PARSE_ifft_range_list,nr=0; const int o1 = PARSE_ifft_min_range_list; const int o2 = PARSE_ifft_max_range_list; const int o3 = PARSE_ifft_step_range_list; for (i=0; i=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff,"Too many ranges specified; a maximum of %d are allowed.",USING_ITEMS_MAX); TBADD2(ERR_SYNTAX,0); return; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_ifft_min_range_list]); return; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_ifft_min_range_list]); return; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } if ((stk[pos+o3].objType==PPLOBJ_NUM)||(stk[pos+o3].objType==PPLOBJ_DATE)||(stk[pos+o3].objType==PPLOBJ_BOOL)) { int tempDbl; if (unit[nr].objType!=stk[pos+o3].objType) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting types of <%s> and <%s>.", nr+1, pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o3].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_ifft_step_range_list]); return; } if (!ppl_unitsDimEqual(&unit[nr],&stk[pos+o3])) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d have conflicting physical units of <%s> and <%s>.", nr+1, ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o3],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_ifft_step_range_list]); return; } step[nr]= stk[pos+o3].real; tempDbl = 1.0 + floor((max[nr]-min[nr]) / step[nr] + 0.5); // Add one because this is a fencepost problem if (tempDbl<2.0) { sprintf(c->errStat.errBuff, "The number of samples produced by the range and step size specified for dimension %d to the fft command is fewer than two; a single data sample cannot be FFTed.", nr+1); TBADD2(ERR_RANGE,in->stkCharPos[pos+PARSE_ifft_step_range_list]); return; } if ((!gsl_finite(tempDbl)||(tempDbl>1e8))) { sprintf(c->errStat.errBuff, "The number of samples produced by the range and step size specified for dimension %d to the fft command is in excess of 1e8; Pyxplot is not the right tool to do this FFT in.", nr+1); TBADD2(ERR_RANGE,in->stkCharPos[pos+PARSE_ifft_step_range_list]); return; } Nsteps[nr] = (int)tempDbl; } else { Nsteps[nr] = 100; // shouldn't be here step [nr] = floor((max[nr]-min[nr]) / (Nsteps[nr]-1)); } nr++; } Ndims=nr; } // Work out total size of FFT data grid { double tempDbl = 1.0; for (i=0; i 1e8) { sprintf(c->errStat.errBuff, "The total number of samples in the requested %d-dimensional FFT is in excess of 1e8; Pyxplot is not the right tool to do this FFT in.", Ndims); TBADD2(ERR_NUMERICAL,0); return; } Nsamples = (int)tempDbl; } // Allocate a new memory context for the data file we're about to read contextLocalVec= ppl_memAlloc_DescendIntoNewContext(); contextDataTab = ppl_memAlloc_DescendIntoNewContext(); // Work out what type of window we're going to use { int gotWindow = (stk[PARSE_ifft_window].objType==PPLOBJ_STR); char *cptr = (char *)stk[PARSE_ifft_window].auxil; WindowType = fftwindow_rectangular; if (gotWindow) { if (strcmp(cptr,"hamming" )!=0) WindowType = fftwindow_hamming; else if (strcmp(cptr,"hann" )!=0) WindowType = fftwindow_hann; else if (strcmp(cptr,"cosine" )!=0) WindowType = fftwindow_cosine; else if (strcmp(cptr,"lanczos" )!=0) WindowType = fftwindow_lanczos; else if (strcmp(cptr,"bartlett" )!=0) WindowType = fftwindow_bartlett; else if (strcmp(cptr,"triangular" )!=0) WindowType = fftwindow_triangular; else if (strcmp(cptr,"gauss" )!=0) WindowType = fftwindow_gauss; else if (strcmp(cptr,"bartletthann")!=0) WindowType = fftwindow_bartletthann; else if (strcmp(cptr,"blackman" )!=0) WindowType = fftwindow_blackman; } } // Read input data if (stk[PARSE_ifft_filename].objType==PPLOBJ_STR) { const int NcolRequired=Ndims+2; int status=0, j; ppldata_fromCmd(c, &data, pl, in, 0, filenameOut, dataSpool, PARSE_TABLE_ifft_, 0, NcolRequired, 0, min, minSet, max, maxSet, unit, 0, &status, c->errStat.errBuff, &errCount, iterDepth); // Exit on error if ((status)||(data==NULL)) { TBADD2(ERR_GENERIC,0); ppl_memAlloc_AscendOutOfContext(contextLocalVec); return; } // Check that the firstEntries above have the same units as any supplied ranges for (j=0; jfirstEntries+j)) { sprintf(c->errStat.errBuff, "The minimum and maximum limits specified in range %d in the fit command have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", j+1, ppl_printUnit(c,unit+j,NULL,NULL,0,1,0), ppl_printUnit(c,data->firstEntries+j,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); return; } } // Read unit of f(x) in final two columns of data table (real and imaginary components of f(x) firstEntry = data->firstEntries[Ndims]; firstEntry.real=1.0; firstEntry.imag=0.0; firstEntry.flagComplex=0; if (!ppl_unitsDimEqual(&data->firstEntries[Ndims], &data->firstEntries[Ndims+1])) { sprintf(c->errStat.errBuff, "Data in columns %d and %d of the data table supplied to the fft command have conflicting units of <%s> and <%s> respectively. These represent the real and imaginary components of an input sample, and must have the same units.", Ndims+1, Ndims+2, ppl_printUnit(c,&data->firstEntries[Ndims],NULL,NULL,0,1,0), ppl_printUnit(c,&data->firstEntries[Ndims+1],NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); return; } // Check that we have at least two datapoints if (data->Nrows < 2) { sprintf(c->errStat.errBuff, "FFT construction is only possible on data sets with members at at least two values of x."); TBADD2(ERR_NUMERICAL,0); return; } // Allocate workspace in which to do FFT datagrid = (fftw_complex *)fftw_malloc(Nsamples * sizeof(fftw_complex)); if (datagrid == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } // Loop through data table blk = data->first; j=0; for (i=0; iblockPosition)) { sprintf(c->errStat.errBuff, "Premature end to data table supplied to the fft command. To perform a "); k=strlen(c->errStat.errBuff); for (l=0;lerrStat.errBuff+k, "%dx", Nsteps[l]); k+=strlen(c->errStat.errBuff+k); } k-=(Ndims>0); sprintf(c->errStat.errBuff+k, " Fourier transform, need a grid of %d samples. Only received %ld samples.", Nsamples, i); TBADD2(ERR_FILE,0); return; } // Work out what position we're expecting this data point to represent for (k=i, l=Ndims-1; l>=0; l--) { Npos[l] = (k % Nsteps[l]); pos[l] = min[l]+step[l]*Npos[l]; k /= Nsteps[l]; } // Check that first Ndims columns indeed represent this point for (k=0; kdata_real[k + (Ndims+2)*j] , pos[k])) { int m; sprintf(c->errStat.errBuff, "Data supplied to fft command must be on a regular rectangular grid and in row-major ordering. Row %ld should represent a data point at position (", i+1); m=strlen(c->errStat.errBuff); for (l=0; lerrStat.errBuff+m,"%s,",ppl_unitsNumericDisplay(c,&x,0,1,-1)); m+=strlen(c->errStat.errBuff+m); } m-=(Ndims>0); sprintf(c->errStat.errBuff+m, "). In fact, it contained a data point at position ("); m+=strlen(c->errStat.errBuff+m); for (l=0; ldata_real[l + (Ndims+2)*j]; sprintf(c->errStat.errBuff+m,"%s,",ppl_unitsNumericDisplay(c,&x,0,1,-1)); m+=strlen(c->errStat.errBuff+m); } m-=(Ndims>0); sprintf(c->errStat.errBuff+m, ")."); j=strlen(c->errStat.errBuff); TBADD2(ERR_NUMERICAL,0); return; } { pplObj x; x.refCount=1; pplObjNum(&x,0,0,0); x.real = blk->data_real[(Ndims+0) + (Ndims+2)*j]; x.imag = blk->data_real[(Ndims+1) + (Ndims+2)*j]; if (x.imag==0) { x.flagComplex=0; x.imag=0.0; } else { x.flagComplex=1; } (*WindowType)(&x, Ndims, Npos, Nsteps); // Apply window function to data #ifdef HAVE_FFTW3 datagrid[i][0] = x.real; datagrid[i][1] = x.imag; #else datagrid[i].re = x.real; datagrid[i].im = x.imag; #endif } j++; if (j==blk->blockPosition) { j=0; blk=blk->next; } } } else // Fetch data from a function { int i, fnlen; int pos = PARSE_ifft_fnnames; char *scratchpad = (char *)ppl_memAlloc(LSTR_LENGTH); // Allocate workspace in which to do FFT datagrid = (fftw_complex *)fftw_malloc(Nsamples * sizeof(fftw_complex)); if (datagrid == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); return; } // Print function name fnlen=0; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (fnlen!=0) scratchpad[fnlen++]='.'; sprintf(scratchpad+fnlen,"%s",(char *)stk[pos+PARSE_ifft_fnname_fnnames].auxil); fnlen+=strlen(scratchpad+fnlen); } scratchpad[fnlen++]='('; for (i=0; istackPtr; int j = fnlen; int k = i, l, explen1, explen2, errPos=-1, errType=-1, lastOpAssign; int Npos[USING_ITEMS_MAX]; double pos[USING_ITEMS_MAX]; pplExpr *e; pplObj *out; for (l=Ndims-1; l>=0; l--) { Npos[l] = (k % Nsteps[l]); pos[l] = min[l]+step[l]*Npos[l]; k /= Nsteps[l]; } for (l=0; l0),")"); explen1 = explen2 = j-(Ndims>0)+1; ppl_error_setstreaminfo(&c->errcontext, 1, "fitting expression"); ppl_expCompile(c,pl->srcLineN,pl->srcId,pl->srcFname,scratchpad,&explen2,1,1,1,&e,&errPos,&errType,c->errStat.errBuff); if (c->errStat.status || (errPos>=0)) { fftw_free(datagrid); return; } if (explen2errStat.errBuff, "Unexpected trailing matter at the end of expression."); pplExpr_free(e); TBADD2(ERR_SYNTAX,0); return; } out = ppl_expEval(c, e, &lastOpAssign, 1, 1); pplExpr_free(e); if (c->errStat.status) { fftw_free(datagrid); return; } if (out->objType!=PPLOBJ_NUM) { fftw_free(datagrid); sprintf(c->errStat.errBuff, "The supplied function to fit produces a value which is not a number but has type <%s>.", pplObjTypeNames[out->objType]); TBADD2(ERR_TYPE,0); STACK_CLEAN; return; } if ((!gsl_finite(out->real))||(!gsl_finite(out->imag))) { int j=0; sprintf(c->errStat.errBuff+j, "Could not evaluate input function at position "); j+=strlen(c->errStat.errBuff+j); strncpy(c->errStat.errBuff+j, scratchpad, fnlen); j+=fnlen; for (l=0; lerrStat.errBuff+j,"%s,",ppl_unitsNumericDisplay(c,&x,0,1,-1)); j+=strlen(c->errStat.errBuff+j); } sprintf(c->errStat.errBuff+j, ")"); TBADD2(ERR_NUMERICAL,0); STACK_CLEAN; return; } if (i==0) { firstEntry=*out; firstEntry.real=1.0; firstEntry.imag=0.0; firstEntry.flagComplex=0; } else if (!ppl_unitsDimEqual(out, &firstEntry)) { sprintf(c->errStat.errBuff, "The supplied function to FFT does not produce values with consistent units; has produced values with units of <%s> and of <%s>.", ppl_printUnit(c,&firstEntry,NULL,NULL,0,1,0), ppl_printUnit(c,out,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,0); STACK_CLEAN; return; } (*WindowType)(out, Ndims, Npos, Nsteps); // Apply window function to data #ifdef HAVE_FFTW3 datagrid[i][0] = out->real; datagrid[i][1] = out->imag; #else datagrid[i].re = out->real; datagrid[i].im = out->imag; #endif STACK_CLEAN; } } // We're finished... can now free DataTable ppl_memAlloc_AscendOutOfContext(contextLocalVec); // FFT data #ifdef HAVE_FFTW3 fftwplan = fftw_plan_dft(Ndims, Nsteps, datagrid, datagrid, inverse ? FFTW_BACKWARD : FFTW_FORWARD, FFTW_ESTIMATE); // FFTW 3.x fftw_execute(fftwplan); fftw_destroy_plan(fftwplan); #else fftwplan = fftwnd_create_plan(Ndims, Nsteps, inverse ? FFTW_BACKWARD : FFTW_FORWARD, FFTW_ESTIMATE); // FFTW 2.x fftwnd_one(fftwplan, datagrid, datagrid); fftwnd_destroy_plan(fftwplan); #endif // Make FFTDescriptor data structure output = (FFTDescriptor *)malloc(sizeof(FFTDescriptor)); if (output == NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD2(ERR_MEMORY,0); fftw_free(datagrid); return; } output->Ndims = Ndims; for (i=0; iXSize[i] = Nsteps[i]; } for (i=0; irange[i],0,max[i]-min[i],0); output->range[i].refCount=1; ppl_unitsDimCpy(&output->range[i],&unit[i]); } for (i=0; iinvRange[i],0,0,0); ppl_unitsDimInverse(&output->invRange[i], &output->range[i]); } output->datagrid = datagrid; // Apply normalisation to data and phase-shift it t put zero in the right place { int Npos[USING_ITEMS_MAX]; double norm = 1.0; for (i=0; irange[i].real / Nsteps[i]; for (i=0; i=0; l--) { pos = (k % Nsteps[l]); k /= Nsteps[l]; angle = (inverse?-1:1)*2*M_PI*pos*Npos[l]/Nsteps[l]; normR2 = normR * cos(angle) - normI * sin(angle); normI2 = normR * sin(angle) + normI * cos(angle); normR = normR2; normI = normI2; } #ifdef HAVE_FFTW3 datagrid[i][0] = datagrid[i][0] * normR - datagrid[i][1] * normI; datagrid[i][1] = datagrid[i][0] * normI + datagrid[i][1] * normR; #else datagrid[i].re = datagrid[i].re * normR - datagrid[i].im * normI; datagrid[i].im = datagrid[i].re * normI + datagrid[i].im * normR; #endif } } // Make output unit { int status=0, et=0; output->outputUnit = firstEntry; // Output of an FFT has units of fn being FFTed, multiplied by the units of all of the arguments being FFTed for (i=0; ioutputUnit, &output->range[i], &output->outputUnit, &status, &et, c->errStat.errBuff); if (status>=0) break; } if (status) { TBADD2(ERR_INTERNAL,0); fftw_free(datagrid); free(output); return; } output->outputUnit.real = output->outputUnit.imag = 0.0; output->outputUnit.flagComplex = 0; // Output unit has zero magnitude } // Make a new function descriptor funcPtr = (pplFunc *)malloc(sizeof(pplFunc)); if (funcPtr == NULL) { sprintf(c->errStat.errBuff, "Out of memory whilst adding FFT object to function dictionary."); TBADD2(ERR_MEMORY,0); return; } funcPtr->functionType = PPL_FUNC_FFT; funcPtr->refCount = 1; funcPtr->minArgs = Ndims; funcPtr->maxArgs = Ndims; funcPtr->notNan = 1; funcPtr->numOnly = 1; funcPtr->realOnly = 0; funcPtr->dimlessOnly = 0; funcPtr->needSelfThis = 0; funcPtr->functionPtr = (void *)output; funcPtr->argList = NULL; funcPtr->min = funcPtr->max = NULL; funcPtr->minActive = funcPtr->maxActive = NULL; funcPtr->next = NULL; funcPtr->description = funcPtr->LaTeX = funcPtr->descriptionShort = NULL; // Supersede any previous function descriptor { int om, rc; pplObj val; pplObj *obj=NULL; ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &obj, PARSE_ifft_varnames, PARSE_ifft_varname_varnames); if ((c->errStat.status) || (obj==NULL)) return; if (obj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD2(ERR_NAMESPACE,0); return; } om = obj->amMalloced; rc = obj->refCount; obj->amMalloced = 0; obj->refCount = 1; ppl_garbageObject(obj); val.refCount=1; pplObjFunc(&val,0,1,funcPtr); pplObjCpy(obj, &val, 0, om, 1); obj->refCount = rc; } // Free copies of data vectors defined within our local context ppl_memAlloc_AscendOutOfContext(contextDataTab); return; } // Function which is called whenever an FFT function is evaluated, to extract value out of data grid void ppl_fft_evaluate(ppl_context *c, char *FuncName, FFTDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout) { int i, j; double tempDbl; *out = desc->outputUnit; // Issue user with a warning if complex arithmetic is not enabled if (c->set->term_current.ComplexNumbers != SW_ONOFF_ON) ppl_warning(&c->errcontext, ERR_NUMERICAL, "Attempt to evaluate a Fourier transform function whilst complex arithmetic is disabled. Fourier transforms are almost invariably complex and so this is unlikely to work."); // Check dimensions of input arguments and ensure that they are all real for (i=0; iNdims; i++) { if (!ppl_unitsDimEqual(in+i, &desc->invRange[i])) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errout, "The %s(x) function expects argument %d to have dimensions of <%s>, but has instead received an argument with dimensions of <%s>.", FuncName, i+1, ppl_printUnit(c, &desc->invRange[i], NULL, NULL, 0, 1, 0), ppl_printUnit(c, in+i, NULL, NULL, 1, 1, 0)); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } *status=1; return; } if ((in+i)->flagComplex) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(errout, "The %s(x) function expects argument %d to be real, but the supplied argument has an imaginary component.", FuncName, i+1); } else { pplObjNum(out,0,0,0); out->real = GSL_NAN; out->imag = 0; } *status=1; return; } } // Work out closest datapoint in FFT datagrid to the one we want j=0; for (i=0; iNdims; i++) { tempDbl = floor((in+i)->real * desc->range[i].real + 0.5); if ((tempDbl >= 0.0) && (tempDbl <= desc->XSize[i]/2)) { } // Positive frequencies stored in lower half of array else if ((tempDbl < 0.0) && (tempDbl >=-desc->XSize[i]/2)) { tempDbl += desc->XSize[i]; } // Negative frequencies stored in upper half of array else { return; } // Query out of range; return zero with appropriate output unit j *= desc->XSize[i]; j += (int)tempDbl; } // Write output value to out #ifdef HAVE_FFTW3 out->real = desc->datagrid[j][0]; if (desc->datagrid[j][1] == 0.0) { out->flagComplex = 0; out->imag = 0.0; } else { out->flagComplex = 1; out->imag = desc->datagrid[j][1]; } #else out->real = desc->datagrid[j].re; if (desc->datagrid[j].im == 0.0) { out->flagComplex = 0; out->imag = 0.0; } else { out->flagComplex = 1; out->imag = desc->datagrid[j].im; } #endif return; } pyxplot-0.9.2/src/commands/flowctrl.c0000664000175000017500000010043412026340554016216 0ustar dcf21dcf21// flowctrl.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: flowctrl.c 1307 2012-09-14 18:45:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _FLOWCTRL_C 1 #include #include #include #include #include #include #include #include #include "commands/flowctrl.h" #include "coreUtils/errorReport.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjFunc_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "datafile.h" #include "pplConstants.h" #define TBADD(et,cont) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,0,pl->linetxt,cont) #define TBADD2(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") #define STACK_POP \ { \ c->stackPtr--; \ ppl_garbageObject(&c->stack[c->stackPtr]); \ if (c->stack[c->stackPtr].refCount != 0) { strcpy(c->errStat.errBuff,"Stack forward reference detected."); TBADD(ERR_INTERNAL,0); return; } \ } void ppl_directive_break(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int named = (stk[PARSE_break_loopname].objType == PPLOBJ_STR); char *name = (char *)stk[PARSE_break_loopname].auxil; if (named) { int i; for (i=iterDepth; i>=0; i--) if ((c->shellLoopName[i]!=NULL)&&(strcmp(c->shellLoopName[i],name)==0)) break; if (i<0) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Not inside any loop with the name '%s'.", name); TBADD2(ERR_SYNTAX, in->stkCharPos[PARSE_break_loopname]); return; } c->shellBreakLevel = i; } else { if (!c->shellBreakable) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "The break statement can only be placed inside a loop structure."); TBADD2(ERR_SYNTAX, 0); return; } c->shellBreakLevel = -1; } c->shellBroken = 1; return; } void ppl_directive_continue(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int named = (stk[PARSE_continue_loopname].objType == PPLOBJ_STR); char *name = (char *)stk[PARSE_continue_loopname].auxil; if (named) { int i; for (i=iterDepth; i>=0; i--) if ((c->shellLoopName[i]!=NULL)&&(strcmp(c->shellLoopName[i],name)==0)) break; if (i<0) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Not inside any loop with the name '%s'.", name); TBADD2(ERR_SYNTAX, in->stkCharPos[PARSE_continue_loopname]); return; } c->shellBreakLevel = i; } else { if (!c->shellBreakable) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "The continue statement can only be placed inside a loop structure."); TBADD2(ERR_SYNTAX, 0); return; } c->shellBreakLevel = -1; } c->shellContinued = 1; return; } void ppl_directive_return(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; pplObj *retval = &stk[PARSE_return_return_value]; int gotval = (retval->objType != PPLOBJ_ZOM); if (!c->shellReturnable) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "The return statement can only be placed inside subroutines."); TBADD2(ERR_SYNTAX, 0); return; } c->shellBreakLevel = -1; c->shellReturned = 1; if (gotval) pplObjCpy(&c->shellReturnVal, retval, 0, 0, 1); else pplObjNum(&c->shellReturnVal, 0, 0, 0); return; } void ppl_directive_do(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { int criterion = 1; pplObj *stk = in->stk; parserLine *plc = (parserLine *)stk[PARSE_do_code ].auxil; pplExpr *cond = (pplExpr *)stk[PARSE_do_condition].auxil; char *name = (char *)stk[PARSE_do_loopname].auxil; int named= (stk[PARSE_do_loopname].objType == PPLOBJ_STR); ppl_context *context = c; // Needed for CAST_TO_BOOL int shellBreakableOld = c->shellBreakable; const int stkLevelOld = c->stackPtr; if (named) c->shellLoopName[iterDepth] = name; else c->shellLoopName[iterDepth] = NULL; c->shellBreakable = 1; do { int lastOpAssign, dollarAllowed=1; pplObj *val; ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"do loop"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; val = ppl_expEval(context, cond, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"do loop stopping criterion"); goto cleanup; } CAST_TO_BOOL(val); criterion = (val->real != 0); while (c->stackPtr>stkLevelOld) { STACK_POP; } } while (criterion && !cancellationFlag); cleanup: if ((c->shellBroken)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellBroken=0; c->shellBreakLevel=0; } c->shellLoopName[iterDepth] = NULL; c->shellBreakable = shellBreakableOld; return; } void ppl_directive_for(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int BASICstyle= (stk[PARSE_for_var_name].objType == PPLOBJ_STR); char *varname = (char *)stk[PARSE_for_var_name].auxil; pplObj *beginVal = &stk[PARSE_for_start_value]; pplObj *endVal = &stk[PARSE_for_final_value]; pplObj *stepVal = &stk[PARSE_for_step_size], stepTmp; int stepGot = (stk[PARSE_for_step_size].objType == PPLOBJ_NUM); parserLine *plc = (parserLine *)stk[PARSE_for_code ].auxil; pplExpr *begin = (pplExpr *)stk[PARSE_for_begin ].auxil; int beginGot = (stk[PARSE_for_begin ].objType == PPLOBJ_EXP); pplExpr *cond = (pplExpr *)stk[PARSE_for_criterion ].auxil; int condGot = (stk[PARSE_for_criterion].objType == PPLOBJ_EXP); pplExpr *end = (pplExpr *)stk[PARSE_for_iterate ].auxil; int endGot = (stk[PARSE_for_iterate ].objType == PPLOBJ_EXP); char *name = (char *)stk[PARSE_for_loopname].auxil; int named = (stk[PARSE_for_loopname].objType == PPLOBJ_STR); ppl_context *context = c; // Needed for CAST_TO_BOOL int shellBreakableOld = c->shellBreakable; const int stkLevelOld = c->stackPtr; if (named) c->shellLoopName[iterDepth] = name; else c->shellLoopName[iterDepth] = NULL; c->shellBreakable = 1; if (BASICstyle) { double iter; int forwards = stepGot ? (stepVal->real>0) : (endVal->real > beginVal->real); if (!stepGot) // If no step is specified, make it equal to one SI unit { memcpy(&stepTmp, beginVal, sizeof(pplObj)); stepTmp.refCount=1; stepTmp.amMalloced=0; stepTmp.real=forwards?1:-1; stepVal = &stepTmp; } if (!ppl_unitsDimEqual(beginVal , endVal )) { sprintf(c->errStat.errBuff,"The start and end values of this for loop are dimensionally incompatible: the start value has dimensions of <%s> but the end value has dimensions of <%s>.",ppl_printUnit(c,beginVal,NULL,NULL,0,1,0),ppl_printUnit(c,endVal,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,in->stkCharPos[PARSE_for_final_value]); goto cleanup; } if (!ppl_unitsDimEqual(beginVal , stepVal)) { sprintf(c->errStat.errBuff,"The start value and step size of this for loop are dimensionally incompatible: the start value has dimensions of <%s> but the step size has dimensions of <%s>.",ppl_printUnit(c,beginVal,NULL,NULL,0,1,0),ppl_printUnit(c,stepVal,NULL,NULL,1,1,0)); TBADD2(ERR_NUMERICAL,in->stkCharPos[PARSE_for_start_value]); goto cleanup; } if ( (stepVal->real==0) || ((endVal->real!=beginVal->real)&&((stepVal->real > 0) != forwards)) ) { strcpy(c->errStat.errBuff,"The number of iterations in this for loop is infinite."); TBADD2(ERR_NUMERICAL,in->stkCharPos[PARSE_for_start_value]); goto cleanup; } for (iter=beginVal->real; (forwards ? (iter<=endVal->real) : (iter>=endVal->real)) && !cancellationFlag ; iter+=stepVal->real) { pplObj *varObj, vartmp; ppl_contextGetVarPointer(c, varname, &varObj, &vartmp); pplObjNum(varObj, varObj->amMalloced, iter, 0); ppl_unitsDimCpy(varObj, beginVal); ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); vartmp.amMalloced=0; ppl_garbageObject(&vartmp); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"for loop"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } } else { if (beginGot) { int lastOpAssign, dollarAllowed=1; ppl_expEval(context, begin, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"for loop initialisation expression"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } } while (1) { if (condGot) { int lastOpAssign, dollarAllowed=1, criterion=1; pplObj *val; val = ppl_expEval(context, cond, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"for loop stopping criterion"); goto cleanup; } CAST_TO_BOOL(val); criterion = (val->real != 0); while (c->stackPtr>stkLevelOld) { STACK_POP; } if (!criterion || cancellationFlag) break; } ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"for loop"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; if (endGot) { int lastOpAssign, dollarAllowed=1; ppl_expEval(context, end, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"for loop stopping criterion"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } } } } cleanup: if ((c->shellBroken)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellBroken=0; c->shellBreakLevel=0; } c->shellLoopName[iterDepth] = NULL; c->shellBreakable = shellBreakableOld; return; } void ppl_directive_foreach(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; pplObj *iter = &stk[PARSE_foreach_item_list]; parserLine *plc = (parserLine *)stk[PARSE_foreach_code].auxil; char *varname = (char *)stk[PARSE_foreach_var_name].auxil; char *name = (char *)stk[PARSE_foreach_loopname].auxil; int named = (stk[PARSE_foreach_loopname].objType == PPLOBJ_STR); int shellBreakableOld = c->shellBreakable; const int stkLevelOld = c->stackPtr; if (named) c->shellLoopName[iterDepth] = name; else c->shellLoopName[iterDepth] = NULL; c->shellBreakable = 1; #define FOREACH_STOP ( c->errStat.status || c->shellBroken || c->shellContinued || c->shellReturned || c->shellExiting || cancellationFlag ) if (iter->objType == PPLOBJ_STR) // Iterate over string: treat this as a filename to glob { int i,j; wordexp_t w; glob_t g; char *raw=(char *)iter->auxil, fName[FNAME_LENGTH]; { int j,k; for (j=k=0; ((raw[j]!='\0')&&(kamMalloced, 0, g.gl_pathv[j]); ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); ppl_contextRestoreVarPointer(c, varname, &vartmp); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"foreach loop"); } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } } globfree(&g); } wordfree(&w); } else if (iter->objType == PPLOBJ_VEC) // Iterate over vector { gsl_vector *vin = ((pplVector *)iter->auxil)->v; const int vinl = vin->size; int i; for (i=0; iamMalloced, gsl_vector_get(vin, i), 0); ppl_unitsDimCpy(varObj, iter); ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); ppl_contextRestoreVarPointer(c, varname, &vartmp); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"foreach loop"); } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } } else if (iter->objType == PPLOBJ_LIST) // Iterate over list { list *lin = (list *)iter->auxil; listIterator *li = ppl_listIterateInit(lin); pplObj *obj; while (((obj=(pplObj*)ppl_listIterate(&li))!=NULL) && !FOREACH_STOP) { pplObj *varObj, vartmp; ppl_contextGetVarPointer(c, varname, &varObj, &vartmp); pplObjCpy(varObj, obj, 0, varObj->amMalloced, 1); ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); ppl_contextRestoreVarPointer(c, varname, &vartmp); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"foreach loop"); } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } } else if ((iter->objType == PPLOBJ_DICT) || (iter->objType == PPLOBJ_MOD) || (iter->objType == PPLOBJ_USER)) // Iterate over dictionary { dict *din = (dict *)iter->auxil; dictIterator *di = ppl_dictIterateInit(din); pplObj *obj; char *key, *cpy; while (((obj=(pplObj*)ppl_dictIterate(&di,&key))!=NULL) && !FOREACH_STOP) { pplObj *varObj, vartmp; ppl_contextGetVarPointer(c, varname, &varObj, &vartmp); cpy = (char *)malloc(strlen(key)+1); if (cpy==NULL) { ppl_contextRestoreVarPointer(c, varname, &vartmp); break; } strcpy(cpy, key); pplObjStr(varObj, varObj->amMalloced, 1, cpy); ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); ppl_contextRestoreVarPointer(c, varname, &vartmp); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"foreach loop"); } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } } else { sprintf(c->errStat.errBuff,"Cannot iterate over an object of type <%s>.",pplObjTypeNames[iter->objType]); TBADD2(ERR_TYPE,in->stkCharPos[PARSE_foreach_item_list]); goto cleanup; } cleanup: if ((c->shellBroken)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellBroken=0; c->shellBreakLevel=0; } c->shellLoopName[iterDepth] = NULL; c->shellBreakable = shellBreakableOld; return; } void ppl_directive_fordata(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; parserLine *plc = (parserLine *)stk[PARSE_foreachdatum_code].auxil; int Nvars = 0, i, status=0, errCount=5; char *varname[USING_ITEMS_MAX]; int pos = PARSE_foreachdatum_variables; char *name = (char *)stk[PARSE_foreachdatum_loopname].auxil; int named = (stk[PARSE_foreachdatum_loopname].objType == PPLOBJ_STR); int shellBreakableOld = c->shellBreakable; pplObj *varObj[USING_ITEMS_MAX], vartmp[USING_ITEMS_MAX]; pplObj unit [USING_ITEMS_MAX]; int minSet[USING_ITEMS_MAX], maxSet[USING_ITEMS_MAX]; double min [USING_ITEMS_MAX], max [USING_ITEMS_MAX]; dataTable *data=NULL; dataBlock *blk =NULL; parserLine *spool=NULL, **dataSpool = &spool; if (named) c->shellLoopName[iterDepth] = name; else c->shellLoopName[iterDepth] = NULL; c->shellBreakable = 1; // Read variable names while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; if (Nvars>=USING_ITEMS_MAX) { sprintf(c->errStat.errBuff,"Too many variable names; a maximum of %d may be specified.",USING_ITEMS_MAX); TBADD2(ERR_SYNTAX,in->stkCharPos[pos+PARSE_foreachdatum_variable_variables]); goto cleanup; } varname[Nvars] = (char *)stk[pos+PARSE_foreachdatum_variable_variables].auxil; Nvars++; } // Fetch ordinate ranges { int i,pos=PARSE_foreachdatum_0range_list,nr=0; const int o1 = PARSE_foreachdatum_min_0range_list; const int o2 = PARSE_foreachdatum_max_0range_list; for (i=0; i=Nvars) { sprintf(c->errStat.errBuff,"Too many ranges specified; there are only %d loop variables.", Nvars); TBADD2(ERR_SYNTAX,0); goto cleanup; } if ((stk[pos+o1].objType==PPLOBJ_NUM)||(stk[pos+o1].objType==PPLOBJ_DATE)||(stk[pos+o1].objType==PPLOBJ_BOOL)) { unit[nr]=stk[pos+o1]; min[nr]=unit[nr].real; minSet[nr]=1; } if ((stk[pos+o2].objType==PPLOBJ_NUM)||(stk[pos+o2].objType==PPLOBJ_DATE)||(stk[pos+o2].objType==PPLOBJ_BOOL)) { if ((minSet[nr])&&(unit[nr].objType!=stk[pos+o2].objType)) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d (%s) have conflicting types of <%s> and <%s>.", nr+1, varname[nr], pplObjTypeNames[unit[nr].objType], pplObjTypeNames[stk[pos+o2].objType]); TBADD2(ERR_TYPE,in->stkCharPos[pos+PARSE_foreachdatum_min_0range_list]); goto cleanup; } if ((minSet[nr])&&(!ppl_unitsDimEqual(&unit[nr],&stk[pos+o2]))) { sprintf(c->errStat.errBuff,"Minimum and maximum limits specified for variable %d (%s) have conflicting physical units of <%s> and <%s>.", nr+1, varname[nr], ppl_printUnit(c,&unit[nr],NULL,NULL,0,0,0), ppl_printUnit(c,&stk[pos+o2],NULL,NULL,1,0,0)); TBADD2(ERR_UNIT,in->stkCharPos[pos+PARSE_foreachdatum_min_0range_list]); goto cleanup; } unit[nr]=stk[pos+o2]; max[nr]=unit[nr].real; maxSet[nr]=1; } nr++; } } // Fetch data ppldata_fromCmd(c, &data, pl, in, 0, NULL, dataSpool, PARSE_TABLE_foreachdatum_, 0, Nvars, Nvars, min, minSet, max, maxSet, unit, 0, &status, c->errcontext.tempErrStr, &errCount, iterDepth); if (status || cancellationFlag) { ppl_error(&c->errcontext,ERR_GENERIC,-1,-1,NULL); goto cleanup; } // Loop over data table blk = data->first; while ((blk!=NULL) && !FOREACH_STOP) { int j; for (j=0; ((jblockPosition) && !FOREACH_STOP); j++) { const int stkLevelOld = c->stackPtr; int k,inRange=1; for (k=0; ((kdata_obj[k+j*Nvars]; const int numeric = obj->objType==unit[k].objType; int om, rc; // Fetch variable pointer ppl_contextGetVarPointer(c, varname[k], &varObj[k], &vartmp[k]); // Check units of ranges if ((minSet[k]||maxSet[k])&&inRange) { if (!numeric) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(c->errcontext.tempErrStr,"Minimum and maximum limits are specified for variable %d (%s), but it computes to a non-numeric quantity of type <%s>.", k+1, varname[k], pplObjTypeNames[obj->objType]); ppl_warning(&c->errcontext,ERR_TYPE,NULL); } inRange=0; } else if (!ppl_unitsDimEqual(&unit[k],obj)) { if (c->set->term_current.ExplicitErrors == SW_ONOFF_ON) { sprintf(c->errcontext.tempErrStr,"The minimum and maximum limits specified in the 'foreach datum ...' command for variable %d (%s) have conflicting physical dimensions with the data returned from the data file. The limits have units of <%s>, whilst the data have units of <%s>.", k+1, varname[k], ppl_printUnit(c,&unit[k],NULL,NULL,0,0,0), ppl_printUnit(c,obj,NULL,NULL,1,0,0)); ppl_warning(&c->errcontext,ERR_UNIT,NULL); } inRange=0; } if (minSet[k]&&(obj->realreal>max[k])) inRange=0; } if ((obj->objType==PPLOBJ_STR) && (obj->auxil==NULL)) { inRange=0; } // NULL strings are bad om=varObj[k]->amMalloced; rc=varObj[k]->refCount; varObj[k]->amMalloced=0; ppl_garbageObject(varObj[k]); pplObjCpy(varObj[k],obj,0,0,1); varObj[k]->amMalloced=om; varObj[k]->refCount =rc;; } if (inRange) { ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); } // Restore variable pointers for (i=0; ierrStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"foreach datum statement"); return; } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } blk=blk->next; if (status) break; } // Free data tables blk = data->first; while (blk != NULL) { int j; for (j=0; jblockPosition; j++) { int k; for (k=0; kdata_obj[k+j*Nvars]); } blk=blk->next; } cleanup: if ((c->shellBroken)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellBroken=0; c->shellBreakLevel=0; } c->shellLoopName[iterDepth] = NULL; c->shellBreakable = shellBreakableOld; return; } void ppl_directive_if(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; parserLine *pl_if = (parserLine *)stk[PARSE_if_code ].auxil; parserLine *pl_else = (parserLine *)stk[PARSE_if_code_else].auxil; int gotelse = (stk[PARSE_if_code_else].objType==PPLOBJ_BYT); pplExpr *cond = (pplExpr *)stk[PARSE_if_criterion].auxil; ppl_context *context = c; // Needed for CAST_TO_BOOL pplObj *val; int lastOpAssign, dollarAllowed=1, criterion; int pos = PARSE_if_0elifs; const int stkLevelOld = c->stackPtr; // Test criterion val = ppl_expEval(context, cond, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"if criterion"); return; } CAST_TO_BOOL(val); criterion = (val->real != 0); while (c->stackPtr>stkLevelOld) { STACK_POP; } if (criterion) { ppl_parserExecute(c, pl_if, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"if statement"); return; } while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } // loop over else ifs while (stk[pos].objType == PPLOBJ_NUM) { parserLine *pl_elif = NULL; pplExpr *cond_elif = NULL; pplObj *val; int lastOpAssign, dollarAllowed=1, criterion; pos = (int)round(stk[pos].real); pl_elif = (parserLine *)stk[pos+PARSE_if_code_elif_0elifs].auxil; cond_elif = (pplExpr *)stk[pos+PARSE_if_criterion_0elifs].auxil; if (pos<=0) break; val = ppl_expEval(context, cond_elif, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"else if criterion"); return; } CAST_TO_BOOL(val); criterion = (val->real != 0); while (c->stackPtr>stkLevelOld) { STACK_POP; } if (criterion) { ppl_parserExecute(c, pl_elif, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"if statement"); return; } while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } } // else if (gotelse) { ppl_parserExecute(c, pl_else, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"if statement"); return; } while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } return; } void ppl_directive_subrt(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; parserLine *plsub = (parserLine *)stk[PARSE_subroutine_code ].auxil; int pos, nArgs=0, argListLen=0, i, om, rc; pplFunc *f = NULL; pplObj *tmpObj; // Count number of arguments pos = PARSE_subroutine_0argument_list; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { char *name; pos = (int)round(stk[pos].real); name = (char *)stk[pos+PARSE_subroutine_argument_name_0argument_list].auxil; nArgs++; argListLen+=strlen(name)+1; } if (nArgs > FUNC_MAXARGS) { sprintf(c->errStat.errBuff, "Too many arguments to function; the maximum allowed number is %d.", FUNC_MAXARGS); TBADD(ERR_OVERFLOW,0); return; } // Allocate function descriptor f = (pplFunc *)malloc(sizeof(pplFunc)); if (f==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY,0); return; } f->functionType = PPL_FUNC_SUBROUTINE; f->refCount = 1; f->minArgs = nArgs; f->maxArgs = nArgs; f->functionPtr = (void *)plsub; f->argList = (char *)malloc(argListLen); f->min = NULL; f->max = NULL; f->minActive = NULL; f->maxActive = NULL; f->numOnly = 0; f->notNan = 0; f->realOnly = 0; f->dimlessOnly = 0; f->next = NULL; f->LaTeX = NULL; f->description = NULL; f->descriptionShort = NULL; if (f->argList==NULL) { sprintf(c->errStat.errBuff, "Out of memory."); TBADD(ERR_MEMORY,0); goto fail; } // Put argument names into structure pos = PARSE_subroutine_0argument_list; i = 0; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { char *name; pos = (int)round(stk[pos].real); name = (char *)stk[pos+PARSE_subroutine_argument_name_0argument_list].auxil; strcpy(f->argList+i, name); i+= strlen(name)+1; } // Look up function or variable we are superseding ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &tmpObj, PARSE_subroutine_subroutine_names, PARSE_subroutine_subroutine_name_subroutine_names); if ((c->errStat.status) || (tmpObj==NULL)) goto fail; if (tmpObj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD(ERR_NAMESPACE,0); goto fail; } om = tmpObj->amMalloced; rc = tmpObj->refCount; tmpObj->amMalloced=0; tmpObj->refCount =1; ppl_garbageObject(tmpObj); pplObjFunc(tmpObj,om,1,f); tmpObj->refCount =rc; if (plsub!=NULL) __sync_add_and_fetch(&plsub->refCount,1); return; fail: if (f!=NULL) { if (f->argList != NULL) free(f->argList); free(f); } return; } void ppl_directive_while(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { int criterion = 1; pplObj *stk = in->stk; parserLine *plc = (parserLine *)stk[PARSE_while_code ].auxil; pplExpr *cond = (pplExpr *)stk[PARSE_while_criterion].auxil; char *name = (char *)stk[PARSE_while_loopname].auxil; int named= (stk[PARSE_while_loopname].objType == PPLOBJ_STR); ppl_context *context = c; // Needed for CAST_TO_BOOL int shellBreakableOld = c->shellBreakable; const int stkLevelOld = c->stackPtr; if (named) c->shellLoopName[iterDepth] = name; else c->shellLoopName[iterDepth] = NULL; c->shellBreakable = 1; while (!cancellationFlag) { int lastOpAssign, dollarAllowed=1; pplObj *val; val = ppl_expEval(context, cond, &lastOpAssign, dollarAllowed, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"while loop stopping criterion"); goto cleanup; } CAST_TO_BOOL(val); criterion = (val->real != 0); while (c->stackPtr>stkLevelOld) { STACK_POP; } if (!criterion) break; ppl_parserExecute(c, plc, NULL, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"while loop"); goto cleanup; } while (c->stackPtr>stkLevelOld) { STACK_POP; } if ((c->shellContinued)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellContinued=0; c->shellBreakLevel=0; continue; } if ((c->shellBroken)||(c->shellContinued)||(c->shellReturned)||(c->shellExiting)) break; } cleanup: if ((c->shellBroken)&&((c->shellBreakLevel==iterDepth)||(c->shellBreakLevel<0))) { c->shellBroken=0; c->shellBreakLevel=0; } c->shellLoopName[iterDepth] = NULL; c->shellBreakable = shellBreakableOld; return; } void ppl_directive_with(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; parserLine *pl2 = (parserLine *)stk[PARSE_with_code].auxil; pplObj *obj = &stk[PARSE_with_namespace]; dict *d; const int stkLevelOld = c->stackPtr; // Check that there's enough space on the stack if (c->ns_ptr > CONTEXT_DEPTH-2) { strcpy(c->errStat.errBuff,"Stack overflow."); TBADD(ERR_MEMORY,""); return; } // Check requested namespace if ((obj->objType!=PPLOBJ_MOD)&&(obj->objType!=PPLOBJ_USER)) { sprintf(c->errStat.errBuff,"Requested namespace is not a module; it has type <%s>.",pplObjTypeNames[obj->objType]); TBADD(ERR_TYPE,""); return; } d = (dict *)obj->auxil; // Enter a new namespace d->refCount++; c->namespaces[++c->ns_ptr] = d; ppl_parserExecute(c, pl2, NULL, interactive, iterDepth+1); // Leave namespace if ((--d->refCount)<1) ppl_dictFree(d); c->ns_ptr--; if (c->errStat.status) { strcpy(c->errStat.errBuff,""); TBADD(ERR_GENERIC,"with block"); return; } while (c->stackPtr>stkLevelOld) { STACK_POP; } return; } pyxplot-0.9.2/src/commands/core.c0000664000175000017500000004712312026340554015317 0ustar dcf21dcf21// core.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: core.c 1304 2012-09-10 21:33:11Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _CORE_C 1 #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_READLINE #include #endif #include #include "commands/core.h" #include "coreUtils/backup.h" #include "coreUtils/errorReport.h" #include "coreUtils/getPasswd.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "expressions/expEval.h" #include "expressions/traceback.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjPrint.h" #include "children.h" #include "input.h" #include "pplConstants.h" #define TBADD(et,pos) ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,et,pos,pl->linetxt,"") void ppl_directive_assert(ppl_context *c, parserLine *pl, parserOutput *in) { pplObj *stk = in->stk; int lt; char *txt, *version; pplObj *val; txt = (stk[PARSE_assert_message].objType==PPLOBJ_STR) ? (char *)stk[PARSE_assert_message].auxil : NULL; version = (stk[PARSE_assert_version].objType==PPLOBJ_STR) ? (char *)stk[PARSE_assert_version].auxil : NULL; val = &stk[PARSE_assert_expr]; lt = (stk[PARSE_assert_lt ].objType==PPLOBJ_STR); if (val->objType != PPLOBJ_ZOM) { ppl_context *context = c; CAST_TO_BOOL(val); if (txt==NULL) txt="Assertion was not true."; if (val->real<0.5) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "%s", txt); TBADD(ERR_ASSERT,in->stkCharPos[PARSE_assert_expr]); return; } } if (version != NULL) { int i=0,j=0,sgn,pass=0; char txtauto[64]; sprintf(txtauto, "This script requires a%s version of Pyxplot (%s %s)", (!lt)?" newer":"n older", (!lt)?">=":"<", version); #define VERSION_FAIL { snprintf(c->errStat.errBuff, LSTR_LENGTH, "%s", txt); TBADD(ERR_ASSERT,in->stkCharPos[PARSE_assert_version]); return; } #define VERSION_MALF { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Malformed version string."); TBADD(ERR_SYNTAX,in->stkCharPos[PARSE_assert_version]); return; } if (txt==NULL) txt=txtauto; sgn = (!lt)?1:-1; while ((version[i]>'\0')&&(version[i]<=' ')) i++; if (version[i]=='\0') return; for (j=0; ((version[i]>='0')&&(version[i]<='9')); i++) { j=10*j+(version[i]-'0'); if (j>1e6)j=1e6; } if ((sgn*VERSION_MAJ < sgn*j)&&(!pass)) VERSION_FAIL; if (sgn*VERSION_MAJ > sgn*j) pass=1; while ((version[i]>'\0')&&(version[i]<=' ')) i++; if (version[i]=='.') i++; else if (version[i]!='\0') { VERSION_MALF; } while ((version[i]>'\0')&&(version[i]<=' ')) i++; if ((version[i]=='\0')&&(sgn==-1)&&(!pass)) VERSION_FAIL; if (version[i]=='\0') return; for (j=0; ((version[i]>='0')&&(version[i]<='9')); i++) { j=10*j+(version[i]-'0'); if (j>1e6)j=1e6; } if ((sgn*VERSION_MIN < sgn*j)&&(!pass)) VERSION_FAIL; if (sgn*VERSION_MIN > sgn*j) pass=1; while ((version[i]>'\0')&&(version[i]<=' ')) i++; if (version[i]=='.') i++; else if (version[i]!='\0') { VERSION_MALF; } while ((version[i]>'\0')&&(version[i]<=' ')) i++; if ((version[i]=='\0')&&(sgn==-1)&&(!pass)) VERSION_FAIL; if (version[i]=='\0') return; for (j=0; ((version[i]>='0')&&(version[i]<='9')); i++) { j=10*j+(version[i]-'0'); if (j>1e6)j=1e6; } if ((sgn*VERSION_REV < sgn*j)&&(!pass)) VERSION_FAIL; if (sgn*VERSION_REV > sgn*j) pass=1; while ((version[i]>'\0')&&(version[i]<=' ')) i++; if (version[i]!='\0') { VERSION_MALF; } if ((version[i]=='\0')&&(sgn==-1)&&(!pass)) VERSION_FAIL; } return; } void ppl_directive_cd(ppl_context *c, parserLine *pl, parserOutput *in) { pplObj *stk = in->stk; int pos = PARSE_cd_path; wordexp_t wordExp; glob_t globData; while (stk[pos].objType == PPLOBJ_NUM) { char *raw, dirName[FNAME_LENGTH]; pos = (int)round(stk[pos].real); if (pos<=0) break; raw = (char *)stk[pos+PARSE_cd_directory_path].auxil; { int j,k; for (j=k=0; ((raw[j]!='\0')&&(kerrStat.errBuff, LSTR_LENGTH, "Could not enter directory '%s'.", dirName); TBADD(ERR_FILE,in->stkCharPos[pos+PARSE_cd_directory_path]); return; } if ((glob(wordExp.we_wordv[0], 0, NULL, &globData) != 0) || (globData.gl_pathc <= 0)) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Could not enter directory '%s'.", dirName); TBADD(ERR_FILE,in->stkCharPos[pos+PARSE_cd_directory_path]); wordfree(&wordExp); return; } wordfree(&wordExp); if (chdir(globData.gl_pathv[0]) < 0) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Could not change into directory '%s'.", globData.gl_pathv[0]); TBADD(ERR_FILE,in->stkCharPos[pos+PARSE_cd_directory_path]); globfree(&globData); break; } globfree(&globData); } if (getcwd( c->errcontext.session_default.cwd , FNAME_LENGTH ) == NULL) { ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Could not read current working directory."); } // Store cwd return; } void ppl_directive_exec(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; char *cmd = (char *)stk[PARSE_exec_command].auxil; parserLine *pl2 = NULL; parserStatus *ps2 = NULL; ppl_parserStatInit(&ps2,&pl2); if ( (ps2==NULL) || (c->inputLineBuffer == NULL) ) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); return; } ppl_error_setstreaminfo(&c->errcontext, -1, "executed statement"); ppl_processLine(c, ps2, cmd, interactive, iterDepth+1); if (c->errStat.status) { strcpy(c->errStat.errBuff, ""); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_GENERIC,0,pl->linetxt,"executed statement"); } if (c->inputLineAddBuffer != NULL) { ppl_warning(&c->errcontext,ERR_SYNTAX,"Line continuation character (\\) at the end of executed string, with no line following it."); free(c->inputLineAddBuffer); c->inputLineAddBuffer=NULL; } ppl_parserStatFree(&ps2); return; } void ppl_directive_global(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int pos; if (c->ns_ptr<2) { sprintf(c->errStat.errBuff,"Cannot declare global variables when not in a subroutine or module namespace."); TBADD(ERR_NAMESPACE,0); return; } pos = PARSE_global_var_names; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { int om, rc; char *varname; pplObj *obj; pos = (int)round(stk[pos].real); varname = (char *)stk[pos+PARSE_global_var_name_var_names].auxil; obj = (pplObj *)ppl_dictLookup(c->namespaces[c->ns_ptr] , varname); if ((obj==NULL)&&(!c->namespaces[c->ns_ptr]->immutable)) { pplObj out; pplObjZom(&out,1); out.refCount=1; // Create a temporary zombie for now ppl_dictAppendCpy(c->namespaces[c->ns_ptr] , varname , (void *)&out , sizeof(pplObj)); obj = (pplObj *)ppl_dictLookup(c->namespaces[c->ns_ptr] , varname); if (obj==NULL) { sprintf(c->errStat.errBuff,"Out of memory."); TBADD(ERR_MEMORY,0); return; } } if ((obj==NULL)||(c->namespaces[c->ns_ptr]->immutable)) { sprintf(c->errStat.errBuff,"Cannot modify variable in immutable namespace."); TBADD(ERR_NAMESPACE,in->stkCharPos[pos+PARSE_global_var_name_var_names]); return; } if (obj->objType==PPLOBJ_GLOB) return; om = obj->amMalloced; rc = obj->refCount; obj->amMalloced = 0; obj->refCount = 1; ppl_garbageObject(obj); pplObjGlobal(obj, om); obj->refCount = rc; } return; } void ppl_directive_history(ppl_context *c, parserLine *pl, parserOutput *in) { #ifdef HAVE_READLINE pplObj *stk = in->stk; int start=0,endpos,k; HIST_ENTRY **history_data; endpos = where_history(); history_data = history_list(); if (stk[PARSE_history_number_lines].objType == PPLOBJ_NUM) { start = endpos - (int)round(stk[PARSE_history_number_lines].real); if (start < 0) start=0; } for (k=start; kerrcontext,history_data[k]->line); return; #else snprintf(c->errStat.errBuff, LSTR_LENGTH, "The 'history' command is not available as the GNU readline library was not linked to when Pyxplot was installed."); TBADD(ERR_GENERIC,0); return; #endif } void ppl_directive_load(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { int i = 0; int j = 0; pplObj *stk = in->stk; char *raw = (char *)stk[PARSE_load_filename].auxil; char fn[FNAME_LENGTH]; wordexp_t wordExp; glob_t globData; { int j,k; for (j=k=0; ((raw[j]!='\0')&&(kerrStat.errBuff, LSTR_LENGTH, "Could not access file '%s'.", fn); TBADD(ERR_FILE,in->stkCharPos[PARSE_load_filename]); return; } for (j=0; (jerrStat.errBuff, LSTR_LENGTH, "Could not access file '%s'.", fn); TBADD(ERR_FILE,in->stkCharPos[PARSE_load_filename]); wordfree(&wordExp); return; } else { continue; } } for (i=0; (ierrStat.status) { strcpy(c->errStat.errBuff, ""); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_GENERIC,0,pl->linetxt,"executed script"); break; } } globfree(&globData); } wordfree(&wordExp); return; } void ppl_directive_local(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int pos; if (c->ns_ptr<2) { sprintf(c->errStat.errBuff,"Cannot declare global variables when not in a subroutine or module namespace."); TBADD(ERR_NAMESPACE,0); return; } pos = PARSE_local_var_names; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { char *varname; pplObj *obj; pos = (int)round(stk[pos].real); varname = (char *)stk[pos+PARSE_local_var_name_var_names].auxil; // Look up requested variable ppl_contextVarLookup(c, varname, &obj, 1); if ((obj==NULL)||(obj->objType!=PPLOBJ_GLOB)) { sprintf(c->errStat.errBuff,"Variable '%s' has not previously been declared global in this namespace. It is already a local variable.",varname); TBADD(ERR_NAMESPACE,in->stkCharPos[pos+PARSE_local_var_name_var_names]); return; } pplObjZom(obj,obj->amMalloced); } return; } void ppl_directive_print(ppl_context *c, parserLine *pl, parserOutput *in) { pplObj *stk = in->stk; int pos = PARSE_print_0print_list; int i = 0; int gotItems = 0; c->errcontext.tempErrStr[i] = '\0'; while (stk[pos].objType == PPLOBJ_NUM) { pos = (int)round(stk[pos].real); if (pos<=0) break; pplObjPrint(c,stk+pos+PARSE_print_expression_0print_list,NULL,c->errcontext.tempErrStr+i,LSTR_LENGTH-i,0,0); c->errcontext.tempErrStr[LSTR_LENGTH-1] = '\0'; i += strlen(c->errcontext.tempErrStr+i); gotItems=1; } ppl_report(&c->errcontext, NULL); // set ans if (gotItems) { pplObj *optr, dummyTemp; int am, rc; ppl_contextGetVarPointer(c, "ans", &optr, &dummyTemp); dummyTemp.amMalloced=0; ppl_garbageObject(&dummyTemp); am = optr->amMalloced; rc = optr->refCount; optr->amMalloced = 0; ppl_garbageObject(optr); pplObjCpy(optr,stk+pos+PARSE_print_expression_0print_list,0,0,1); optr->amMalloced = am; optr->refCount = rc; optr->self_lval = NULL; optr->self_this = NULL; } return; } void ppl_directive_save(ppl_context *c, parserLine *pl, parserOutput *in) { #ifdef HAVE_READLINE pplObj *stk = in->stk; int pos=PARSE_save_filename; int start=0,endpos,k; long x; char *outfname = ""; FILE *outfile = NULL; HIST_ENTRY **history_data; if (stk[pos].objType == PPLOBJ_STR) { outfname = (char *)stk[pos].auxil; ppl_createBackupIfRequired(c, outfname); outfile = fopen(outfname , "w"); } if (outfile == NULL) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "The save command could not open output file '%s' for writing.", outfname); TBADD(ERR_FILE,in->stkCharPos[pos]); return; } fprintf(outfile, "# Command script saved by Pyxplot %s\n# Timestamp: %s\n", VERSION, ppl_strStrip(ppl_friendlyTimestring(),c->errcontext.tempErrStr)); fprintf(outfile, "# User: %s\n\n", ppl_unixGetIRLName(&c->errcontext)); endpos = history_length; history_data = history_list(); x = endpos - c->historyNLinesWritten; if (x < history_base) x=history_base; start = (int)x; for (k=start; kline)); } fclose(outfile); return; #else snprintf(c->errStat.errBuff, LSTR_LENGTH, "The 'save' command is not available as the GNU readline library was not linked to when Pyxplot was installed."); TBADD(ERR_GENERIC,0); return; #endif } void ppl_directive_seterror(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplObj *o = &in->stk[PARSE_set_error_set_option]; char *tempstr = (o->objType==PPLOBJ_STR) ? (char *)in->stk[PARSE_set_error_set_option].auxil : NULL; if (tempstr != NULL) { if (!interactive) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Unrecognised set option '%s'.", tempstr); TBADD(ERR_SYNTAX,in->stkCharPos[PARSE_set_error_set_option]); } else { snprintf(c->errStat.errBuff, LSTR_LENGTH, ppltxt_set , tempstr); TBADD(ERR_SYNTAX,in->stkCharPos[PARSE_set_error_set_option]); } } else { if (!interactive) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "set command detected with no set option following it."); TBADD(ERR_SYNTAX,0); } else { snprintf(c->errStat.errBuff, LSTR_LENGTH, "%s", ppltxt_set_noword); TBADD(ERR_SYNTAX,0); } } return; } void ppl_directive_unseterror(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplObj *o = &in->stk[PARSE_set_error_set_option]; char *tempstr = (o->objType==PPLOBJ_STR) ? (char *)in->stk[PARSE_set_error_set_option].auxil : NULL; if (tempstr != NULL) { if (!interactive) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "Unrecognised set option '%s'.", tempstr); TBADD(ERR_SYNTAX,in->stkCharPos[PARSE_set_error_set_option]); } else { snprintf(c->errStat.errBuff, LSTR_LENGTH, ppltxt_unset , tempstr); TBADD(ERR_SYNTAX,in->stkCharPos[PARSE_set_error_set_option]); } } else { if (!interactive) { snprintf(c->errStat.errBuff, LSTR_LENGTH, "unset command detected with no set option following it."); TBADD(ERR_SYNTAX,0); } else { snprintf(c->errStat.errBuff, LSTR_LENGTH, "%s", ppltxt_unset_noword); TBADD(ERR_SYNTAX,0); } } return; } void ppl_directive_varset(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; pplObj *val = &stk[PARSE_var_set_value]; pplObj *rgx = &stk[PARSE_var_set_regex]; pplObj *obj=NULL; ppl_contextVarHierLookup(c, pl->srcLineN, pl->srcId, pl->srcFname, pl->linetxt, stk, in->stkCharPos, &obj, PARSE_var_set_varnames, PARSE_var_set_varname_varnames); if ((c->errStat.status) || (obj==NULL)) return; if (obj->objType==PPLOBJ_GLOB) { sprintf(c->errStat.errBuff,"Variable declared global in global namespace."); TBADD(ERR_NAMESPACE,0); return; } if (rgx->objType!=PPLOBJ_STR) // variable assignment. not regular expression { int om = obj->amMalloced; int rc = obj->refCount; obj->amMalloced = 0; obj->refCount = 1; ppl_garbageObject(obj); pplObjCpy(obj, val, 0, om, 1); obj->immutable = 0; obj->refCount = rc; } else // regular expression { int i, fstdin, fstdout, trialNumber; sigset_t sigs; fd_set readable; int rel; char *re = NULL, *outstr=NULL; char *in = (char *)rgx->auxil; char *instr = (char *)obj->auxil; // Check that input is a string if (obj->objType!=PPLOBJ_STR) { ppl_error(&c->errcontext,ERR_TYPE,-1,-1,"The regular expression operator can only act on variables which already have string values."); return; } // Append 's' to the beginning of the regular expression rel = (strlen(in)+8)*8; re = (char *)malloc(rel); if (re==NULL) { ppl_error(&c->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); return; } sprintf(re, "s%s", in); // Block sigchild sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); // Fork a child sed process with the regular expression on the command line, and send variable contents to it pplcsp_forkSed(c, re, &fstdin, &fstdout); if (write(fstdin, instr, strlen(instr)) != strlen(instr)) ppl_fatal(&c->errcontext,__FILE__,__LINE__,"Could not write to pipe to sed"); close(fstdin); // Wait for sed process's stdout to become readable. Get bored if this takes more than a second. trialNumber = 1; while (1) { struct timespec waitperiod; // A time.h timespec specifier for a wait of zero seconds waitperiod.tv_sec = 1; waitperiod.tv_nsec = 0; FD_ZERO(&readable); FD_SET(fstdout, &readable); if (pselect(fstdout+1, &readable, NULL, NULL, &waitperiod, NULL) == -1) { if ((errno==EINTR) && (trialNumber<3)) { trialNumber++; continue; } ppl_error(&c->errcontext, ERR_INTERNAL, -1, -1, "Failure of the pselect() function whilst waiting for sed to return data."); sigprocmask(SIG_UNBLOCK, &sigs, NULL); free(re); return; } break; } if (!FD_ISSET(fstdout , &readable)) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Got bored waiting for sed to return data."); sigprocmask(SIG_UNBLOCK, &sigs, NULL); free(re); return; } // Read data back from sed process if ((i = read(fstdout, re, rel)) < 0) { ppl_error(&c->errcontext, ERR_GENERIC, -1, -1, "Could not read from pipe to sed."); sigprocmask(SIG_UNBLOCK, &sigs, NULL); free(re); return; } re[i] = '\0'; close(fstdout); sigprocmask(SIG_UNBLOCK, &sigs, NULL); // Copy string into string variable outstr = (char *)malloc(i+1); if (outstr==NULL) { ppl_error(&c->errcontext, ERR_MEMORY, -1, -1, "Out of memory."); free(re); return; } strcpy(outstr,re); free(re); if (obj->auxilMalloced) free(obj->auxil); obj->auxil = outstr; obj->auxilLen = i+1; obj->auxilMalloced = 1; } return; } pyxplot-0.9.2/src/commands/interpolate.h0000664000175000017500000000332312026340554016714 0ustar dcf21dcf21// interpolate.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: interpolate.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _INTERPOLATE_H #define _INTERPOLATE_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" #define INTERP_AKIMA 23001 #define INTERP_LINEAR 23002 #define INTERP_LOGLIN 23003 #define INTERP_POLYN 23004 #define INTERP_SPLINE 23005 #define INTERP_STEPWISE 23006 #define INTERP_2D 23007 #define INTERP_BMPR 23008 #define INTERP_BMPG 23009 #define INTERP_BMPB 23010 void ppl_directive_interpolate(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth, int mode); void ppl_spline_evaluate (ppl_context *c, char *FuncName, splineDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout); void ppl_interp2d_evaluate (ppl_context *c, const char *FuncName, splineDescriptor *desc, const pplObj *in1, const pplObj *in2, const unsigned char bmp, pplObj *out, int *status, char *errout); #endif pyxplot-0.9.2/src/commands/core.h0000664000175000017500000000401012026340554015310 0ustar dcf21dcf21// core.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: core.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _CORE_H #define _CORE_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_assert (ppl_context *c, parserLine *pl, parserOutput *in); void ppl_directive_cd (ppl_context *c, parserLine *pl, parserOutput *in); void ppl_directive_exec (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_global (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_history(ppl_context *c, parserLine *pl, parserOutput *in); void ppl_directive_load (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_local (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_print (ppl_context *c, parserLine *pl, parserOutput *in); void ppl_directive_save (ppl_context *c, parserLine *pl, parserOutput *in); void ppl_directive_seterror(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); void ppl_directive_unseterror(ppl_context *c, parserLine *pl, parserOutput *in, int interactive); void ppl_directive_varset (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/commands/flowctrl.h0000664000175000017500000000416112026340554016223 0ustar dcf21dcf21// flowctrl.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: flowctrl.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _FLOWCTRL_H #define _FLOWCTRL_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" void ppl_directive_break (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_continue(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_return (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_do (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_for (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_foreach (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_fordata (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_if (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_subrt (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_while (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_with (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/commands/eqnsolve.h0000664000175000017500000000257512026340554016232 0ustar dcf21dcf21// eqnsolve.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eqnsolve.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _EQNSOLVE_H #define _EQNSOLVE_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" double ppl_optimise_RealToLog(double in, int iter, double *norm); double ppl_optimise_LogToReal(double in, int iter, double *norm); void ppl_directive_solve (ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_maximise(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_directive_minimise(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/commands/help.c0000664000175000017500000002344712026340554015322 0ustar dcf21dcf21// help.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: help.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/dict.h" #include "coreUtils/errorReport.h" #include "coreUtils/list.h" #include "coreUtils/memAlloc.h" #include "coreUtils/stringList.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "userspace/context.h" #include "pplConstants.h" #define MAX_HELP_DEPTH 16 // The maximum possible depth of a help hierarchy #define MAX_HELP_HITS 12 // The maximum possible number of help topics which match the same autocomplete strings static void help_PagerDisplay(pplerr_context *c, char *PageName, xmlNode *node, int interactive) { xmlNode *cur_node; char textBuffer [LSTR_LENGTH]; char textBuffer2 [LSTR_LENGTH]; char defaultpagerName[] = "less"; char *pagerName; char *Ncolumns_text; int i, j, Ncolumns, Nchildren, strlen_version, strlen_date; FILE *pagerHandle; sprintf(textBuffer,"\\\\**** Help Topic: %s****\\\\", PageName); i = strlen(textBuffer); for (cur_node = node->children; cur_node; cur_node = cur_node->next) // Loop over children if (cur_node->type == XML_TEXT_NODE) { strlen_version = strlen("$VERSION"); strlen_date = strlen("$DATE" ); for (j=0; cur_node->content[j]!='\0'; ) { if (strncmp((char *)cur_node->content+j,"$VERSION",strlen_version)==0) { j+=strlen_version; strcpy(textBuffer+i,VERSION); i += strlen(textBuffer+i); } else if (strncmp((char *)cur_node->content+j,"$DATE" ,strlen_date )==0) { j+=strlen_date ; strcpy(textBuffer+i,DATE ); i += strlen(textBuffer+i); } else { textBuffer[i++] = cur_node->content[j++]; } } } // NB, textBuffer is not null terminated at this point, but we're about to add stuff to it... sprintf(textBuffer+i, "\\\\\\\\\\\\"); // Insert information about children Nchildren = 0; for (cur_node = node->children; cur_node; cur_node = cur_node->next) // Loop over children if (cur_node->type == XML_ELEMENT_NODE) { if (Nchildren == 0) { sprintf(textBuffer+i,"This help page has the following subtopics:\\\\\\\\"); i += strlen(textBuffer+i); } else { sprintf(textBuffer+i,", "); i += strlen(textBuffer+i); } sprintf(textBuffer+i,"%s",cur_node->name); i += strlen(textBuffer+i); Nchildren++; } if (Nchildren == 0) { sprintf(textBuffer+i,"This help page has no subtopics.\\\\\\\\"); i += strlen(textBuffer+i); } else { sprintf(textBuffer+i,".\\\\\\\\"); i += strlen(textBuffer+i); } // If interactive, tell user how to quit, and also work out column width of display if (interactive!=0) { sprintf(textBuffer+i,"Press the 'Q' key to exit this help page.\\\\"); Ncolumns_text = getenv("COLUMNS"); if (!((Ncolumns_text != NULL) && (Ncolumns = ppl_getFloat(Ncolumns_text, &i), i==strlen(Ncolumns_text)))) Ncolumns = 80; pagerName = getenv("PAGER"); if (pagerName == NULL) pagerName = defaultpagerName; } else { Ncolumns = 80; pagerName = defaultpagerName; } // Word wrap the text we have, and send it to a pager ppl_strWordWrap(textBuffer, textBuffer2, Ncolumns); if (interactive == 0) { ppl_report(c,textBuffer2); // In non-interactive sessions, we just send text to stdout } else { if ((pagerHandle = popen(pagerName,"w"))==NULL) { ppl_error(c, ERR_INTERNAL, -1, -1, "Cannot open pipe to pager application."); } else { fprintf(pagerHandle, "%s", textBuffer2); pclose(pagerHandle); } } return; } static void help_TopicPrint(char *out, char **words, int Nwords) { int i,j; for (i=0,j=0; i<=Nwords; i++) { strcpy(out+j, words[i]); j += strlen(out+j); out[j++]=' '; } out[j]='\0'; } static void help_MatchFound(pplerr_context *c, xmlNode *node, xmlNode **matchNode, list *topicWords, int *matchTextPos, int *Nmatches, int *ambiguous, char **helpPosition, char **helpTexts) { int abbreviation,i; list *prevMatchPosition; if ((*Nmatches)==MAX_HELP_HITS) { ppl_error(c, ERR_INTERNAL, -1, -1, "Cannot parse ppl_help.xml. Need to increase MAX_HELP_HITS."); return; } help_TopicPrint(helpTexts[*Nmatches], helpPosition, ppl_listLen(topicWords)); if (*ambiguous == 0) { if (*matchNode == NULL) { *matchTextPos = 0; *matchNode = node; // This is the first match we've found } else { prevMatchPosition = ppl_strSplit( helpTexts[*matchTextPos] ); abbreviation = 1; // If previous match is an autocomplete shortening of current match, let it stand for (i=0; i<=ppl_listLen(topicWords); i++) if (ppl_strAutocomplete( (char *)ppl_listGetItem(prevMatchPosition,i) , helpPosition[i] , 1)==-1) {abbreviation=0; break;} if (abbreviation!=1) { abbreviation = 1; // If current match is an autocomplete shortening of previous match, the current match wins for (i=0; i<=ppl_listLen(topicWords); i++) if (ppl_strAutocomplete( helpPosition[i] , (char *)ppl_listGetItem(prevMatchPosition,i) , 1)==-1) {abbreviation=0; break;} if (abbreviation==1) { *matchTextPos = *Nmatches; *matchNode = node; } else { *ambiguous = 1; // We have multiple ambiguous matches } } } } (*Nmatches)++; return; } void help_explore(pplerr_context *c, xmlNode *node, xmlNode **matchNode, list *topicWords, int *matchTextPos, int *Nmatches, int *ambiguous, char **helpPosition, char **helpTexts, int depth) { xmlNode *cur_node = NULL; int match,i; if (depth>ppl_listLen(topicWords)) return; if (depth==MAX_HELP_DEPTH) { ppl_error(c, ERR_INTERNAL, -1, -1, "Cannot parse ppl_help.xml. Need to increase MAX_HELP_DEPTH."); return; } for (cur_node = node; cur_node; cur_node = cur_node->next) // Loop over siblings { match=1; if (cur_node->type == XML_ELEMENT_NODE) { sprintf(helpPosition[depth], "%s", cur_node->name); // Converted signedness of chars for (i=1;i<=depth;i++) if (ppl_strAutocomplete( (char *)ppl_listGetItem(topicWords,i-1) , helpPosition[i], 1)==-1) {match=0; break;} if ((match==1) && (depth==ppl_listLen(topicWords))) help_MatchFound(c,cur_node,matchNode,topicWords,matchTextPos,Nmatches,ambiguous,helpPosition,helpTexts); } if (match==1) help_explore(c,cur_node->children,matchNode,topicWords,matchTextPos,Nmatches,ambiguous,helpPosition,helpTexts,depth+1); } return; } void ppl_directive_help(ppl_context *c, parserLine *pl, parserOutput *in, int interactive) { pplerr_context *e = &c->errcontext; list *topicWords = NULL; // A list of the help topic words supplied by the user char *topicString = NULL; // The string of help topic words supplied by the user char filename[FNAME_LENGTH]; // The filename of ppl_help.xml char *helpPosition[MAX_HELP_DEPTH]; // A list of xml tags, used to keep track of our position as we traverse the xml hierarchy char *helpTexts [MAX_HELP_HITS ]; // A list of all of the help topics which have matched the user's request xmlDoc *doc = NULL; // The XML document ppl_help.xml xmlNode *root_element = NULL; // The root element of the above xmlNode *matchNode = NULL; // The XML node which best fits the user's request int matchTextPos = -1; // The position within helpTexts of the node pointed to by matchNode int ambiguous = 0; // Becomes one if we find that the user's request matches multiple help pages int Nmatches = 0; // Counts the number of pages the user's request matches int i; topicString = (char *)in->stk[PARSE_help_topic].auxil; topicWords = ppl_strSplit( topicString ); sprintf(filename, "%s%s%s", SRCDIR, PATHLINK, "help.xml"); // Find help.xml LIBXML_TEST_VERSION doc = xmlReadFile(filename, NULL, 0); if (doc==NULL) { sprintf(e->tempErrStr, "Help command cannot find help data in expected location of '%s'.", filename); ppl_error(e, ERR_INTERNAL, -1, -1, NULL); return; } for (i=0;i // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: histogram.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _HISTOGRAM_H #define _HISTOGRAM_H 1 #include "parser/parser.h" #include "userspace/context.h" #include "userspace/pplObj.h" #include "userspace/pplObjFunc.h" void ppl_directive_histogram(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth); void ppl_histogram_evaluate (ppl_context *c, char *FuncName, histogramDescriptor *desc, pplObj *in, pplObj *out, int *status, char *errout); #endif pyxplot-0.9.2/src/commands/eqnsolve.c0000664000175000017500000004604712026340554016227 0ustar dcf21dcf21// eqnsolve.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: eqnsolve.c 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _EQNSOLVE_C 1 #include #include #include #include #include #include #include "commands/eqnsolve.h" #include "coreUtils/errorReport.h" #include "expressions/expCompile.h" #include "expressions/expEval.h" #include "expressions/traceback_fns.h" #include "mathsTools/dcfmath.h" #include "parser/cmdList.h" #include "parser/parser.h" #include "settings/settingTypes.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/contextVarDef.h" #include "userspace/garbageCollector.h" #include "userspace/pplObj_fns.h" #include "userspace/pplObjPrint.h" #include "userspace/pplObjUnits.h" #include "userspace/unitsDisp.h" #include "userspace/unitsArithmetic.h" #include "stringTools/strConstants.h" // Functions which we use to optimise in a log-log type space to help when // solutions are many orders of magnitude different from initial guess double ppl_optimise_RealToLog(double in, int iter, double *norm) { double a=-2; if ((iter==1) || (iter >= 4)) { *norm = ppl_max(1e-200, fabs(in)); return in/(*norm); } if (iter >=3) a = -500; if (in >= exp(a)) return log(in); else return 2*a - log(2*exp(a)-in); } double ppl_optimise_LogToReal(double in, int iter, double *norm) { double a=-2; if ((iter==1) || (iter >=4)) return in*(*norm); if (iter >=3) a = -500; if (in >= a) return exp(in); else return 2*exp(a)-exp(2*a-in); } // Structure used to communicate between top-level optimiser, and the // evaluation slave called by GSL typedef struct MMComm { ppl_context *context; char *inLine; int iterDepth; int expr1pos [EQNSOLVE_MAXDIMS]; int expr2pos [EQNSOLVE_MAXDIMS]; pplExpr *expr1 [EQNSOLVE_MAXDIMS]; pplExpr *expr2 [EQNSOLVE_MAXDIMS]; char *fitvarname[EQNSOLVE_MAXDIMS]; // Name of nth fit variable pplObj *fitvar [EQNSOLVE_MAXDIMS]; double norm [EQNSOLVE_MAXDIMS]; int Nfitvars , Nexprs , GoneNaN, iter2; double sign; pplObj first [EQNSOLVE_MAXDIMS]; unsigned char isFirst[EQNSOLVE_MAXDIMS]; double WorstScore; int warnPos,warnExprId,warnExprNo; // One final algebra error is allowed to produce a warning char warntext[LSTR_LENGTH]; } MMComm; #define WORSTSCORE_INIT -(DBL_MAX/1e10) static char *printParameterValues(MMComm *data, char *output) { int i=0, j=0; if (data->Nfitvars>1) { sprintf(output+j, "( "); j+=strlen(output+j); } for (i=0; iNfitvars; i++) { sprintf(output+j, "%s=", data->fitvarname[i]); j+=strlen(output+j); pplObjPrint(data->context,data->fitvar[i],data->fitvarname[i],output+j,LSTR_LENGTH-j,0,1); j+=strlen(output+j); sprintf(output+j, "; "); j+=strlen(output+j); } if (j>2) { if (data->Nfitvars>1) strcpy(output+j-2, " )"); else strcpy(output+j-2, "" ); } else strcpy(output , "()"); return output; } static double MultiMinSlave(const gsl_vector *x, void *params) { pplObj output1, output2, *tmp; int i, lastOpAssign; unsigned char squareroot=0; double accumulator=0.0, output; MMComm *data = (MMComm *)params; ppl_context *c = data->context; if (c->errStat.status) return GSL_NAN; // We've previously had a serious error... so don't do any more work if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { for (i=0; iNfitvars; i++) data->fitvar[i]->real = ppl_optimise_LogToReal( gsl_vector_get(x, i) , data->iter2, &data->norm[i] ); } else { for (i=0; iNfitvars; i++) { data->fitvar[i]->real = ppl_optimise_LogToReal( gsl_vector_get(x,2*i ) , data->iter2, &data->norm[2*i ] ); data->fitvar[i]->imag = ppl_optimise_LogToReal( gsl_vector_get(x,2*i+1) , data->iter2, &data->norm[2*i+1] ); data->fitvar[i]->flagComplex = !ppl_dblEqual(data->fitvar[i]->imag, 0); if (!data->fitvar[i]->flagComplex) data->fitvar[i]->imag=0.0; // Enforce that real numbers have positive zero imaginary components } } for (i=0; iNexprs; i++) { tmp = ppl_expEval(c, data->expr1[i], &lastOpAssign, 0, data->iterDepth+1); // If a numerical error happened; ignore it for now, but return NAN if (c->errStat.status) { data->warnExprId=i; data->warnExprNo=1; data->warnPos=c->errStat.errPosExpr; sprintf(data->warntext, "An algebraic error was encountered at %s: %s", printParameterValues(data,c->errcontext.tempErrStr), c->errStat.errMsgExpr); ppl_tbClear(c); return GSL_NAN; } // Check that expression evaluates a number if ((tmp==NULL) || (tmp->objType!=PPLOBJ_NUM)) { strcpy(c->errStat.errBuff, "Supplied expression does not evaluate to a numeric quantity."); ppl_tbAdd(c,data->expr1[i]->srcLineN,data->expr1[i]->srcId,data->expr1[i]->srcFname,0,ERR_TYPE,data->expr1pos[i],data->inLine,""); ppl_garbageObject(&c->stack[--c->stackPtr]); // trash and pop tmp from stack return GSL_NAN; } memcpy(&output1,tmp,sizeof(pplObj)); ppl_garbageObject(&c->stack[--c->stackPtr]); // trash and pop tmp from stack if (data->expr2[i] != NULL) { tmp = ppl_expEval(c, data->expr2[i], &lastOpAssign, 0, data->iterDepth+1); // If a numerical error happened; ignore it for now, but return NAN if (c->errStat.status) { data->warnExprId=i; data->warnExprNo=2; data->warnPos=c->errStat.errPosExpr; sprintf(data->warntext, "An algebraic error was encountered at %s: %s", printParameterValues(data,c->errcontext.tempErrStr), c->errStat.errMsgExpr); ppl_tbClear(c); return GSL_NAN; } // Check that expression evaluates a number if ((tmp==NULL) || (tmp->objType!=PPLOBJ_NUM)) { strcpy(c->errStat.errBuff, "Supplied expression does not evaluate to a numeric quantity."); ppl_tbAdd(c,data->expr2[i]->srcLineN,data->expr2[i]->srcId,data->expr2[i]->srcFname,0,ERR_TYPE,data->expr2pos[i],data->inLine,""); ppl_garbageObject(&c->stack[--c->stackPtr]); // trash and pop tmp from stack return GSL_NAN; } memcpy(&output2,tmp,sizeof(pplObj)); ppl_garbageObject(&c->stack[--c->stackPtr]); // trash and pop tmp from stack if (!ppl_unitsDimEqual(&output1, &output2)) { sprintf(c->errStat.errBuff, "The two sides of the equation which is being solved are not dimensionally compatible. The left side has dimensions of <%s> while the right side has dimensions of <%s>.",ppl_printUnit(c,&output1, NULL, NULL, 0, 1, 0),ppl_printUnit(c,&output2, NULL, NULL, 1, 1, 0)); ppl_tbAdd(c,data->expr1[i]->srcLineN,data->expr1[i]->srcId,data->expr1[i]->srcFname,0,ERR_UNIT,data->expr1pos[i],data->inLine,""); return GSL_NAN; } #define TWINLOG(X) ((X>1e-200) ? log(X) : (2*log(1e-200) - log(2e-200-X))) accumulator += pow(TWINLOG(output1.real) - TWINLOG(output2.real) , 2); // Minimise sum of square deviations of many equations accumulator += pow(TWINLOG(output1.imag) - TWINLOG(output2.imag) , 2); squareroot = 1; } else { if (data->isFirst[i]) { memcpy(&data->first[i], &output1, sizeof(pplObj)); data->isFirst[i] = 0; } else { if (!ppl_unitsDimEqual(&data->first[i],&output1)) { sprintf(c->errStat.errBuff, "The function being minimised or maximised does not have consistent units."); ppl_tbAdd(c,data->expr1[i]->srcLineN,data->expr1[i]->srcId,data->expr1[i]->srcFname,0,ERR_UNIT,data->expr1pos[i],data->inLine,""); return GSL_NAN; } } accumulator += output1.real; // ... or just the raw values in minimise and maximise commands } } if (squareroot) accumulator = sqrt(accumulator); output = accumulator * data->sign; if ((!gsl_finite(output)) && (data->WorstScore > WORSTSCORE_INIT)) { data->WorstScore *= 1.1; return data->WorstScore; } if (!gsl_finite(output)) { data->GoneNaN=1; } else { if (data->WorstScore < output) data->WorstScore = output; } return output; } static void multiMinIterate(MMComm *commlink, parserLine *pl) { ppl_context *c = commlink->context; size_t iter = 0,iter2 = 0; int i, Nparams, status=0; double size=0,sizelast=0,sizelast2=0; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; // We don't use nmsimplex2 here because it was new in gsl 1.12 gsl_multimin_fminimizer *s; gsl_vector *x, *ss; gsl_multimin_function fn; Nparams = commlink->Nfitvars * ((c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) ? 1:2); fn.n = Nparams; fn.f = &MultiMinSlave; fn.params = (void *)commlink; x = gsl_vector_alloc( Nparams ); ss = gsl_vector_alloc( Nparams ); iter2=0; do { iter2++; commlink->iter2 = iter2; sizelast2 = size; // Transfer starting guess values from fitting variables into gsl_vector x if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { for (i=0; iNfitvars; i++) gsl_vector_set(x, i ,ppl_optimise_RealToLog(commlink->fitvar[i]->real , iter2, &commlink->norm[ i ])); } else { for (i=0; iNfitvars; i++) { gsl_vector_set(x,2*i ,ppl_optimise_RealToLog(commlink->fitvar[i]->real , iter2, &commlink->norm[2*i ])); gsl_vector_set(x,2*i+1,ppl_optimise_RealToLog(commlink->fitvar[i]->imag , iter2, &commlink->norm[2*i+1])); } } for (i=0; i1e-6) gsl_vector_set(ss, i, 0.05 * gsl_vector_get(x,i)); else gsl_vector_set(ss, i, 0.05 ); // Avoid having a stepsize of zero } s = gsl_multimin_fminimizer_alloc (T, fn.n); gsl_multimin_fminimizer_set (s, &fn, x, ss); // If initial value we are giving the minimiser produces an algebraic error, it's not worth continuing MultiMinSlave(x,(void *)commlink); if (c->errStat.status) return; if (commlink->warnPos>=0) { int i = commlink->warnExprId; int j = commlink->warnExprNo; strcpy(c->errStat.errBuff, commlink->warntext); if (j==1) ppl_tbAdd(c,commlink->expr1[i]->srcLineN,commlink->expr1[i]->srcId,commlink->expr1[i]->srcFname,1,ERR_NUMERICAL,commlink->expr1pos[i] + commlink->warnPos,commlink->inLine,""); else ppl_tbAdd(c,commlink->expr2[i]->srcLineN,commlink->expr2[i]->srcId,commlink->expr2[i]->srcFname,1,ERR_NUMERICAL,commlink->expr2pos[i] + commlink->warnPos,commlink->inLine,""); return; } iter = 0; commlink->GoneNaN = 0; commlink->WorstScore = WORSTSCORE_INIT; do { iter++; // When you're minimising over many parameters simultaneously sometimes nothing happens for a long time for (i=0; i<2+Nparams*2; i++) { status = gsl_multimin_fminimizer_iterate(s); if (status) break; } if (status || c->errStat.status) break; sizelast = size; size = gsl_multimin_fminimizer_minimum(s); } while ((iter < 10) || ((size < sizelast) && (iter < 50))); // Iterate 10 times, and then see whether size carries on getting smaller // Transfer best-fit values from s->x into fitting variables if (c->set->term_current.ComplexNumbers == SW_ONOFF_OFF) { for (i=0; iNfitvars; i++) commlink->fitvar[i]->real = ppl_optimise_LogToReal(gsl_vector_get(s->x, i ) , iter2, &commlink->norm[ i ]); } else { for (i=0; iNfitvars; i++) { commlink->fitvar[i]->real = ppl_optimise_LogToReal(gsl_vector_get(s->x,2*i ) , iter2, &commlink->norm[2*i ]); commlink->fitvar[i]->imag = ppl_optimise_LogToReal(gsl_vector_get(s->x,2*i+1) , iter2, &commlink->norm[2*i+1]); } } gsl_multimin_fminimizer_free(s); } while ((iter2 < 4) || ((commlink->GoneNaN==0) && (!status) && (size < sizelast2) && (iter2 < 20))); // Iterate 2 times, and then see whether size carries on getting smaller if (iter2>=20) status=1; if (status) { sprintf(c->errStat.errBuff, "Failed to converge. GSL returned error: %s", gsl_strerror(status)); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_UNIT,0,pl->linetxt,""); return; } gsl_vector_free(x); gsl_vector_free(ss); return; } static void minOrMax(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth, double sign) { pplObj *stk = in->stk, *pos; MMComm commlink; char *varName; pplObj dummyTemp; int i; commlink.context = c; commlink.inLine = pl->linetxt; commlink.iterDepth = iterDepth; commlink.Nfitvars = 0; commlink.Nexprs = 1; // Fetch the names of the variables which we are fitting pos = &stk[PARSE_minimise_fit_variables]; while ((pos->objType == PPLOBJ_NUM) && (pos->real > 0)) { pos = &stk[ (int)round(pos->real) ]; varName = (char *)(pos + PARSE_minimise_fit_variable_fit_variables)->auxil; ppl_contextGetVarPointer(c, varName, &commlink.fitvar[commlink.Nfitvars], &dummyTemp); if (dummyTemp.objType==PPLOBJ_NUM) { ppl_unitsDimCpy(commlink.fitvar[commlink.Nfitvars], &dummyTemp); commlink.fitvar[commlink.Nfitvars]->real = dummyTemp.real; commlink.fitvar[commlink.Nfitvars]->imag = dummyTemp.imag; commlink.fitvar[commlink.Nfitvars]->flagComplex = dummyTemp.flagComplex; } dummyTemp.amMalloced=0; ppl_garbageObject(&dummyTemp); commlink.fitvarname[ commlink.Nfitvars ] = varName; commlink.Nfitvars += 1; if (commlink.Nfitvars >= EQNSOLVE_MAXDIMS) { sprintf(c->errStat.errBuff, "Too many via variables; the maximum allowed number is %d.", EQNSOLVE_MAXDIMS); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_OVERFLOW,0,pl->linetxt,""); return; } } commlink.expr1[0] = (pplExpr *)stk[PARSE_minimise_expression].auxil; commlink.expr1pos[0]= in->stkCharPos[PARSE_minimise_expression]; commlink.expr2[0] = NULL; commlink.sign = sign; commlink.isFirst[0] = 1; commlink.warnPos =-1; commlink.GoneNaN = 0; commlink.WorstScore = WORSTSCORE_INIT; pplObjNum(&commlink.first[0],0,0,0); multiMinIterate(&commlink, pl); if ((c->errStat.status) || (commlink.GoneNaN==1)) { for (i=0; ireal=GSL_NAN; commlink.fitvar[i]->imag=0; commlink.fitvar[i]->flagComplex=0; } // We didn't produce a sensible answer return; } if (commlink.warnPos >= 0) ppl_warning(&c->errcontext, ERR_NUMERICAL, commlink.warntext); return; } void ppl_directive_solve(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { pplObj *stk = in->stk; int pos; MMComm commlink; char *varName; pplObj dummyTemp; int i; commlink.context = c; commlink.inLine = pl->linetxt; commlink.iterDepth = iterDepth; commlink.Nfitvars = 0; commlink.Nexprs = 0; // Fetch the names of the variables which we are fitting pos = PARSE_solve_fit_variables; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { pos = (int)round(stk[pos].real); varName = (char *)stk[pos+PARSE_solve_fit_variable_fit_variables].auxil; ppl_contextGetVarPointer(c, varName, &commlink.fitvar[commlink.Nfitvars], &dummyTemp); if (dummyTemp.objType==PPLOBJ_NUM) { ppl_unitsDimCpy(commlink.fitvar[commlink.Nfitvars], &dummyTemp); commlink.fitvar[commlink.Nfitvars]->real = dummyTemp.real; commlink.fitvar[commlink.Nfitvars]->imag = dummyTemp.imag; commlink.fitvar[commlink.Nfitvars]->flagComplex = dummyTemp.flagComplex; } dummyTemp.amMalloced=0; ppl_garbageObject(&dummyTemp); commlink.fitvarname[ commlink.Nfitvars ] = varName; commlink.Nfitvars += 1; if (commlink.Nfitvars >= EQNSOLVE_MAXDIMS) { sprintf(c->errStat.errBuff, "Too many via variables; the maximum allowed number is %d.", EQNSOLVE_MAXDIMS); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_OVERFLOW,in->stkCharPos[pos+PARSE_solve_fit_variable_fit_variables],pl->linetxt,""); return; } } // Fetch a list of the equations to solve pos = PARSE_solve_expressions; while ((stk[pos].objType == PPLOBJ_NUM) && (stk[pos].real > 0)) { pos = (int)round(stk[pos].real); commlink.expr1 [commlink.Nexprs] = (pplExpr *)stk[pos+PARSE_solve_left_expression_expressions].auxil; commlink.expr1pos[commlink.Nexprs] = in->stkCharPos[pos+PARSE_solve_left_expression_expressions]; commlink.expr2 [commlink.Nexprs] = (pplExpr *)stk[pos+PARSE_solve_right_expression_expressions].auxil; commlink.expr2pos[commlink.Nexprs] = in->stkCharPos[pos+PARSE_solve_right_expression_expressions]; commlink.Nexprs += 1; if (commlink.Nexprs >= EQNSOLVE_MAXDIMS) { sprintf(c->errStat.errBuff, "Too many simultaneous equations to solve; the maximum allowed number is %d.", EQNSOLVE_MAXDIMS); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_OVERFLOW,in->stkCharPos[pos+PARSE_solve_left_expression_expressions],pl->linetxt,""); return; } } if (commlink.Nexprs < 1) { sprintf(c->errStat.errBuff, "No equations supplied to solve."); ppl_tbAdd(c,pl->srcLineN,pl->srcId,pl->srcFname,0,ERR_NUMERICAL,0,pl->linetxt,""); return; } commlink.sign = 1.0; commlink.warnPos =-1; commlink.GoneNaN = 0; commlink.WorstScore = WORSTSCORE_INIT; for (i=0; ierrStat.status) || (commlink.GoneNaN==1)) { for (i=0; ireal=GSL_NAN; commlink.fitvar[i]->imag=0; commlink.fitvar[i]->flagComplex=0; } // We didn't produce a sensible answer return; } if (commlink.warnPos >= 0) ppl_warning(&c->errcontext, ERR_NUMERICAL, commlink.warntext); return; } void ppl_directive_minimise(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { minOrMax(c, pl, in, interactive, iterDepth, 1.0); } void ppl_directive_maximise(ppl_context *c, parserLine *pl, parserOutput *in, int interactive, int iterDepth) { minOrMax(c, pl, in, interactive, iterDepth, -1.0); } pyxplot-0.9.2/src/input.c0000664000175000017500000003355312026340554013727 0ustar dcf21dcf21// input.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: input.c 1289 2012-08-11 16:06:49Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #define _INPUT_C 1 #include #include #include #include #include #ifdef HAVE_READLINE #include #include #endif #include "coreUtils/errorReport.h" #include "coreUtils/getPasswd.h" #include "expressions/traceback_fns.h" #include "parser/parser.h" #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "settings/settings.h" #include "settings/settingTypes.h" #include "settings/textConstants.h" #include "userspace/context.h" #include "children.h" #include "input.h" #include "pplConstants.h" #include "pyxplot.h" int ppl_inputInit(ppl_context *context) { context->inputLineBufferLen = LSTR_LENGTH; context->inputLineBuffer = (char *)malloc( context->inputLineBufferLen ); return (context->inputLineBuffer!=NULL); } sigjmp_buf sigint_destination; int sigint_longjmp=0; void ppl_interactiveSigInt(int signo) { if (sigint_longjmp) siglongjmp(sigint_destination, 1); fprintf(stdout,"\n"); cancellationFlag = 1; return; } void ppl_interactiveSession(ppl_context *context) { int linenumber = 1; void (*sigint_old)(int) = NULL; parserLine *pl = NULL; parserStatus *ps = NULL; if (DEBUG) ppl_log(&context->errcontext,"Starting an interactive session."); ppl_parserStatInit(&ps,&pl); if ( (ps==NULL) || (context->inputLineBuffer == NULL) ) { ppl_error(&context->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); return; } if ((isatty(STDIN_FILENO) == 1) && (context->errcontext.session_default.splash == SW_ONOFF_ON)) ppl_report(&context->errcontext,ppltxt_welcome); context->shellExiting = 0; sigint_old = signal(SIGINT, ppl_interactiveSigInt); // Set up SIGINT handler while ((!context->shellExiting)&&(!context->shellBroken)&&(!context->shellContinued)&&(!context->shellReturned)) { pplcsp_checkForGvOutput(context); cancellationFlag = 0; if (isatty(STDIN_FILENO) == 1) { ppl_error_setstreaminfo(&context->errcontext,-1, ""); #ifdef HAVE_READLINE { int len; char *line_ptr, prompt[32]; if (context->inputLineAddBuffer!=NULL) { strcpy(prompt,".......> "); } else { snprintf(prompt,16,"%s.......",ps->prompt); strcpy(prompt+7, "> "); } if (sigsetjmp(sigint_destination,1)!=0) { printf("\n"); } sigint_longjmp=1; line_ptr = readline(prompt); sigint_longjmp=0; if (line_ptr==NULL) break; add_history(line_ptr); context->historyNLinesWritten++; len = strlen(line_ptr)+1; if ((context->inputLineBufferLen>LSTR_LENGTH) && (leninputLineBuffer); ppl_inputInit(context); } if (len > context->inputLineBufferLen) { context->inputLineBuffer = (char *)realloc(context->inputLineBuffer, len); context->inputLineBufferLen=len; } if (context->inputLineBuffer == NULL) break; strcpy(context->inputLineBuffer, line_ptr); free(line_ptr); } #else { char prompt[32]; if (sigsetjmp(sigint_destination,1)!=0) { printf("\n"); } sigint_longjmp=1; if (context->inputLineAddBuffer!=NULL) { strcpy(prompt,".......> "); } else { snprintf(prompt,16,"%s.......",ps->prompt); strcpy(prompt+7, "> "); } printf("%s",prompt); if (fgets(context->inputLineBuffer,context->inputLineBufferLen-1,stdin)==NULL) { break; } sigint_longjmp=0; context->inputLineBuffer[context->inputLineBufferLen-1]='\0'; } #endif } else { ppl_error_setstreaminfo(&context->errcontext, linenumber, "piped input"); if ((feof(stdin)) || (ferror(stdin))) break; ppl_file_readline(stdin, &context->inputLineBuffer, &context->inputLineBufferLen, 0); context->inputLineBuffer[context->inputLineBufferLen-1]='\0'; linenumber++; } if ((!cancellationFlag)&&(!context->shellExiting)&&(!context->shellBroken)&&(!context->shellContinued)&&(!context->shellReturned)) { ppl_processLine(context, ps, context->inputLineBuffer, isatty(STDIN_FILENO), 0); } cancellationFlag = 0; ppl_error_setstreaminfo(&context->errcontext, -1, ""); pplcsp_killAllHelpers(context); } if (context->inputLineAddBuffer != NULL) { free(context->inputLineAddBuffer); context->inputLineAddBuffer=NULL; } context->shellExiting = 0; signal(SIGINT, sigint_old); // Restore old SIGINT handler if (isatty(STDIN_FILENO) == 1) { if (context->errcontext.session_default.splash == SW_ONOFF_ON) ppl_report(&context->errcontext,"\nGoodbye. Have a nice day."); else ppl_report(&context->errcontext,""); // Make a new line } ppl_parserStatFree(&ps); return; } void ppl_processScript(ppl_context *context, char *input, int iterDepth) { int linenumber = 1; int status; char full_filename[FNAME_LENGTH]; char filename_description[FNAME_LENGTH]; FILE *infile; parserLine *pl = NULL; parserStatus *ps = NULL; int shellBreakableOld = context->shellBreakable; int shellReturnableOld = context->shellReturnable; char *oldInputLineBuffer = context->inputLineBuffer; int oldInputLineBufferLen = context->inputLineBufferLen; char *oldInputLineAddBuffer = context->inputLineAddBuffer; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Processing input from the script file '%s'.", input); ppl_log(&context->errcontext, NULL); } ppl_unixExpandUserHomeDir(&context->errcontext, input, context->errcontext.session_default.cwd, full_filename); sprintf(filename_description, "file '%s'", input); if ((infile=fopen(full_filename,"r")) == NULL) { sprintf(context->errcontext.tempErrStr, "Could not find command file '%s'. Skipping on to next command file.", full_filename); ppl_error(&context->errcontext, ERR_FILE, -1, -1, NULL); goto restore; } ppl_inputInit(context); ppl_parserStatInit(&ps,&pl); if ( (ps==NULL) || (context->inputLineBuffer == NULL) ) { ppl_error(&context->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); goto restore; } context->shellExiting = 0; context->shellBreakable = 0; context->shellReturnable = 0; while ((!context->shellExiting)&&(!context->shellBroken)&&(!context->shellContinued)&&(!context->shellReturned)&&(!cancellationFlag)) { ppl_error_setstreaminfo(&context->errcontext, linenumber, filename_description); if ((feof(infile)) || (ferror(infile))) break; if (context->inputLineBufferLen>LSTR_LENGTH) { free(context->inputLineBuffer); ppl_inputInit(context); } if (context->inputLineBuffer == NULL) { ppl_error(&context->errcontext,ERR_MEMORY,-1,-1,"Out of memory."); break; } ppl_file_readline(infile, &context->inputLineBuffer, &context->inputLineBufferLen, 0); linenumber++; status = ppl_processLine(context, ps, context->inputLineBuffer, 0, iterDepth); ppl_error_setstreaminfo(&context->errcontext, -1, ""); pplcsp_killAllHelpers(context); if ( (status>0) || context->shellExiting || cancellationFlag )// If an error occurs in a script, aborted processing it { if (!context->shellExiting) ppl_error(&context->errcontext, ERR_FILE, -1, -1, "Aborting."); if (context->inputLineAddBuffer != NULL) { free(context->inputLineAddBuffer); context->inputLineAddBuffer=NULL; } break; } } if ((!context->shellExiting)&&(!context->shellBroken)&&(!context->shellContinued)&&(!context->shellReturned)&&(!cancellationFlag)) if (context->inputLineAddBuffer != NULL) // Process last line of file if there is still text buffered { ppl_warning(&context->errcontext,ERR_SYNTAX,"Line continuation character (\\) at the end of command script, with no line following it."); ppl_error_setstreaminfo(&context->errcontext, linenumber, filename_description); status = ppl_processLine(context, ps, "", 0, iterDepth); ppl_error_setstreaminfo(&context->errcontext, -1, ""); if (status>0) ppl_error(&context->errcontext, ERR_FILE, -1, -1, "Aborting."); if (context->inputLineAddBuffer != NULL) { free(context->inputLineAddBuffer); context->inputLineAddBuffer=NULL; } } context->shellExiting = 0; context->shellBreakable = shellBreakableOld; context->shellReturnable = shellReturnableOld; context->inputLineAddBuffer = NULL; fclose(infile); ppl_parserStatFree(&ps); pplcsp_checkForGvOutput(context); restore: if (context->inputLineBuffer!=NULL) free(context->inputLineBuffer); context->inputLineBuffer = oldInputLineBuffer; context->inputLineBufferLen = oldInputLineBufferLen; context->inputLineAddBuffer = oldInputLineAddBuffer; return; } int ppl_processLine(ppl_context *context, parserStatus *ps, char *in, int interactive, int iterDepth) { int i, status=0; char *inputLineBuffer = NULL; // Find last character of presently entered line. If it's a \, buffer line and collect another for (i=0; in[i]!='\0'; i++); for (; ((i>0)&&(in[i]<=' ')); i--); if (in[i]=='\\') { if (context->inputLineAddBuffer==NULL) { context->inputLineAddBuffer = (char *)malloc(i+1); if (context->inputLineAddBuffer == NULL) { ppl_error(&context->errcontext, ERR_MEMORY, -1, -1, "Out of memory whilst trying to combine input lines."); return 1; } strncpy(context->inputLineAddBuffer, in, i); context->inputLineAddBuffer[i]='\0'; } else { int j = strlen(context->inputLineAddBuffer); context->inputLineAddBuffer = (char *)realloc((void *)context->inputLineAddBuffer, j+i+1); if (context->inputLineAddBuffer == NULL) { ppl_error(&context->errcontext, ERR_MEMORY, -1, -1, "Out of memory whilst trying to combine input lines."); return 1; } strncpy(context->inputLineAddBuffer+j, in, i); context->inputLineAddBuffer[j+i]='\0'; } return 0; } // Add previous backslashed lines to the beginning of this one if (context->inputLineAddBuffer!=NULL) { int j = strlen(context->inputLineAddBuffer); context->inputLineAddBuffer = (char *)realloc((void *)context->inputLineAddBuffer, j+i+2); if (context->inputLineAddBuffer == NULL) { ppl_error(&context->errcontext, ERR_MEMORY, -1, -1, "Out of memory whilst trying to combine input lines."); return 1; } strncpy(context->inputLineAddBuffer+j, in, i+1); context->inputLineAddBuffer[j+i+1]='\0'; inputLineBuffer = context->inputLineAddBuffer; } else { inputLineBuffer = in; } #define LOOP_OVER_LINE \ { \ int bracketLevel=0; \ char quoteChar='\0'; \ for (i=0; inputLineBuffer[i]!='\0'; i++) \ { \ if ((quoteChar=='\0') && (inputLineBuffer[i]=='(') ) bracketLevel++; \ else if ((quoteChar=='\0') && (inputLineBuffer[i]==')') ) bracketLevel--; \ else if ((quoteChar=='\0') && (inputLineBuffer[i]=='\'') ) quoteChar = '\''; \ else if ((quoteChar=='\0') && (inputLineBuffer[i]=='\"') ) quoteChar = '\"'; \ else if ((quoteChar=='\'') && (inputLineBuffer[i]=='\'') && (inputLineBuffer[i-1]!='\\')) quoteChar = '\0'; \ else if ((quoteChar=='\"') && (inputLineBuffer[i]=='\"') && (inputLineBuffer[i-1]!='\\')) quoteChar = '\0'; \ else if ((quoteChar=='\0') && (inputLineBuffer[i]=='`' ) ) quoteChar = '`'; \ else if ((quoteChar=='`' ) && (inputLineBuffer[i]=='`' ) && (inputLineBuffer[i-1]!='\\')) quoteChar = '\0'; #define LOOP_END } } // Cut comments off the ends of lines LOOP_OVER_LINE else if ((quoteChar=='\0') && (inputLineBuffer[i]=='#')) break; LOOP_END inputLineBuffer[i] = '\0'; // Loop over semicolon-separated line segments LOOP_OVER_LINE else if ((quoteChar=='\0') && (bracketLevel==0) && (inputLineBuffer[i]==';')) { inputLineBuffer[i]='\0'; status = ppl_ProcessStatement(context, ps, inputLineBuffer, interactive, iterDepth); if (status) break; inputLineBuffer = inputLineBuffer+i+1; i=-1; } LOOP_END if (!status) status = ppl_ProcessStatement(context, ps, inputLineBuffer, interactive, iterDepth); if (context->inputLineAddBuffer != NULL) free(context->inputLineAddBuffer); context->inputLineAddBuffer = NULL; return (status!=0); } int ppl_ProcessStatement(ppl_context *context, parserStatus *ps, char *line, int interactive, int iterDepth) { int stat=0; ppl_tbClear(context); // If line is blank, ignore it { int i=0,j=0; for (i=0; line[i]!='\0'; i++) if (line[i]>' ') { j=1; break; } if (j==0) return 0; } stat = ppl_parserCompile(context, ps, context->errcontext.error_input_linenumber, context->errcontext.error_input_sourceId, context->errcontext.error_input_filename, line, 0, iterDepth); if ( (!stat) && (!context->errStat.status) && (ps->blockDepth==0) ) { ppl_parserExecute(context, ps->pl[iterDepth], NULL, interactive, iterDepth); } if ((iterDepth>0)&&(ps->blockDepth==0)) { ppl_parserLineFree(ps->pl[iterDepth]); ps->pl[iterDepth]=NULL; } if (stat || context->errStat.status) { if (iterDepth==0) { ppl_tbWrite(context); ppl_parserStatReInit(ps); } return 1; } return 0; } pyxplot-0.9.2/src/texify.c0000664000175000017500000006343212026340554014077 0ustar dcf21dcf21// texify.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: texify.c 1288 2012-08-11 15:11:12Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include "coreUtils/memAlloc.h" #include "mathsTools/dcfmath.h" #include "expressions/expCompile_fns.h" #include "expressions/expEval.h" #include "settings/settingTypes.h" #include "stringTools/strConstants.h" #include "stringTools/asciidouble.h" #include "userspace/context.h" #include "userspace/pplObj_fns.h" #include "userspace/unitsArithmetic.h" #include "userspace/unitsDisp.h" #include "pplConstants.h" #include "texify.h" #define FFW_TOKEN \ while ((i1)) { for (jg=0; isdigit(in[ji+jg]); jg++); if ( (jg>0) && (!isalnum(in[ji+jg])) && (in[ji+jg]!='_') ) { k=kno_; snprintf(out+k, outlen-1-k, "_{"); // We have an underscore number at the end of variable name k += strlen(out+k); for (m=ji;moutlen-16) { strcpy(out+j, "..."); j+=strlen(out+j); break; } if (in[i]=='\\') { strcpy(out+j, "$\\backslash$"); j+=strlen(out+j); } else if (in[i]=='_' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='&' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='%' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='$' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='{' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='}' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='#' ) { out[j++]='\\'; out[j++]=in[i]; } else if (in[i]=='^' ) { strcpy(out+j, "\\verb|^|"); j+=strlen(out+j); } else if (in[i]=='~' ) { strcpy(out+j, "$\\sim$"); j+=strlen(out+j); } else if (in[i]=='<' ) { strcpy(out+j, "$<$"); j+=strlen(out+j); } else if (in[i]=='>' ) { strcpy(out+j, "$>$"); j+=strlen(out+j); } else if (in[i]=='|' ) { strcpy(out+j, "$|$"); j+=strlen(out+j); } else if ((in[i]=='\"')&&((i==0)||(in[i-1]!='\\'))) { out[j++]=DoubleQuoteLevel?'\'':'`'; out[j++]=DoubleQuoteLevel?'\'':'`'; DoubleQuoteLevel=!DoubleQuoteLevel; } else if ((in[i]=='\'')&&((i==0)||(in[i-1]!='\\'))) { out[j++]=QuoteLevel?'\'':'`'; QuoteLevel=!QuoteLevel; } else { out[j++]=in[i]; } } out[j++]='\0'; return; } void ppl_texify_generic(ppl_context *c, char *in, int inlen, int *end, char *out, int outlen, int *mm_in, int *tr_in) { pplTokenCode *tokenBuff; const int allowCommaOperator = (inlen<0); const int equalsAllowed = 1; const int dollarAllowed = 1; int errPos=-1, errType, tlen; char errbuff[LSTR_LENGTH]; int *stkpos, i, k, lastOpMultDiv=0; int mm=0, tr=0; int *mathMode = (mm_in==NULL) ? &mm : mm_in; int *textRm = (tr_in==NULL) ? &tr : tr_in; #define MAX_BRACKETS 4096 int bracketLevel=0, highestBracketLevel=0, bracketOpenPos[MAX_BRACKETS]; // First tokenise expression ppl_expTokenise(c, in, end, dollarAllowed, equalsAllowed, allowCommaOperator, 0, 0, 0, &tlen, &errPos, &errType, errbuff); if (errPos>=0) { *end=0; return; } if (tlen <=0) { *end=0; return; } // Backup tokenised version tokenBuff = (pplTokenCode *)malloc(tlen * sizeof(pplTokenCode)); if (tokenBuff==NULL) { *end=0; return; } memcpy(tokenBuff, c->tokenBuff, tlen*sizeof(pplTokenCode)); if (inlen>=0) tlen = ppl_min(tlen, inlen); // Malloc buffer for storing stack positions of numerical constants stkpos = (int *)malloc(tlen*sizeof(int)); if (stkpos==NULL) { *end=0; return; } for (i=0; istackPtr; for (i=0; istackFull) { free(stkpos); free(tokenBuff); strcpy(out, "stack overflow"); return; } pplObjNum(&c->stack[k], 0, ppl_getFloat(in+i,NULL), 0); while ((tokenBuff[i].state == (unsigned char)'L') && (istackFull) { free(stkpos); free(tokenBuff); strcpy(out, "stack overflow"); return; } while ((tokenBuff[ei].state == (unsigned char)'G') && (eierrcontext.tempErrStr); if (errpos>=0) continue; if (in[upos+q]!=')') continue; ei = ei+(1+q); if (tokenBuff[ei].state != (unsigned char)'P') continue; // we don't have closing bracket ei++; while ((tokenBuff[ei].state == (unsigned char)'P') && (in[i]<=' ') && (in[i]>='\0') && (eistack[k], &val, sizeof(pplObj)); // Clean up for ( ; i=tlen)||(stkpos[ei]<0)) continue; // right argument is not literal or unit() function sp = stkpos[ei]; c->stack[sp].real*=-1; if (c->stack[sp].flagComplex) c->stack[sp].imag*=-1; for ( ; i0) && (tokenBuff[i-1].state == (unsigned char)'P') && (stkpos[i-1]>=0)) if ((in[i]=='*')&&(in[i+1]=='*')) { int ei=i, sp1, sp2, stat=0, errpos=-1; pplObj val; while ((tokenBuff[ei].state == (unsigned char)'J') && (ei=tlen)||(stkpos[ei]<0)) continue; // right argument is not a literal sp1 = stkpos[i-1]; sp2 = stkpos[ei]; val.refCount = 1; val.amMalloced = 0; pplObjNum(&val,0,0,0); ppl_uaPow(c, &c->stack[sp1], &c->stack[sp2], &val, &stat, &errpos, c->errcontext.tempErrStr); if ((stat)||(errpos>=0)) continue; memcpy(&c->stack[sp1], &val, sizeof(pplObj)); for ( ; i0) && (stkpos[i-1]>=0)) if ( ((in[i]=='*')&&(in[i+1]!='*')) || (in[i]=='/') ) { int ei=i, sp1, sp2, stat=0, errpos=-1, gotUnit; pplObj val; gotUnit = (tokenBuff[i-1].state == (unsigned char)'P'); while ((tokenBuff[ei].state == (unsigned char)'J') && (ei=tlen)||(stkpos[ei]<0)) continue; // right argument is not a literal gotUnit = gotUnit || (tokenBuff[ei].state == (unsigned char)'G'); if (!gotUnit) continue; // neither side is a unit() sp1 = stkpos[i-1]; sp2 = stkpos[ei]; val.refCount = 1; val.amMalloced = 0; pplObjNum(&val,0,0,0); if (in[i]=='*') ppl_uaMul(c, &c->stack[sp1], &c->stack[sp2], &val, &stat, &errpos, c->errcontext.tempErrStr); else ppl_uaDiv(c, &c->stack[sp1], &c->stack[sp2], &val, &stat, &errpos, c->errcontext.tempErrStr); if ((stat)||(errpos>=0)) continue; memcpy(&c->stack[sp1], &val, sizeof(pplObj)); for ( ; i=0) { double real=0, imag=0; pplObj *o = &c->stack[stkpos[i]]; char *u = NULL; if (lastOpMultDiv) u = ppl_printUnit(c, o, &real, &imag, 0, 1, SW_DISPLAY_L); if ((real!=1) || (imag!=0)) { snprintf(out+k, outlen-k, "%s", ppl_unitsNumericDisplay(c, o, 0, SW_DISPLAY_L, 0)+1); // Chop off initial $ k+=strlen(out+k)-1; // Chop off final $ out[k]='\0'; } else { snprintf(out+k, outlen-k, "%s", u); k+=strlen(out+k); } while ((i=0)) { i++; } } else if (o=='B') // Process a string literal { int ei, l; char quoteType=in[i]; for (ei=i ; ((ei1)&&(in[i+l-1]>='\0')&&(in[i+l-1]<=' ')) l--; // Strip trailing spaces if ((quoteType=='\'')||(quoteType=='\"')) { l-=2; i++; } ENTER_TEXTRM; if (quoteType=='\'') snprintf(out+k, outlen-k, "`"); else if (quoteType=='\"') snprintf(out+k, outlen-k, "``"); k+=strlen(out+k); ppl_texify_string(in+i, out+k, l, outlen-k-1); k+=strlen(out+k); if (quoteType=='\'') snprintf(out+k, outlen-k, "'"); else if (quoteType=='\"') snprintf(out+k, outlen-k, "''"); k+=strlen(out+k); ENTER_MATHMODE; i=ei; } else if (o=='C') // string substitution operator { snprintf(out+k, outlen-k, "\\%%"); k+=strlen(out+k); FFW_TOKEN; } else if ((o=='D')||(o=='E')||(o=='P')) // open or close brackets { if (in[i]=='(') { snprintf(out+k, outlen-k, "\\left( "); k+=strlen(out+k); if ((bracketLevel>=0)&&(bracketLevel highestBracketLevel) highestBracketLevel = bracketLevel; } else if (in[i]==')') { snprintf(out+k, outlen-k, "\\right) "); k+=strlen(out+k); bracketLevel--; if ((bracketLevel>=0)&&(bracketLevel='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if ((o=='G')||(o=='T')||(o=='V')) // variable name { int mathrm = (o=='T')||(o=='V'); int ei=i; while ((ei=tlen)||((tokenBuff[ei].state!='P')&&(tokenBuff[ei].state!='B'))) goto variableName; // function not called with () afterwards; int_d is followed by B, not P if ((tokenBuff[ei].state=='P')&&(in[ei]!='(')) goto variableName; ppl_dictLookupWithWildcard(c->namespaces[0],in+i,dummyVar,FNAME_LENGTH,&dptr); if (dptr==NULL) goto variableName; // function was not in the default namespace fname = dptr->key; ldptr = ppl_dictLookup(c->namespaces[c->ns_ptr], fname); if (ldptr!=NULL) goto variableName; // function redefined locally ldptr = ppl_dictLookup(c->namespaces[1 ], fname); if (ldptr!=NULL) goto variableName; // function redefined globally fnobj = (pplFunc *)((pplObj *)dptr->data)->auxil; if (fnobj==NULL) goto variableName; latex = fnobj->LaTeX; if (latex==NULL) goto variableName; // no latex model supplied // Find ( at beginning of function arguments for (bi=i; isalnum(in[bi])||(in[bi]=='_'); bi++); for ( ; (in[bi]>'\0')&&(in[bi]<=' '); bi++); if (in[bi]!='(') goto variableName; // could not find ( ppl_strBracketMatch(in+bi,'(',')',cp,&ncp,&cbp,16); // Search for a ) to match the ( if (cbp<= 0) goto variableName; // could not find ) if (ncp>=16) goto variableName; // wrong number of arguments if (dummyVar[0]=='\0') { if ((ncp< fnobj->minArgs)||(ncp>fnobj->maxArgs)) goto variableName; } // wrong number of arguments else { if (ncp!=fnobj->minArgs) goto variableName; } // Work through latex model ppl_texify_MakeGreek(dummyVar, dummyVarGreek, FNAME_LENGTH, mathMode, textRm); for (j=0; latex[j]!='\0'; j++) { if (latex[j ]!='@') snprintf(out+k, outlen-k, "%c", latex[j]); else if (latex[j+1]=='?') snprintf(out+k, outlen-k, "%s", dummyVarGreek); else if (latex[j+1]=='<') { snprintf(out+k, outlen-k, "\\left( "); k+=strlen(out+k); if ((bracketLevel>=0)&&(bracketLevel highestBracketLevel) highestBracketLevel = bracketLevel; } else if (latex[j+1]=='>') { snprintf(out+k, outlen-k, "\\right) "); k+=strlen(out+k); bracketLevel--; if ((bracketLevel>=0)&&(bracketLevel='1')&&(latex[j+1]<='6')) { int l=(latex[j+1]-'1'), end; ppl_texify_generic(c, in+bi+cp[l]+1, cp[l+1]-cp[l]-1, &end, out+k, outlen-k, mathMode, textRm); k+=strlen(out+k); } else if (latex[j+1]=='0') { int a, end; for (a=0; a='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='J') // a binary operator { if (MARKUP_MATCH("**" )) { snprintf(out+k, outlen-k, "\\,*\\kern-1.5pt *\\,\\,"); FFW_N(2); } else if (MARKUP_MATCH("<<" )) { snprintf(out+k, outlen-k, "\\ll "); FFW_N(2); } else if (MARKUP_MATCH(">>" )) { snprintf(out+k, outlen-k, "\\gg "); FFW_N(2); } else if (MARKUP_MATCH("<=" )) { snprintf(out+k, outlen-k, "\\leq "); FFW_N(2); } else if (MARKUP_MATCH(">=" )) { snprintf(out+k, outlen-k, "\\geq "); FFW_N(2); } else if (MARKUP_MATCH("==" )) { snprintf(out+k, outlen-k, "=="); FFW_N(2); } else if (MARKUP_MATCH("<>" )) { snprintf(out+k, outlen-k, "<>"); FFW_N(2); } else if (MARKUP_MATCH("!=" )) { snprintf(out+k, outlen-k, "!="); FFW_N(2); } else if (MARKUP_MATCH("&&" )) { ENTER_TEXTRM; snprintf(out+k, outlen-k, "\\,\\&\\&\\,"); FFW_N(2); } else if (MARKUP_MATCH("and")) { ENTER_TEXTRM; snprintf(out+k, outlen-k, " and "); FFW_N(3); } else if (MARKUP_MATCH("AND")) { ENTER_TEXTRM; snprintf(out+k, outlen-k, " and "); FFW_N(3); } else if (MARKUP_MATCH("||" )) { snprintf(out+k, outlen-k, "\\,||\\,"); FFW_N(2); } else if (MARKUP_MATCH("or" )) { ENTER_TEXTRM; snprintf(out+k, outlen-k, " or "); FFW_N(2); } else if (MARKUP_MATCH("OR" )) { ENTER_TEXTRM; snprintf(out+k, outlen-k, " or "); FFW_N(2); } else if (MARKUP_MATCH("*" )) { snprintf(out+k, outlen-k, "\\times "); FFW_N(1); opMultDiv=1; } else if (MARKUP_MATCH("/" )) { snprintf(out+k, outlen-k, "/"); FFW_N(1); opMultDiv=1; } else if (MARKUP_MATCH("%" )) { ENTER_TEXTRM; snprintf(out+k, outlen-k, "\\%%"); FFW_N(1); } else if (MARKUP_MATCH("+" )) { snprintf(out+k, outlen-k, "+"); FFW_N(1); } else if (MARKUP_MATCH("-" )) { snprintf(out+k, outlen-k, "-"); FFW_N(1); } else if (MARKUP_MATCH("<" )) { snprintf(out+k, outlen-k, "<"); FFW_N(1); } else if (MARKUP_MATCH(">" )) { snprintf(out+k, outlen-k, ">"); FFW_N(1); } else if (MARKUP_MATCH("&" )) { ENTER_TEXTRM; snprintf(out+k, outlen-k, "\\,\\&\\,"); FFW_N(1); } else if (MARKUP_MATCH("^" )) { snprintf(out+k, outlen-k, "\\verb|^|"); FFW_N(1); } else if (MARKUP_MATCH("|" )) { snprintf(out+k, outlen-k, "\\,|\\,"); FFW_N(1); } else if (MARKUP_MATCH("," )) { snprintf(out+k, outlen-k, ","); FFW_N(1); } k+=strlen(out+k); while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='K') // a terniary operator { if (MARKUP_MATCH("?")) { snprintf(out+k, outlen-k, "\\,?\\,"); FFW_N(1); } else if (MARKUP_MATCH(":")) { snprintf(out+k, outlen-k, ":"); FFW_N(1); } k+=strlen(out+k); while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if ((o=='M')||(o=='Q')) // list literal { if (in[i]=='[') snprintf(out+k, outlen-k, "\\left["); if (in[i]==']') snprintf(out+k, outlen-k, "\\right]"); k+=strlen(out+k); i++; while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='N') // dictionary literal { if (in[i]=='{') snprintf(out+k, outlen-k, "\\left\\{"); if (in[i]=='}') snprintf(out+k, outlen-k, "\\right\\}"); k+=strlen(out+k); i++; while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='O') // dollar operator { if (in[i]=='$') snprintf(out+k, outlen-k, "\\$"); k+=strlen(out+k); i++; while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='R') // dot operator { if (in[i]=='.') snprintf(out+k, outlen-k, "."); k+=strlen(out+k); i++; while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else if (o=='S') // assignment operator { if (MARKUP_MATCH("=" )) { snprintf(out+k, outlen-k, "="); FFW_N(1); } else if (MARKUP_MATCH("+=" )) { snprintf(out+k, outlen-k, "\\,\\,+\\kern-2.5pt ="); FFW_N(2); } else if (MARKUP_MATCH("-=" )) { snprintf(out+k, outlen-k, "\\,\\,-\\kern-2.5pt ="); FFW_N(2); } else if (MARKUP_MATCH("*=" )) { snprintf(out+k, outlen-k, "\\,\\,\\times\\kern-2.5pt ="); FFW_N(2); } else if (MARKUP_MATCH("/=" )) { snprintf(out+k, outlen-k, "\\,/\\kern-1.5pt ="); FFW_N(2); } else if (MARKUP_MATCH("%=" )) { snprintf(out+k, outlen-k, "\\,\\,\\textrm{\\%%}\\kern-2pt ="); FFW_N(2); } else if (MARKUP_MATCH("&=" )) { snprintf(out+k, outlen-k, "\\,\\,\\textrm{\\&}\\kern-2pt ="); FFW_N(2); } else if (MARKUP_MATCH("^=" )) { snprintf(out+k, outlen-k, "\\,\\,\\verb|^|\\kern-2pt ="); FFW_N(2); } else if (MARKUP_MATCH("|=" )) { snprintf(out+k, outlen-k, "\\,\\,|\\kern-2.3pt ="); FFW_N(2); } else if (MARKUP_MATCH("<<=")) { snprintf(out+k, outlen-k, "\\ll="); FFW_N(3); } else if (MARKUP_MATCH(">>=")) { snprintf(out+k, outlen-k, "\\gg="); FFW_N(3); } else if (MARKUP_MATCH("**=")) { snprintf(out+k, outlen-k, "\\,*\\kern-1.5pt *\\kern-1.5pt="); FFW_N(3); } k+=strlen(out+k); while ((in[i]>='\0')&&(in[i]<=' ')&&(tokenBuff[i].state==o)) { FFW_N(1); } } else // unknown token { FFW_TOKEN; } lastOpMultDiv = opMultDiv; } if (inlen<0) { ENTER_PLAINTEXT; } out[k]='\0'; free(stkpos); free(tokenBuff); return; } pyxplot-0.9.2/src/readConf.h0000664000175000017500000000162712026340554014313 0ustar dcf21dcf21// readConf.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: readConf.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _READCONF_H #define _READCONF_H 1 #include "userspace/context.h" void ppl_readconfig(ppl_context *c); #endif pyxplot-0.9.2/src/children.c0000664000175000017500000006332612026340554014361 0ustar dcf21dcf21// children.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: children.c 1284 2012-08-06 23:19:26Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include #include #include #include #include "stringTools/asciidouble.h" #include "stringTools/strConstants.h" #include "coreUtils/memAlloc.h" #include "coreUtils/errorReport.h" #include "settings/settingTypes.h" #include "children.h" // Pipes for communication between the main Pyxplot process and the CSP int PipeCSP2MAIN[2]={0,0}; int PipeMAIN2CSP[2]={0,0}; char PipeOutputBuffer[LSTR_LENGTH] = ""; static char SIGTERM_NAME[16]; // The name of SIGTERM, which we filter out from GV's output, as it tends to whinge about being killed. static ppl_context *static_context; // Flags used to keep track of all of the open GhostView processes #define PTABLE_LISTLEN 4096 static int *GhostViews; // A list of X11_multiwindow and X11_singlewindow sessions which we kill on Pyxplot exit static int *GhostView_Persists; // A list of X11_persist sessions for which we leave our temporary directory until they quit static int *HelperPIDs; // A list of helper processes forked by the main Pyxplot process static int GhostView_pid = 0; // pid of any running gv process launched under X11_singlewindow static int PyxplotRunning = 1; // Flag which we drop in the CSP when the main process stops running // Functions to be called from main Pyxplot process void pplcsp_init(ppl_context *context) { int pid, fail, i; struct stat statinfo; // Create empty lists for storing lists of GhostView processes GhostViews = (int *)malloc(PTABLE_LISTLEN*sizeof(int)); GhostView_Persists = (int *)malloc(PTABLE_LISTLEN*sizeof(int)); HelperPIDs = (int *)malloc(PTABLE_LISTLEN*sizeof(int)); static_context = context; if ((GhostViews==NULL)||(GhostView_Persists==NULL)||(HelperPIDs==NULL)) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Out of memory."); for (i=0; ierrcontext,__FILE__,__LINE__,"Could not create a pipe."); if (pipe(PipeMAIN2CSP) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not create a pipe."); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for the CSP."); else if ( pid != 0) { close(PipeMAIN2CSP[0]); // Parent process; close CSP's ends of pipes //close(PipeCSP2MAIN[1]); // Leave this pipe open so that sed can return error messages down it if (signal(SIGCHLD, pplcsp_checkForHelperExits) == SIG_ERR) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Main process could not set up a signal handler for SIGCHLD."); return; // Parent process returns } // Close main process's ends of the pipes close(PipeCSP2MAIN[0]); close(PipeMAIN2CSP[1]); // Make all log messages appear to come from the CSP sprintf(context->errcontext.error_source, "CSP%6d", getpid()); signal(SIGINT, SIG_IGN); // Ignore SIGINT if (setpgid( getpid() , getpid() ) < 0) if (DEBUG) ppl_log(&context->errcontext,"Failed to set process group ID."); // Make into a process group leader so that we won't catch SIGINT // Make temporary working directory fail=0; if ((mkdir(context->errcontext.session_default.tempdir , 0700) != 0) || // Create temporary working directory (access(context->errcontext.session_default.tempdir, F_OK) != 0) ) { fail=1; } // If temporary directory does not exist, fail. else { if (stat(context->errcontext.session_default.tempdir, &statinfo) <0) fail=1; // Otherwise stat it and make sure it's a directory we own if (!S_ISDIR(statinfo.st_mode)) fail=1; if (statinfo.st_uid != getuid()) fail=1; } if (fail==1) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Failed to create temporary directory." ); } if (chdir(context->errcontext.session_default.tempdir) < 0) { ppl_fatal(&context->errcontext,__FILE__,__LINE__,"chdir into temporary directory failed."); } // chdir into temporary directory // Enter CSP execution loop if (signal(SIGCHLD, pplcsp_checkForChildExits) == SIG_ERR) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"CSP could not set up a signal handler for SIGCHLD."); pplcsp_main(context); close(PipeCSP2MAIN[1]); // Close pipes close(PipeMAIN2CSP[0]); if (chdir("/") < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"chdir out of temporary directory failed."); // chdir out of temporary directory sprintf(PipeOutputBuffer, "rm -Rf %s", context->errcontext.session_default.tempdir); if (system(PipeOutputBuffer) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Removal of temporary directory failed."); // Remove temporary directory ppl_memAlloc_FreeAll(0); if (DEBUG) ppl_log(&context->errcontext,"CSP terminating normally."); exit(0); } void pplcsp_checkForGvOutput(ppl_context *context) { struct timespec waitperiod; // A time.h timespec specifier for a wait of zero seconds fd_set readable; int pos, TrialNumber; char linebuffer[SSTR_LENGTH]; TrialNumber=1; while (1) { waitperiod.tv_sec = waitperiod.tv_nsec = 0; FD_ZERO(&readable); FD_SET(PipeCSP2MAIN[0], &readable); if (pselect(PipeCSP2MAIN[0]+1, &readable, NULL, NULL, &waitperiod, NULL) == -1) { if ((errno==EINTR) && (TrialNumber<3)) { TrialNumber++; continue; } if (DEBUG) ppl_log(&context->errcontext,"pselect failure whilst checking for GV output"); return; } break; } if (!FD_ISSET(PipeCSP2MAIN[0] , &readable)) return; // select tells us that pipe from CSP is not readable pos = strlen(PipeOutputBuffer); if (read(PipeCSP2MAIN[0], PipeOutputBuffer+pos, LSTR_LENGTH-pos-5) > 0) while (PipeOutputBuffer[0]!='\0') { ppl_strRemoveCompleteLine(PipeOutputBuffer, linebuffer); if (linebuffer[0]=='\0') continue; if (strstr(linebuffer, SIGTERM_NAME)!=NULL) continue; if (strncmp(linebuffer, SED_COMMAND, strlen(SED_COMMAND))==0) ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, "A problem was encounter with the supplied regular expression."); else ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, linebuffer); } return; } void pplcsp_sendCommand(ppl_context *context, char *cmd) { if (PipeMAIN2CSP[1]==0) return; // Pipe has not yet been opened (Ooops). if (write(PipeMAIN2CSP[1], cmd, strlen(cmd)) != strlen(cmd)) ppl_error(&context->errcontext,ERR_INTERNAL, -1, -1, "Attempt to send a message to the CSP failed."); return; } // Functions to be called from the Child Support Process void pplcsp_main(ppl_context *context) { int gotPersists=1; while (gotPersists) { struct timespec waitperiod, waitedperiod; waitperiod.tv_sec = 0; waitperiod.tv_nsec = PyxplotRunning ? 100000000 : 500000000; // After pyxplot has quit, reduce polling rate to twice a second. Why not? nanosleep(&waitperiod,&waitedperiod); // Wake up every 100ms pplcsp_checkForNewCommands(context); // Check for orders from Pyxplot if (PyxplotRunning && (getppid()==1)) // We've been orphaned and adopted by init { PyxplotRunning=0; if (DEBUG) ppl_log(&context->errcontext,"CSP has detected that it has been orphaned."); } gotPersists=0; if (PyxplotRunning) gotPersists=1; else { int i; for (i=0; ierrcontext,errtext); } GhostViews[i]=0; // Stabat mater dolorosa if (GhostView_pid == gv_pid) GhostView_pid = 0; } } for (i=0; ierrcontext,errtext); } GhostView_Persists[i]=0; // Stabat mater dolorosa if (GhostView_pid == gv_pid) GhostView_pid = 0; } } return; } void pplcsp_checkForNewCommands(ppl_context *context) { struct timespec waitperiod; // A time.h timespec specifier for a wait of zero seconds fd_set readable; int pos, TrialNumber; char linebuffer[SSTR_LENGTH]; TrialNumber=1; while (1) { waitperiod.tv_sec = waitperiod.tv_nsec = 0; FD_ZERO(&readable); FD_SET(PipeMAIN2CSP[0], &readable); if (pselect(PipeMAIN2CSP[0]+1, &readable, NULL, NULL, &waitperiod, NULL) == -1) { if ((errno==EINTR) && (TrialNumber<3)) { TrialNumber++; continue; } if (DEBUG) ppl_log(&context->errcontext,"pselect failure whilst CSP checking for new commands"); return; } break; } if (!FD_ISSET(PipeMAIN2CSP[0] , &readable)) return; // select tells us that pipe from main process is not readable pos = strlen(PipeOutputBuffer); if (read(PipeMAIN2CSP[0], PipeOutputBuffer+pos, LSTR_LENGTH-pos-5) > 0) while (1) { ppl_strRemoveCompleteLine(PipeOutputBuffer, linebuffer); if (linebuffer[0]=='\0') break; pplcsp_processCommand(context, linebuffer); } return; } void pplcsp_processCommand(ppl_context *context, char *in) { char cmd[FNAME_LENGTH]; if (in[0]=='\0') return; else if (in[0]=='A') // clear command executed { if (DEBUG) ppl_log(&context->errcontext,"Received request to clear display."); pplcsp_killLatestSinglewindow(context); } else if (in[0]=='B') // Pyxplot quit { if (DEBUG) ppl_log(&context->errcontext,"Received notice that Pyxplot is quitting."); pplcsp_killAllGvs(context); PyxplotRunning=0; } else if (in[0]=='0') // gv_singlewindow { // Pick out filename of eps file to display, which is last command-line argument int state=0,i; char *filename=in+1; for (i=1; in[i]!='\0'; i++) if ( ((in[i]>' ')||(in[i]<'\0')) || ((i>1)&&(in[i-1]=='\\')) ) { if (!state) { filename = in+i; state=1; } // New word } else state=0; if (GhostView_pid > 1) { if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Received gv_singlewindow request. Putting into existing window with pid %d.", GhostView_pid); ppl_log(&context->errcontext,NULL); } sprintf(cmd, "cp -f %s %s", filename, context->pplcsp_ghostView_fname); if (system(cmd) != 0) if (DEBUG) { ppl_log(&context->errcontext,"Failed to copy postscript document into existing gv_singlewindow session.");} } else { if (DEBUG) ppl_log(&context->errcontext,"Received gv_singlewindow request. Making a new window for it."); strcpy(context->pplcsp_ghostView_fname, filename); GhostView_pid = pplcsp_forkNewGv(context, in+1, GhostViews); } } else if (in[0]=='1') // gv_multiwindow { if (DEBUG) ppl_log(&context->errcontext,"Received gv_multiwindow request."); pplcsp_forkNewGv(context, in+1, GhostViews); } else if (in[0]=='2') // gv_persist { if (DEBUG) ppl_log(&context->errcontext,"Received gv_persist request."); pplcsp_forkNewGv(context, in+1, GhostView_Persists); } return; } int pplcsp_forkNewGv(ppl_context *context, char *fname, int *gv_list) { #define MAX_CMDARGS 64 int pid, i, state=0, NArgs=0; char *Args[MAX_CMDARGS], ViewerApp[FNAME_LENGTH]; sigset_t sigs; // Split up command line into words for (i=0; fname[i]!='\0'; i++) { if ( ((fname[i]>' ')||(fname[i]<'\0')) || ((i>1)&&(fname[i-1]=='\\')) ) { if (state) {} // In the middle of a word... keep going else { Args[NArgs++] = fname+i; state=1; } // New word } else { if (state) { fname[i]='\0'; state=0; } // End of word else {} // Lots of whitespace } if (NArgs==MAX_CMDARGS) { FILE *f = fdopen(PipeCSP2MAIN[1], "w"); if (f==NULL) return 0; fprintf(f, "Command for launching postscript viewer contains too many command-line switches.\n"); fclose(f); return 0; } } Args[NArgs]=NULL; snprintf(ViewerApp, FNAME_LENGTH, "%s", Args[0]); ViewerApp[FNAME_LENGTH-1]='\0'; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); sigprocmask(SIG_BLOCK, &sigs, NULL); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for the CSP."); else if ( pid != 0) { // Parent process (i.e. the CSP) int i; for (i=0; ierrcontext.error_source, "GV%7d", getpid()); context->errcontext.session_default.color = SW_ONOFF_OFF; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "New postscript viewer process alive; going to view %s.", fname); ppl_log(&context->errcontext,NULL); } if (PipeCSP2MAIN[1] != STDERR_FILENO) // Redirect stderr to pipe, so that GhostView doesn't spam terminal { if (dup2(PipeCSP2MAIN[1], STDERR_FILENO) != STDERR_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stderr to pipe."); close(PipeCSP2MAIN[1]); } if (setpgid( getpid() , getpid() )) if (DEBUG) ppl_log(&context->errcontext,"Failed to set process group ID."); // Make into a process group leader so that we won't catch SIGINT // Run postscript viewer if (execvp(Args[0],Args)!=0) { if (DEBUG) ppl_log(&context->errcontext,"Attempt to execute postscript viewer returned error code."); } // Execute postscript viewer fprintf(stderr, "Execution of postscript viewer '%s' failed.\n", ViewerApp); fflush(stderr); // execvp call should not return exit(1); } return 0; } void pplcsp_killAllGvs(ppl_context *context) { int i; if (DEBUG) ppl_log(&context->errcontext,"Killing all ghostview processes."); for (i=0; i 1) { if (DEBUG) { sprintf(context->errcontext.tempErrStr, "Killing latest ghostview singlewindow process with pid %d.", GhostView_pid); ppl_log(&context->errcontext,NULL); } kill(GhostView_pid, SIGTERM); } else { if (DEBUG) { sprintf(context->errcontext.tempErrStr, "No ghostview singlewindow process to kill."); ppl_log(&context->errcontext,NULL); } } GhostView_pid = 0; return; } // Facilities for forking helper processes with pipes from the main Pyxplot process void pplcsp_checkForHelperExits(int signo) { int i; char errtext[256]; ppl_context *context = static_context; for (i=0; ierrcontext,errtext); } HelperPIDs[i]=0; // Stabat mater dolorosa } } return; } void pplcsp_killAllHelpers(ppl_context *context) { int i; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); sigprocmask(SIG_BLOCK, &sigs, NULL); for (i=0; ierrcontext,__FILE__,__LINE__,"Could not open required pipes."); sigprocmask(SIG_BLOCK, &sigs, NULL); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for sed process."); else if ( pid != 0) { // Parent process close(fd0[0]); *fstdin = fd0[1]; close(fd1[1]); *fstdout = fd1[0]; for (i=0; ierrcontext.error_source, "SED%6d", getpid()); context->errcontext.session_default.color = SW_ONOFF_OFF; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "New sed process alive; going to run command \"%s\".", cmd); ppl_log(&context->errcontext,NULL); } if (fd0[0] != STDIN_FILENO) // Redirect stdin to pipe { if (dup2(fd0[0], STDIN_FILENO) != STDIN_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdin to pipe."); close(fd0[0]); } if (fd1[1] != STDOUT_FILENO) // Redirect stdout to pipe { if (dup2(fd1[1], STDOUT_FILENO) != STDOUT_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdout to pipe."); close(fd1[1]); } if (PipeCSP2MAIN[1] != STDERR_FILENO) // Redirect stderr to pipe { if (dup2(PipeCSP2MAIN[1], STDERR_FILENO) != STDERR_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stderr to pipe."); close(PipeCSP2MAIN[1]); } if (execl(SED_COMMAND, SED_COMMAND, cmd, NULL)!=0) if (DEBUG) ppl_log(&context->errcontext,"Attempt to execute sed returned error code."); // Execute sed ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, "Execution of helper process 'sed' failed."); // execlp call should not return exit(1); } return; } // NB: Leaves SIGCHLD blocked void pplcsp_forkLaTeX(ppl_context *context, char *filename, int *PidOut, int *fstdin, int *fstdout) { int fd0[2], fd1[2]; int i,pid; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); if ((pipe(fd0)<0) || (pipe(fd1)<0)) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not open required pipes."); sigprocmask(SIG_BLOCK, &sigs, NULL); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for latex process."); else if ( pid != 0) { // Parent process close(fd0[0]); *fstdin = fd0[1]; close(fd1[1]); *fstdout = fd1[0]; *PidOut = pid; for (i=0; ierrcontext.error_source, "TEX%6d", getpid()); context->errcontext.session_default.color = SW_ONOFF_OFF; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "New latex process alive; going to latex file \"%s\".", filename); ppl_log(&context->errcontext,NULL); } if (fd0[0] != STDIN_FILENO) // Redirect stdin to pipe { if (dup2(fd0[0], STDIN_FILENO) != STDIN_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdin to pipe."); close(fd0[0]); } if (fd1[1] != STDOUT_FILENO) // Redirect stdout to pipe { if (dup2(fd1[1], STDOUT_FILENO) != STDOUT_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdout to pipe."); } if (PipeCSP2MAIN[1] != STDERR_FILENO) // Redirect stderr to pipe { if (dup2(fd1[1], STDERR_FILENO) != STDERR_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stderr to pipe."); close(fd1[1]); } if (execl(LATEX_COMMAND, LATEX_COMMAND, "-file-line-error", filename, NULL)!=0) if (DEBUG) ppl_log(&context->errcontext,"Attempt to execute latex returned error code."); // Execute latex ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, "Execution of helper process 'latex' failed."); // execlp call should not return exit(1); } return; } // NB: Leaves SIGCHLD blocked void pplcsp_forkInputFilter(ppl_context *context, char **cmd, int *fstdout) { int fd0[2]; int i,pid; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); if (pipe(fd0)<0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not open required pipes."); sigprocmask(SIG_BLOCK, &sigs, NULL); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for input filter process."); else if ( pid != 0) { // Parent process close(fd0[1]); *fstdout = fd0[0]; for (i=0; ierrcontext.error_source, "IF %6d", getpid()); context->errcontext.session_default.color = SW_ONOFF_OFF; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "New input filter process alive; going to run command \"%s\".", cmd[0]); ppl_log(&context->errcontext,NULL); } if (fd0[1] != STDOUT_FILENO) // Redirect stdout to pipe { if (dup2(fd0[1], STDOUT_FILENO) != STDOUT_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdout to pipe."); close(fd0[1]); } if (PipeCSP2MAIN[1] != STDERR_FILENO) // Redirect stderr to pipe { if (dup2(PipeCSP2MAIN[1], STDERR_FILENO) != STDERR_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stderr to pipe."); close(PipeCSP2MAIN[1]); } if (execvp(cmd[0], cmd)!=0) if (DEBUG) ppl_log(&context->errcontext,"Attempt to execute input filter returned error code."); // Execute input filter sprintf(context->errcontext.tempErrStr, "Execution of input filter '%s' failed.", cmd[0]); ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, NULL); // execvp call should not return exit(1); } return; } // NB: Leaves SIGCHLD blocked void pplcsp_forkKpseWhich(ppl_context *context, const char *ftype, int *fstdout) { char CmdLineOpt[128]; int fd0[2]; int i,pid; sigset_t sigs; sigemptyset(&sigs); sigaddset(&sigs,SIGCHLD); if (pipe(fd0)<0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not open required pipes."); sigprocmask(SIG_BLOCK, &sigs, NULL); if ((pid=fork()) < 0) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not fork a child process for kpsewhich process."); else if ( pid != 0) { // Parent process close(fd0[1]); *fstdout = fd0[0]; for (i=0; ierrcontext.error_source, "KPS%6d", getpid()); context->errcontext.session_default.color = SW_ONOFF_OFF; if (DEBUG) { sprintf(context->errcontext.tempErrStr, "New kpsewhich process alive; going to get paths for filetype \"%s\".", ftype); ppl_log(&context->errcontext,NULL); } if (fd0[1] != STDOUT_FILENO) // Redirect stdout to pipe { if (dup2(fd0[1], STDOUT_FILENO) != STDOUT_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stdout to pipe."); close(fd0[1]); } if (PipeCSP2MAIN[1] != STDERR_FILENO) // Redirect stderr to pipe { if (dup2(PipeCSP2MAIN[1], STDERR_FILENO) != STDERR_FILENO) ppl_fatal(&context->errcontext,__FILE__,__LINE__,"Could not redirect stderr to pipe."); close(PipeCSP2MAIN[1]); } sprintf(CmdLineOpt, "-show-path=.%s", ftype); if (execl(KPSE_COMMAND, KPSE_COMMAND, CmdLineOpt, NULL)!=0) if (DEBUG) ppl_log(&context->errcontext,"Attempt to execute kpsewhich returned error code."); // Execute kpsewhich ppl_error(&context->errcontext,ERR_GENERIC, -1, -1, "Execution of helper process 'kpsewhich' failed."); // execlp call should not return exit(1); } return; } pyxplot-0.9.2/src/input.h0000664000175000017500000000242612026340554013727 0ustar dcf21dcf21// input.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: input.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _INPUT_H #define _INPUT_H 1 #include "parser/parser.h" #include "userspace/context.h" int ppl_inputInit (ppl_context *context); void ppl_interactiveSession(ppl_context *context); void ppl_processScript (ppl_context *context, char *input, int iterDepth); int ppl_processLine (ppl_context *context, parserStatus *ps, char *in, int interactive, int iterDepth); int ppl_ProcessStatement (ppl_context *context, parserStatus *ps, char *line, int interactive, int iterDepth); #endif pyxplot-0.9.2/src/stringTools/0000775000175000017500000000000012026340554014742 5ustar dcf21dcf21pyxplot-0.9.2/src/stringTools/asciidouble.h0000664000175000017500000000463312026340554017404 0ustar dcf21dcf21// asciidouble.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: asciidouble.h 1273 2012-07-20 00:18:37Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _ASCIIDOUBLE_H #define _ASCIIDOUBLE_H 1 #include unsigned char ppl_dblEqual(double a, double b); unsigned char ppl_dblApprox(double a, double b, double err); double ppl_getFloat (const char *str, int *Nchars); int ppl_validFloat (const char *str, int *end); char *ppl_numericDisplay (double in, char *output, int SigFig, int latex); void ppl_file_readline (FILE *file, char **output, int *MaxLenPtr, int MaxLength); void ppl_getWord (char *out, const char *in, int max); char *ppl_nextWord (char *in); char *ppl_friendlyTimestring (); char *ppl_strStrip (const char *in, char *out); char *ppl_strUpper (const char *in, char *out); char *ppl_strLower (const char *in, char *out); char *ppl_strUnderline (const char *in, char *out); char *ppl_strRemoveCompleteLine (char *in, char *out); char *ppl_strSlice (const char *in, char *out, int start, int end); char *ppl_strCommaSeparatedListScan(char **inscan, char *out); int ppl_strAutocomplete (const char *candidate, char *test, int Nmin); void ppl_strWordWrap (const char *in, char *out, int width); void ppl_strBracketMatch (const char *in, char open, char close, int *CommaPositions, int *Nargs, int *ClosingBracketPos, int MaxCommaPoses); int ppl_strCmpNoCase (const char *a, const char *b); char *ppl_strEscapify (const char *in, char *out); int ppl_strWildcardTest (const char *test, const char *wildcard); #endif pyxplot-0.9.2/src/stringTools/strConstants.h0000664000175000017500000000171212026340554017621 0ustar dcf21dcf21// strConstants.h // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: strConstants.h 1261 2012-07-11 21:38:05Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #ifndef _STRCONSTANTS_H #define _STRCONSTANTS_H 1 #define LSTR_LENGTH 32768 #define FNAME_LENGTH 4096 #define SSTR_LENGTH 2048 #define STR_MARGIN 32 #endif pyxplot-0.9.2/src/stringTools/asciidouble.c0000664000175000017500000005136612026340554017404 0ustar dcf21dcf21// asciidouble.c // // The code in this file is part of Pyxplot // // // Copyright (C) 2006-2012 Dominic Ford // 2008-2012 Ross Church // // $Id: asciidouble.c 1273 2012-07-20 00:18:37Z dcf21 $ // // Pyxplot 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. // // You should have received a copy of the GNU General Public License along with // Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin // Street, Fifth Floor, Boston, MA 02110-1301, USA // ---------------------------------------------------------------------------- #include #include #include #include #include #include #include "settings/settings.h" #include /* ppl_getFloat(): This gets a float from a string */ double ppl_getFloat(const char *str, int *Nchars) { double accumulator = 0; int decimals = 0; unsigned char past_decimal_point = 0; unsigned char negative = 0; int pos = 0; int pos2= 0; if ((str[pos+0]=='n') && (str[pos+1]=='a') && (str[pos+2]=='n') && (str[pos+3]>='\0') && (str[pos+3]<=' ')) { if (Nchars!=NULL) *Nchars=3; return GSL_NAN; } if ((str[pos+0]=='N') && (str[pos+1]=='A') && (str[pos+2]=='N') && (str[pos+3]>='\0') && (str[pos+3]<=' ')) { if (Nchars!=NULL) *Nchars=3; return GSL_NAN; } if (str[pos] == '-') { negative = 1; pos++; } // Deal with negatives else if (str[pos] == '+') { pos++; } // Deal with e.g. 1E+09 if ((str[pos+0]=='0') && (str[pos+1]=='x')) // Hexadecimal { pos+=2; while (1) { if ((str[pos]>='0') && (str[pos]<='9')) accumulator = ((16 * accumulator) + (((int)str[pos])-48)); else if ((str[pos]>='A') && (str[pos]<='F')) accumulator = ((16 * accumulator) + (((int)str[pos])-55)); else if ((str[pos]>='a') && (str[pos]<='f')) accumulator = ((16 * accumulator) + (((int)str[pos])-87)); else break; pos++; } if (negative == 1) accumulator *= -1; // Deal with negatives } else { while (((str[pos]>='0') && (str[pos]<='9')) || (str[pos] == '.')) { if (str[pos] == '.') { past_decimal_point = 1; } else { accumulator = ((10 * accumulator) + (((int)str[pos])-48)); if (past_decimal_point == 1) decimals++; } pos++; } while (decimals != 0) // Deals with decimals { decimals--; accumulator /= 10; } if (negative == 1) accumulator *= -1; // Deals with negatives if ((str[pos] == 'e') || (str[pos] == 'E')) accumulator *= pow(10.0,ppl_getFloat(str+pos+1 , &pos2)); /* Deals with exponents */ if (pos2 > 0) pos += (1+pos2); // Add on characters taken up by exponent, including one for the 'e' character. } if (pos == 0) pos = -1; // Alert the user that this was a blank string! if (Nchars != NULL) *Nchars = pos; return(accumulator); } /* ppl_validFloat(): Sees whether candidate string is a valid float */ int ppl_validFloat(const char *str, int *end) { unsigned char past_decimal_point=0, had_number=0, expvalid=1; int pos = 0; int pos2= 0; if ((str[pos+0]=='n') && (str[pos+1]=='a') && (str[pos+2]=='n') && (str[pos+3]>='\0') && (str[pos+3]<=' ')) { pos+=3; had_number=1; goto VALID_FLOAT_ENDED; } if ((str[pos+0]=='N') && (str[pos+1]=='A') && (str[pos+2]=='N') && (str[pos+3]>='\0') && (str[pos+3]<=' ')) { pos+=3; had_number=1; goto VALID_FLOAT_ENDED; } if (str[pos] == '-') { pos++; } /* Deal with negatives */ else if (str[pos] == '+') { pos++; } /* Deal with e.g. 1E+09 */ if ((str[pos+0]=='0') && (str[pos+1]=='x')) // Hexadecimal { pos+=2; while (1) { if ((str[pos]>='0') && (str[pos]<='9')) pos++; else if ((str[pos]>='A') && (str[pos]<='F')) pos++; else if ((str[pos]>='a') && (str[pos]<='f')) pos++; else break; had_number = 1; } if (!had_number) return 0; } else { while (((str[pos]>='0') && (str[pos]<='9')) || (str[pos] == '.')) { if (str[pos] == '.') { if (past_decimal_point) goto VALID_FLOAT_ENDED; else past_decimal_point = 1; } else { had_number = 1; } pos++; } if (!had_number) return 0; if ((str[pos] == 'e') || (str[pos] == 'E')) /* Deals with exponents */ { expvalid = ppl_validFloat(str+pos+1 , &pos2); pos += pos2+1; } } VALID_FLOAT_ENDED: while ((str[pos]!='\0')&&(str[pos]<=' ')) pos++; /* Fast-forward over spaces at end */ if ((!had_number)||(!expvalid)) return 0; if (end==NULL) return 1; if ((*end>=0)&&(pos<*end)) return 0; *end = pos; return 1; } /* ppl_numericDisplay(): Displays a double in either %f or %e formats */ char *ppl_numericDisplay(double in, char *output, int SigFig, int latex) { char format[16]; double x, AccLevel; int DecimalLevel, DPmax, i, j, k, l; if ((fabs(in) < 1e10) && (fabs(in) > 1e-3)) { x = fabs(in); AccLevel = x*(1.0+pow(10,-SigFig)); DPmax = SigFig-log10(x); for (DecimalLevel=0; DecimalLevel'0')&&(output[j]<='9')) l=1; if ((l==1)||(output[j]!='0')) output[i++]=output[j]; } // Turn -08 into -8 output[i++]='}'; output[i++]='\0'; } } } } for (i=0; ((output[i]!='\0')&&(output[i]!='.')); i++); // If we have trailing decimal zeros, get rid of them if (output[i]!='.') return output; for (j=i+1; isdigit(output[j]); j++); if (i==j) return output; for (k=j-1; output[k]=='0'; k--); if (k==i) k--; k++; if (k==j) return output; for (l=0; output[j+l]!='\0'; l++) output[k+l] = output[j+l]; output[k+l]='\0'; return output; } // Useful function for checking whether two doubles are roughly equal to one another unsigned char ppl_dblEqual(double a, double b) { if ( (fabs(a) < 1e-100) && (fabs(b) < 1e-100) ) return 1; if ( (fabs(a-b) > fabs(1e-7*a)) || (fabs(a-b) > fabs(1e-7*b)) ) return 0; return 1; } unsigned char ppl_dblApprox(double a, double b, double err) { if ( fabs(a-b) > (fabs(err)+1e-50) ) return 0; return 1; } /* ppl_file_readline(): This remarkably useful function forwards a file to the next newline */ void ppl_file_readline(FILE *file, char **output, int *MaxLenPtr, int MaxLength) { char c = '\x07'; int i=0; if (MaxLenPtr != NULL) { MaxLength = *MaxLenPtr; while (((int)c != '\n') && (!feof(file)) && (!ferror(file))) { if (cancellationFlag) break; if (i>MaxLength-4) { char *new = realloc(*output, MaxLength*=2); if (new==NULL) break; *output=new; } if ( (fscanf(file,"%c",&c)>=0) && ((c>31)||(c==9)) ) { (*output)[i++]=c; } // ASCII 9 is a tab } *MaxLenPtr = MaxLength; (*output)[i]='\0'; } else { char *outputscan = *output; while (((int)c != '\n') && (!feof(file)) && (!ferror(file))) { if (cancellationFlag) break; if ((fscanf(file,"%c",&c)>=0) && ((c>31)||(c==9)) && (i characters. */ void ppl_getWord(char *out, const char *in, int max) { int count = 0; while ((*in <= ' ') && (*in > '\0')) in++; /* Fastforward over preceeding whitespace */ while (((*in > ' ') || (*in < '\0')) && (count < (max-1))) { *(out++) = *(in++); count++; } *out = '\0'; /* Terminate output */ } /* ppl_nextWord(): Fast forward over word, and return pointer to next word */ char *ppl_nextWord(char *in) { while ((*in <= ' ') && (*in > '\0')) in++; /* Fastforward over preceeding whitespace */ while ((*in > ' ') || (*in < '\0')) in++; /* Fastforward over one word */ while ((*in <= ' ') && (*in > '\0')) in++; /* Fastforward over whitespace before next word */ return(in); /* Return pointer to next word */ } /* ppl_friendlyTimestring(): Returns pointer to time string */ char *ppl_friendlyTimestring() { time_t timenow; timenow = time(NULL); return( ctime(&timenow) ); } /* ppl_strStrip(): Strip whitespace from both ends of a string */ char *ppl_strStrip(const char *in, char *out) { char *scan = out; while ((*in <= ' ') && (*in > '\0')) in++; while (*in != '\0') *(scan++)=*(in++); scan--; while ((scan>out) && (*scan >= '\0') && (*scan <= ' ')) scan--; *++scan = '\0'; return out; } /* ppl_strUpper(): Capitalise a string */ char *ppl_strUpper(const char *in, char *out) { char *scan = out; while (*in != '\0') if ((*in >='a') && (*in <='z')) *scan++ = *in++ +'A'-'a'; else *scan++ = *in++; *scan = '\0'; return out; } /* ppl_strLower(): Lowercase a string */ char *ppl_strLower(const char *in, char *out) { char *scan = out; while (*in != '\0') if ((*in >='A') && (*in <='Z')) *scan++ = *in++ +'a'-'A'; else *scan++ = *in++; *scan = '\0'; return out; } /* ppl_strUnderline(): Underline a string */ char *ppl_strUnderline(const char *in, char *out) { char *scan = out; while (*in != '\0') { if ((*in>=' ')||(*in<'\0')) *scan++='-'; in++; } *scan = '\0'; return out; } /* ppl_strRemoveCompleteLine(): Removes a single complete line from a text buffer, if there is one */ char *ppl_strRemoveCompleteLine(char *in, char *out) { char *scan, *scan2, *scanout; scan = scan2 = in; scanout = out; while ((*scan != '\0') && (*scan != '\n')) scan++; // Find first carriage-return in text buffer if (*scan != '\0') while (scan2'\0') && (candidate[j]<=' ')); j++); // Fastforward over whitespace at beginning of candidate for (i=0; 1; i++,j++) if (test[i]!='\0') { if (toupper(test[i]) != toupper(candidate[j])) // Candidate string has deviated from test string { if (i' ') && (isalnum(test[i])==0) && (test[i]!='_')) return -1; return j; } else // Word terminated with more letters { return -1; } } } else { // We've hit the end of the test string if (candidate[j]<=' ') // Word teminated with space... { return j; } else if ((isalnum(candidate[j])==0) && (candidate[j]!='_')) // Word teminated with punctuation... { // Alphanumeric test strings can be terminated by punctuation; others must have spaces after them for (i=0; test[i]!='\0'; i++) if ((test[i]>' ') && (isalnum(test[i])==0) && (test[i]!='_')) return -1; return j; } else // Word terminated with more letters { return -1; } } } /* ppl_strWordWrap(): Word wrap a piece of text to a certain width */ void ppl_strWordWrap(const char *in, char *out, int width) { int WhiteSpace = 1; int LastSpace = -1; int LineStart = 0; int LineFeeds = 0; // If we meet > 1 linefeed during a period of whitespace, it marks the beginning of a new paragraph int i,j; for (i=0,j=0 ; in[i]!='\0' ; i++) { if ((WhiteSpace==1) && (in[i]<=' ')) // Once we've encountered one space, ignore any further whitespaceness { if (j==0) j++; // If we open document with a new paragraph, we haven't already put down a space character to overwrite if ((in[i]=='\n') && (++LineFeeds==2)) { out[j-1]='\n'; out[j]='\n'; LineStart=j++; LastSpace=-1; } // Two linefeeds in a period of whitespace means a new paragraph continue; } if ((WhiteSpace==0) && (in[i]<=' ')) // First whitespace character after a string of letters { if (in[i]=='\n') LineFeeds=1; out[j]=' '; LastSpace=j++; WhiteSpace=1; continue; } if ((in[i]=='\\') && (in[i+1]=='\\')) {i++; out[j]='\n'; LineStart=j++; LastSpace=-1; WhiteSpace=1; continue;} // Double-backslash implies a hard linebreak. if (in[i]=='#') {out[j++]=' '; WhiteSpace=1; continue;} // A hash character implies a hard space character, used to tabulate data WhiteSpace=0; LineFeeds=0; if (((j-LineStart) > width) && (LastSpace != -1)) { out[LastSpace]='\n'; LineStart=LastSpace; LastSpace=-1; } // If line is too line, insert a linebreak if (strncmp(in+i, "\\lab" , 4)==0) {i+=3; out[j++]='<'; continue;} // Macros for left-angle-brackets, etc. if (strncmp(in+i, "\\rab" , 4)==0) {i+=3; out[j++]='>'; continue;} if (strncmp(in+i, "\\VERSION", 8)==0) {i+=7; strcpy(out+j,VERSION); j+=strlen(out+j); continue;} if (strncmp(in+i, "\\DATE" , 5)==0) {i+=4; strcpy(out+j,DATE ); j+=strlen(out+j); continue;} if (strncmp(in+i, "Elephants", 9)==0) {i+=8; out[j++]='#'; continue;} out[j++] = in[i]; } out[j]='\0'; return; } /* ppl_strBacketMatch(): Find a closing bracket to match an opening bracket, and optionally return a list of all comma positions */ /* 'in' should point to the opening bracket character for which we are looking for the closing partner */ void ppl_strBracketMatch(const char *in, char open, char close, int *CommaPositions, int *Nargs, int *ClosingBracketPos, int MaxCommaPoses) { int BracketLevel[3] = {0,0,0}; char bopen [4] = "([{"; char bclose [4] = ")]}"; int inpos = 0; int commapos = 0; char QuoteType = '\0'; int idx = (open=='{') ? 2 : ((open=='[') ? 1 : 0); int done = 0; int btype; for ( ; in[inpos]!='\0'; inpos++) { if (QuoteType != '\0') // Do not pay attention to brackets inside quoted strings { if ((in[inpos]==QuoteType) && (in[inpos-1]!='\\')) QuoteType='\0'; continue; } else if ((in[inpos]=='\'') || (in[inpos]=='\"')) QuoteType = in[inpos]; // Entering a quoted string for (btype=0; btype<3; btype++) { if (in[inpos]==bopen[btype]) // Entering a nested level of brackets { BracketLevel[btype]++; if ( (idx==btype) && (BracketLevel[btype]==1) && (BracketLevel[(btype+1)%3]==0) && (BracketLevel[(btype+2)%3]==0) && (CommaPositions != NULL) && ((MaxCommaPoses < 0) || (commapos < MaxCommaPoses)) ) *(CommaPositions+(commapos++)) = inpos; // Put ( on comma list } else if (in[inpos]==bclose[btype]) // Leaving a nested level of brackets { BracketLevel[btype]--; if ( (idx==btype) && (BracketLevel[btype]==0) && (BracketLevel[(btype+1)%3]==0) && (BracketLevel[(btype+2)%3]==0) ) { done=1; break; } } } if ( (in[inpos]==',') && (BracketLevel[idx]==1) && (BracketLevel[(idx+1)%3]==0) && (BracketLevel[(idx+2)%3]==0) ) // Found a new comma-separated item { if ((CommaPositions != NULL) && ((MaxCommaPoses < 0) || (commapos < MaxCommaPoses))) *(CommaPositions+(commapos++)) = inpos; // Put , on comma list } if (done) break; } if (in[inpos] == '\0') { if (Nargs != NULL) *Nargs = -1; if (ClosingBracketPos != NULL) *ClosingBracketPos = -1; return; } else { if ((CommaPositions != NULL) && ((MaxCommaPoses < 0) || (commapos < MaxCommaPoses))) *(CommaPositions+(commapos++)) = inpos; // Put ) on comma list if (Nargs != NULL) *Nargs = commapos-1; // There are N+1 arguments between N commas, but we've also counted ( and ). if (ClosingBracketPos != NULL) *ClosingBracketPos = inpos; return; } } /* ppl_strCmpNoCase(): A case-insensitive version of the standard strcmp() function */ int ppl_strCmpNoCase(const char *a, const char *b) { char aU, bU; while (1) { if ((*a == '\0')&&(*b == '\0')) return 0; if (*a == *b) {a++; b++; continue;} if ((*a>='a')&&(*a<='z')) aU=*a-'a'+'A'; else aU=*a; if ((*b>='a')&&(*b<='z')) bU=*b-'a'+'A'; else bU=*b; if (aU==bU) {a++; b++; continue;} if (aU< bU) return -1; return 1; } } /* ppl_strEscapify(): Inserts escape characters into strings before quote characters */ char *ppl_strEscapify(const char *in, char *out) { const char *scanin = in; char *scanout = out; *scanout++ = '\"'; while (*scanin != '\0') { if (*scanin=='\?') { strcpy(scanout,"\\?"); scanout+=2; scanin++; continue; } if (*scanin=='\a') { strcpy(scanout,"\\a"); scanout+=2; scanin++; continue; } if (*scanin=='\b') { strcpy(scanout,"\\b"); scanout+=2; scanin++; continue; } if (*scanin=='\f') { strcpy(scanout,"\\f"); scanout+=2; scanin++; continue; } if (*scanin=='\n') { strcpy(scanout,"\\n"); scanout+=2; scanin++; continue; } if (*scanin=='\r') { strcpy(scanout,"\\r"); scanout+=2; scanin++; continue; } if (*scanin=='\t') { strcpy(scanout,"\\t"); scanout+=2; scanin++; continue; } if (*scanin=='\v') { strcpy(scanout,"\\v"); scanout+=2; scanin++; continue; } if ((*scanin=='\'')||(*scanin=='\"')||(*scanin=='\\')) *(scanout++) = '\\'; *(scanout++) = *(scanin++); } *scanout++ = '\"'; *scanout++ = '\0'; return out; } /* ppl_strWildcardTest(): Test whether test string matches wildcard string */ int ppl_strWildcardTest(const char *test, const char *wildcard) { int i=0, j, k, mineat=0, maxeat=0; while ((wildcard[i]!='\0') && (wildcard[i]!='?') && (wildcard[i]!='*')) if (test[i] != wildcard[i]) { return 0; } else { i++; } if (wildcard[i]=='\0') return (test[i]=='\0'); j=i; while ((wildcard[j]=='?') || (wildcard[j]=='*')) { if (wildcard[j]=='?') { mineat++; maxeat++; } else { maxeat = 10000; } j++; } for (k=0; k <| |_) | | (_) | |_ | .__/ \__, /_/\_\ .__/|_|\___/ \__| Copyright (C) 2006-2012 Dominic Ford |_| |___/ |_| 2008-2012 Ross Church For documentation and more information, see . ----- 1. INTRODUCTION Pyxplot is a multi-purpose graph plotting tool, scientific scripting language, vector graphics suite, and data processing package. Its interface is designed to make common tasks -- e.g., plotting labelled graphs of data -- accessible via short, simple, intuitive commands. But these commands also take many optional settings, allowing their output to be fine-tuned into styles appropriate for printed publications, talks or websites. Pyxplot is simple enough to be used without prior programming experience, but powerful enough that programmers can extensively configure and script it. A SCIENTIFIC SCRIPTING LANGUAGE Pyxplot doesn't just plot graphs. It's a scripting language in which variables can have physical units. Calculations automatically return results in an appropriate unit, whether that be kilograms, joules or lightyears. Datafiles can be converted straightforwardly from one set of units to another. Meanwhile Pyxplot has all the other features of a scripting language: flow control and branching, string manipulation, complex data types, an object-oriented class structure and straightforward file I/O. It also supports vector and matrix algebra, can integrate or differentiate expressions, and can numerically solve systems of equations. A VECTOR GRAPHICS SUITE The graphical canvas isn't just for plotting graphs on. Circles, polygons and ellipses can be drawn to build vector graphics. Colors are a native object type for easy customisation. For the mathematically minded, Pyxplot's canvas interfaces cleanly with its vector math environment, so that geometric construction is easy. A DATA PROCESSING PACKAGE Pyxplot can interpolate data, find best-fit lines, and compile histograms. It can Fourier transform data, calculate statistics, and output results to new datafiles. Where fine control is needed, custom code can be used to process every data point in a file. Examples of the graphical output produced by Pyxplot can be found on the Pyxplot website: . 2. SYSTEM REQUIREMENTS Pyxplot works on most UNIX-like operating systems. We have tested it under Linux, Solaris and MacOS X, and believe that it should work on other similar POSIX systems. We regret that it is not available for Microsoft Windows, and have no plans for porting it at this time. It requires that the following software packages (not included) be installed: - fftw (version 2 or, preferably, 3+) - gcc and make - Ghostscript - The Gnu Scientific Library (version 1.10+) - ImageMagick - LaTeX (version 2e) - libpng (version 1.2+) - libxml2 (version 2.6+) - zlib It is also strongly recommended that the following software packages be installed: - cfitsio -- required for Pyxplot to be able to plot datafiles in FITS format. - Ghostview (or ggv) -- required for Pyxplot to be able to display plots live on the screen; Pyxplot remains able to generate image files on disk without it. Alternatively, the set viewer within Pyxplot allows a different postscript viewer to be used. - gunzip -- required for Pyxplot to be able to plot compressed datafiles in .gz format. - The Gnu Readline Library (version 5+) -- required for Pyxplot to be able to provide tab completion and command histories in Pyxplot's interactive command-line interface. - libkpathsea -- required to efficiently find the fonts used by LaTeX. - wget -- required for Pyxplot to be able to plot datafiles directly from the Internet. Debian and Ubuntu users can find the above software in the following packages: fftw3-dev, gcc, ghostscript, gv, imagemagick, libc6-dev, libcfitsio3-dev, libgsl0-dev, libkpathsea-dev, libpng12-dev, libreadline-dev, libxml2-dev, make, texlive-latex-extra, texlive-latex-recommended, texlive-fonts-extra, texlive-fonts-recommended, wget, zlib1g-dev. These packages may be installed from a command prompt by typing, all on one line: sudo apt-get install fftw3-dev gcc ghostscript gv imagemagick libc6-dev libcfitsio3-dev libgsl0-dev libkpathsea-dev libpng12-dev libreadline-dev libxml2-dev make texlive-latex-extra texlive-latex-recommended texlive-fonts-extra texlive-fonts-recommended wget zlib1g-dev Users of MacOS X can find the above software in the following MacPorts packages: cfitsio, fftw-3, ghostscript, gsl-devel, gv, ImageMagick, libpng, libxml2, readline-5, texlive, wget, zlib. It may then be necessary to run the command export C_INCLUDE_PATH=/opt/local/include before running the configure script below. 3. INSTALLATION FROM SOURCE ARCHIVE First, download the required archive can be downloaded from the front page of Pyxplot website -- . It is assumed that the packages listed above have already been installed; if they are not, you will need to either install them yourself, if you have superuser access to your machine, or contact your system administrator. * Unpack the distributed .tar.gz: tar xvfz pyxplot_0.9.0.tar.gz cd pyxplot * Run the installation script: ./configure make * Finally, start Pyxplot: ./bin/pyxplot 3A. SYSTEM-WIDE INSTALLATION Having completed the steps described above, Pyxplot may be installed system-wide by a superuser with the following additional step: sudo make install By default, the Pyxplot executable installs to /usr/local/bin/pyxplot. If desired, this installation path may be modified in the file Makefile.skel, by changing the variable USRDIR in the first line to an alternative desired installation location. Pyxplot may now be started by any system user, simply by typing: pyxplot 4. FURTHER INFORMATION Full documentation can be found in doc/pyxplot.tex , or in doc/pyxplot.pdf after installation. This document is alternatively available from the Pyxplot website: . ---- Dominic Ford Ross Church pyxplot-0.9.2/Makefile.skel0000664000175000017500000004005012026340554014220 0ustar dcf21dcf21# MAKEFILE.SKEL # # The code in this file is part of Pyxplot # # # Copyright (C) 2006-2012 Dominic Ford # 2008-2012 Ross Church # # $Id: Makefile.skel 1302 2012-09-05 17:30:27Z dcf21 $ # # Pyxplot 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. # # You should have received a copy of the GNU General Public License along with # Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # Skeleton Makefile for Pyxplot... this is configured by running ./configure, # which adds a few lines of the form: # # GV_COMMAND=/usr/bin/gv # Location of final code. Change the value of USRDIR below to install Pyxplot # to a location other than /usr/local: USRDIR=/usr/local BINDIR=${DESTDIR}${USRDIR}/bin BINDIR_PRIVATE=${DESTDIR}${USRDIR}/lib/pyxplot SRCDIR=${DESTDIR}${USRDIR}/share/pyxplot DOCDIR=${DESTDIR}${USRDIR}/share/doc/pyxplot MANDIR=${DESTDIR}${USRDIR}/share/man/man1 CWD=$(shell pwd) VERSION_MAJ = 0 VERSION_MIN = 9 VERSION_REV = 2 DATE = 19/09/2012 COMPILE = $(CC) -Wall -g `xml2-config --cflags` `gsl-config --cflags` -c -I $(CWD)/src LIBS = $(LINK_FFTW) `xml2-config --libs` `gsl-config --libs` $(LINK_READLINE) -lz -lpng $(LINK_KPATHSEA) -lm LINK = $(CC) -Wall -g OPTIMISATION = -O2 DEBUG = -D DEBUG=1 -D MEMDEBUG1=1 -D MEMDEBUG2=0 NODEBUG = -D DEBUG=0 -D MEMDEBUG1=0 -D MEMDEBUG2=0 LOCAL_SRCDIR = src LOCAL_OBJDIR = obj LOCAL_DOCDIR = doc LOCAL_BINDIR = bin PPL_FILES = canvasItems.c children.c commands/core.c commands/eqnsolve.c commands/fft.c commands/fit.c commands/flowctrl.c commands/funcset.c \ commands/help.c commands/histogram.c commands/interpolate.c commands/interpolate_2d_engine.c commands/set.c commands/show.c commands/tabulate.c \ coreUtils/backup.c coreUtils/dict.c coreUtils/errorReport.c coreUtils/getPasswd.c coreUtils/list.c coreUtils/memAlloc.c coreUtils/stringList.c \ datafile.c datafile_rasters.c defaultObjs/airyFuncs.c defaultObjs/defaultFuncs.c defaultObjs/defaultUnits.c defaultObjs/defaultVars.c \ defaultObjs/moduleAst.c defaultObjs/moduleColor.c defaultObjs/moduleFractals.c defaultObjs/moduleOs.c defaultObjs/modulePhy.c \ defaultObjs/moduleRandom.c defaultObjs/moduleStats.c defaultObjs/moduleTime.c defaultObjs/zetaRiemann.c epsMaker/bmp_a85.c epsMaker/bmp_bmpread.c \ epsMaker/bmp_gifread.c epsMaker/bmp_jpegread.c epsMaker/bmp_optimise.c epsMaker/bmp_pngread.c epsMaker/canvasDraw.c epsMaker/dvi_font.c \ epsMaker/dvi_interpreter.c epsMaker/dvi_read.c epsMaker/eps_arrow.c epsMaker/eps_box.c epsMaker/eps_circle.c epsMaker/eps_core.c \ epsMaker/eps_ellipse.c epsMaker/eps_eps.c epsMaker/eps_image.c epsMaker/eps_piechart.c epsMaker/eps_plot.c epsMaker/eps_plot_axespaint.c \ epsMaker/eps_plot_canvas.c epsMaker/eps_plot_colormap.c epsMaker/eps_plot_contourmap.c epsMaker/eps_plot_filledregion.c epsMaker/eps_plot_gridlines.c \ epsMaker/eps_plot_labelsarrows.c epsMaker/eps_plot_legend.c epsMaker/eps_plot_linedraw.c epsMaker/eps_plot_linkedaxes.c epsMaker/eps_plot_styles.c \ epsMaker/eps_plot_threedimbuff.c epsMaker/eps_plot_ticking_auto2.c epsMaker/eps_plot_ticking_auto3.c epsMaker/eps_plot_ticking_auto.c \ epsMaker/eps_plot_ticking.c epsMaker/eps_point.c epsMaker/eps_polygon.c epsMaker/eps_settings.c epsMaker/eps_style.c epsMaker/eps_text.c \ epsMaker/kpse_wrap.c expressions/dollarOp.c expressions/expCompile.c expressions/expEval.c expressions/expEvalCalculus.c expressions/expEvalOps.c \ expressions/expEvalSlice.c expressions/fnCall.c expressions/traceback.c input.c mathsTools/dcfmath.c parser/cmdList.c parser/parserCompile.c \ parser/parserExecute.c parser/parserInit.c parser/parserShell.c pyxplot.c readConf.c settings/arrows.c settings/axes.c settings/colors.c \ settings/epsColors.c settings/labels.c settings/papersizes.c settings/settingsInit.c settings/settingTypes.c settings/textConstants.c \ settings/withWords.c stringTools/asciidouble.c texify.c userspace/calendars.c userspace/context.c userspace/contextVarDef.c \ userspace/garbageCollector.c userspace/pplObj.c userspace/pplObjCmp.c userspace/pplObjDump.c userspace/pplObjFunc.c userspace/pplObjMethods.c \ userspace/pplObjPrint.c userspace/unitsArithmetic.c userspace/unitsDisp.c PPL_HEADERS = canvasItems.h children.h commands/core.h commands/eqnsolve.h commands/fft.h commands/fit.h commands/flowctrl.h commands/funcset.h \ commands/help.h commands/histogram.h commands/interpolate.h commands/interpolate_2d_engine.h commands/set.h commands/show.h commands/tabulate.h \ coreUtils/backup.h coreUtils/dict.h coreUtils/errorReport.h coreUtils/getPasswd.h coreUtils/list.h coreUtils/memAlloc.h coreUtils/stringList.h \ datafile.h datafile_rasters.h defaultObjs/airyFuncs.h defaultObjs/defaultFuncs.h defaultObjs/defaultFuncsMacros.h defaultObjs/moduleAst.h \ defaultObjs/moduleColor.h defaultObjs/moduleFractals.h defaultObjs/moduleOs.h defaultObjs/modulePhy.h defaultObjs/moduleRandom.h \ defaultObjs/moduleStats.h defaultObjs/moduleTime.h defaultObjs/zetaRiemann.h epsMaker/bmp_a85.h epsMaker/bmp_bmpread.h epsMaker/bmp_gifread.h \ epsMaker/bmp_image.h epsMaker/bmp_jpegread.h epsMaker/bmp_optimise.h epsMaker/bmp_pngread.h epsMaker/canvasDraw.h epsMaker/dvi_font.h \ epsMaker/dvi_interpreter.h epsMaker/dvi_read.h epsMaker/eps_arrow.h epsMaker/eps_comm.h epsMaker/eps_box.h epsMaker/eps_circle.h epsMaker/eps_core.h \ epsMaker/eps_ellipse.h epsMaker/eps_eps.h epsMaker/eps_image.h epsMaker/eps_piechart.h epsMaker/eps_plot.h epsMaker/eps_plot_axespaint.h \ epsMaker/eps_plot_canvas.h epsMaker/eps_plot_colormap.h epsMaker/eps_plot_contourmap.h epsMaker/eps_plot_filledregion.h epsMaker/eps_plot_gridlines.h \ epsMaker/eps_plot_labelsarrows.h epsMaker/eps_plot_legend.h epsMaker/eps_plot_linedraw.h epsMaker/eps_plot_linkedaxes.h epsMaker/eps_plot_styles.h \ epsMaker/eps_plot_threedimbuff.h epsMaker/eps_plot_ticking_auto2.h epsMaker/eps_plot_ticking_auto3.h epsMaker/eps_plot_ticking_auto.h \ epsMaker/eps_plot_ticking.h epsMaker/eps_point.h epsMaker/eps_polygon.h epsMaker/eps_settings.h epsMaker/eps_style.h epsMaker/eps_text.h \ epsMaker/kpse_wrap.h expressions/dollarOp.h expressions/expCompile.h expressions/expCompile_fns.h expressions/expEval.h expressions/expEvalCalculus.h \ expressions/expEvalOps.h expressions/expEvalSlice.h expressions/fnCall.h expressions/traceback.h expressions/traceback_fns.h input.h \ mathsTools/dcfmath.h parser/cmdList.h parser/parser.h pplConstants.h pyxplot.h readConf.h settings/arrows.h settings/arrows_fns.h settings/axes_fns.h \ settings/colors.h settings/epsColors.h settings/labels.h settings/labels_fns.h settings/papersizes.h settings/settings.h settings/settings_fns.h \ settings/settingTypes.h settings/textConstants.h settings/withWords.h settings/withWords_fns.h stringTools/asciidouble.h stringTools/strConstants.h \ texify.h userspace/calendars.h userspace/context.h userspace/contextVarDef.h userspace/garbageCollector.h userspace/pplObj.h userspace/pplObj_fns.h \ userspace/pplObjCmp.h userspace/pplObjDump.h userspace/pplObjFunc.h userspace/pplObjFunc_fns.h userspace/pplObjMethods.h userspace/pplObjPrint.h \ userspace/pplObjUnits.h userspace/unitsArithmetic.h userspace/unitsDisp.h PPLW_FILES = helpers/pyxplot_watch.c coreUtils/dict.c coreUtils/errorReport.c coreUtils/list.c coreUtils/memAlloc.c coreUtils/stringList.c \ stringTools/asciidouble.c settings/settingTypes.c PPLW_HEADERS = coreUtils/dict.h coreUtils/errorReport.h coreUtils/list.h coreUtils/memAlloc.h coreUtils/stringList.h \ stringTools/asciidouble.h settings/settingTypes.h FITSHELP_FILES = helpers/pyxplot_fitshelper.c stringTools/asciidouble.c FITSHELP_HEADERS = stringTools/asciidouble.h stringTools/strConstants.h PPL_SOURCES = $(PPL_FILES:%.c=$(LOCAL_SRCDIR)/%.c) PPL_OBJECTS = $(PPL_FILES:%.c=$(LOCAL_OBJDIR)/%.o) PPL_OBJECTS_DEBUG = $(PPL_OBJECTS:%.o=%.debug.o) PPL_OBJECTS_INSTALL = $(PPL_OBJECTS:%.o=%.install.o) PPL_HFILES = $(PPL_HEADERS:%.h=$(LOCAL_SRCDIR)/%.h) Makefile PPLW_SOURCES = $(PPLW_FILES:%.c=$(LOCAL_SRCDIR)/%.c) PPLW_OBJECTS = $(PPLW_FILES:%.c=$(LOCAL_OBJDIR)/%.o) PPLW_OBJECTS_DEBUG = $(PPLW_OBJECTS:%.o=%.debug.o) PPLW_OBJECTS_INSTALL= $(PPLW_OBJECTS:%.o=%.install.o) PPLW_HFILES = $(PPLW_HEADERS:%.h=$(LOCAL_SRCDIR)/%.h) Makefile FITSHELP_SOURCES = $(FITSHELP_FILES:%.c=$(LOCAL_SRCDIR)/%.c) FITSHELP_OBJECTS = $(FITSHELP_FILES:%.c=$(LOCAL_OBJDIR)/%.o) FITSHELP_OBJECTS_INSTALL = $(FITSHELP_OBJECTS:%.o=%.install.o) FITSHELP_HFILES = $(FITSHELP_HEADERS:%.h=$(LOCAL_SRCDIR)/%.h) Makefile ALL_HFILES = $(PPL_HFILES) $(PPLW_HFILES) $(FITSHELP_HFILES) COMMON_SWITCHES = -D VERSION=\"$(VERSION_MAJ).$(VERSION_MIN).$(VERSION_REV)\" -D VERSION_MAJ=$(VERSION_MAJ) -D VERSION_MIN=$(VERSION_MIN) -D VERSION_REV=$(VERSION_REV) -D DATE=\"$(DATE)\" -D PATHLINK=\"$(PATHLINK)\" $(HAVE_READLINE) $(HAVE_FFTW3) $(HAVE_FITSIO) $(HAVE_KPATHSEA) -D LATEX_COMMAND=\"$(LATEX_COMMAND)\" -D KPSE_COMMAND=\"$(KPSE_COMMAND)\" -D CONVERT_COMMAND=\"$(CONVERT_COMMAND)\" -D GHOSTSCRIPT_COMMAND=\"$(GS_COMMAND)\" -D SED_COMMAND=\"$(SED_COMMAND)\" $(GUNZIP_COMMAND) $(WGET_COMMAND) -D GHOSTVIEW_COMMAND=\"$(GV_COMMAND)\" -D GHOSTVIEW_OPT=\"$(GV_OPT)\" -D GGV_COMMAND=\"$(GGV_COMMAND)\" NOINSTALL_SWITCHES = $(COMMON_SWITCHES) -D SRCDIR=\"$(CWD)/$(LOCAL_SRCDIR)/\" -D DOCDIR=\"$(CWD)/$(LOCAL_DOCDIR)/\" -D PPLBINARY=\"$(CWD)/$(LOCAL_BINDIR)/pyxplot\" -D FITSHELPER=\"$(CWD)/$(LOCAL_BINDIR)/pyxplot_fitshelper\" -D TIMEHELPER=\"$(CWD)/$(LOCAL_BINDIR)/pyxplot_timehelper\" INSTALL_SWITCHES = $(COMMON_SWITCHES) -D SRCDIR=\"$(SRCDIR)\" -D DOCDIR=\"$(DOCDIR)\" -D PPLBINARY=\"$(BINDIR)/pyxplot\" -D FITSHELPER=\"$(BINDIR_PRIVATE)/pyxplot_fitshelper\" -D TIMEHELPER=\"$(BINDIR_PRIVATE)/pyxplot_timehelper\" DEBUG_SWITCHES = $(COMMON_SWITCHES) -D SRCDIR=\"$(CWD)/$(LOCAL_SRCDIR)/\" -D DOCDIR=\"$(CWD)/$(LOCAL_DOCDIR)/\" -D PPLBINARY=\"$(CWD)/$(LOCAL_BINDIR)/debug/pyxplot\" -D FITSHELPER=\"$(CWD)/$(LOCAL_BINDIR)/pyxplot_fitshelper\" -D TIMEHELPER=\"$(CWD)/$(LOCAL_BINDIR)/pyxplot_timehelper\" all: $(LOCAL_BINDIR)/pyxplot $(LOCAL_BINDIR)/pyxplot_watch $(LOCAL_BINDIR)/pyxplot_fitshelper $(LOCAL_BINDIR)/pyxplot_timehelper $(LOCAL_BINDIR)/debug/pyxplot $(LOCAL_BINDIR)/debug/pyxplot_watch $(LOCAL_BINDIR)/install/pyxplot $(LOCAL_BINDIR)/install/pyxplot_watch $(LOCAL_BINDIR)/install/pyxplot_fitshelper $(LOCAL_BINDIR)/install/pyxplot_timehelper $(LOCAL_OBJDIR)/pyxplot.1 $(LOCAL_OBJDIR)/pyxplot_watch.1 src/settings/epsColors.h: buildScripts/colorlistGenerate.py python buildScripts/colorlistGenerate.py src/settings/epsColors.c: src/settings/epsColors.h src/parser/cmdList.h: buildScripts/parser_data.py buildScripts/parser_data.dat python buildScripts/parser_data.py src/parser/cmdList.c: src/parser/cmdList.h # # General macros for the compile steps # $(LOCAL_OBJDIR)/%.o: $(LOCAL_SRCDIR)/%.c $(ALL_HFILES) mkdir -p $(LOCAL_OBJDIR) $(LOCAL_OBJDIR)/commands $(LOCAL_OBJDIR)/coreUtils $(LOCAL_OBJDIR)/defaultObjs $(LOCAL_OBJDIR)/epsMaker $(LOCAL_OBJDIR)/expressions $(LOCAL_OBJDIR)/helpers $(LOCAL_OBJDIR)/mathsTools $(LOCAL_OBJDIR)/parser $(LOCAL_OBJDIR)/settings $(LOCAL_OBJDIR)/stringTools $(LOCAL_OBJDIR)/userspace $(COMPILE) $(CFLAGS) $(CPPFLAGS) $(OPTIMISATION) $(NODEBUG) $(NOINSTALL_SWITCHES) $< -o $@ $(LOCAL_OBJDIR)/%.debug.o: $(LOCAL_SRCDIR)/%.c $(ALL_HFILES) mkdir -p $(LOCAL_OBJDIR) $(LOCAL_OBJDIR)/commands $(LOCAL_OBJDIR)/coreUtils $(LOCAL_OBJDIR)/defaultObjs $(LOCAL_OBJDIR)/epsMaker $(LOCAL_OBJDIR)/expressions $(LOCAL_OBJDIR)/helpers $(LOCAL_OBJDIR)/mathsTools $(LOCAL_OBJDIR)/parser $(LOCAL_OBJDIR)/settings $(LOCAL_OBJDIR)/stringTools $(LOCAL_OBJDIR)/userspace $(COMPILE) $(CFLAGS) $(CPPFLAGS) $(OPTIMISATION) $(DEBUG) $(DEBUG_SWITCHES) $< -o $@ $(LOCAL_OBJDIR)/%.install.o: $(LOCAL_SRCDIR)/%.c $(ALL_HFILES) mkdir -p $(LOCAL_OBJDIR) $(LOCAL_OBJDIR)/commands $(LOCAL_OBJDIR)/coreUtils $(LOCAL_OBJDIR)/defaultObjs $(LOCAL_OBJDIR)/epsMaker $(LOCAL_OBJDIR)/expressions $(LOCAL_OBJDIR)/helpers $(LOCAL_OBJDIR)/mathsTools $(LOCAL_OBJDIR)/parser $(LOCAL_OBJDIR)/settings $(LOCAL_OBJDIR)/stringTools $(LOCAL_OBJDIR)/userspace $(COMPILE) $(CFLAGS) $(CPPFLAGS) $(OPTIMISATION) $(NODEBUG) $(INSTALL_SWITCHES) $< -o $@ # # Make the pyxplot binaries # $(LOCAL_BINDIR)/pyxplot: $(PPL_OBJECTS) mkdir -p $(LOCAL_BINDIR) $(LINK) $(LDFLAGS) $(PPL_OBJECTS) $(LIBS) -o $(LOCAL_BINDIR)/pyxplot $(LOCAL_BINDIR)/debug/pyxplot: $(PPL_OBJECTS_DEBUG) mkdir -p $(LOCAL_BINDIR)/debug echo "The files in this directory are binaries with debugging options enabled: they produce activity logs called 'pyxplot.log'. It should be noted that these binaries can up to ten times slower than non-debugging versions." > $(LOCAL_BINDIR)/debug/README $(LINK) $(LDFLAGS) $(PPL_OBJECTS_DEBUG) $(LIBS) -o $(LOCAL_BINDIR)/debug/pyxplot $(LOCAL_BINDIR)/install/pyxplot: $(PPL_OBJECTS_INSTALL) mkdir -p $(LOCAL_BINDIR)/install echo "The files in this directory are binaries intended to be installed with 'make install'. They should not be used in their present location, as they contain hard-coded links to files which are created by the 'make install' step." > $(LOCAL_BINDIR)/debug/README $(LINK) $(LDFLAGS) $(PPL_OBJECTS_INSTALL) $(LIBS) -o $(LOCAL_BINDIR)/install/pyxplot # # Make the pyxplot_watch binaries # $(LOCAL_BINDIR)/pyxplot_watch: $(PPLW_OBJECTS) mkdir -p $(LOCAL_BINDIR) $(LINK) $(LDFLAGS) $(PPLW_OBJECTS) $(LIBS) -o $(LOCAL_BINDIR)/pyxplot_watch $(LOCAL_BINDIR)/debug/pyxplot_watch: $(PPLW_OBJECTS_DEBUG) mkdir -p $(LOCAL_BINDIR)/debug $(LINK) $(LDFLAGS) $(PPLW_OBJECTS_DEBUG) $(LIBS) -o $(LOCAL_BINDIR)/debug/pyxplot_watch $(LOCAL_BINDIR)/install/pyxplot_watch: $(PPLW_OBJECTS_INSTALL) mkdir -p $(LOCAL_BINDIR)/install $(LINK) $(LDFLAGS) $(PPLW_OBJECTS_INSTALL) $(LIBS) -o $(LOCAL_BINDIR)/install/pyxplot_watch # # Make fits helper binaries # $(LOCAL_BINDIR)/pyxplot_fitshelper: $(FITSHELP_OBJECTS) mkdir -p $(LOCAL_BINDIR) $(LINK) $(LDFLAGS) $(FITSHELP_OBJECTS) $(LINK_FITSIO) $(LIBS) -o $(LOCAL_BINDIR)/pyxplot_fitshelper $(LOCAL_BINDIR)/install/pyxplot_fitshelper: $(FITSHELP_OBJECTS_INSTALL) mkdir -p $(LOCAL_BINDIR)/install $(LINK) $(LDFLAGS) $(FITSHELP_OBJECTS_INSTALL) $(LINK_FITSIO) $(LIBS) -o $(LOCAL_BINDIR)/install/pyxplot_fitshelper # # Make time helper # $(LOCAL_BINDIR)/pyxplot_timehelper: $(LOCAL_SRCDIR)/helpers/pyxplot_timehelper.sh mkdir -p $(LOCAL_BINDIR) cp $(LOCAL_SRCDIR)/helpers/pyxplot_timehelper.sh $@ $(LOCAL_BINDIR)/install/pyxplot_timehelper: $(LOCAL_SRCDIR)/helpers/pyxplot_timehelper.sh mkdir -p $(LOCAL_BINDIR)/install cp $(LOCAL_SRCDIR)/helpers/pyxplot_timehelper.sh $@ # # Make man page # $(LOCAL_OBJDIR)/pyxplot.1: buildScripts/manpage_pyxplot.py mkdir -p $(LOCAL_OBJDIR) python buildScripts/manpage_pyxplot.py ${DOCDIR}/pyxplot.pdf > $(LOCAL_OBJDIR)/pyxplot.1 $(LOCAL_OBJDIR)/pyxplot_watch.1: buildScripts/manpage_pyxplot_watch.py mkdir -p $(LOCAL_OBJDIR) python buildScripts/manpage_pyxplot_watch.py ${DOCDIR}/pyxplot.pdf > $(LOCAL_OBJDIR)/pyxplot_watch.1 # # Install step # install: all install -d ${SRCDIR} ${BINDIR} ${BINDIR_PRIVATE} ${MANDIR} install -m644 ${LOCAL_SRCDIR}/help.xml ${SRCDIR} install -m755 ${LOCAL_BINDIR}/install/pyxplot ${BINDIR}/pyxplot install -m755 ${LOCAL_BINDIR}/install/pyxplot_watch ${BINDIR}/pyxplot_watch install -m755 ${LOCAL_BINDIR}/install/pyxplot_fitshelper ${BINDIR_PRIVATE}/pyxplot_fitshelper install -m755 ${LOCAL_BINDIR}/install/pyxplot_timehelper ${BINDIR_PRIVATE}/pyxplot_timehelper install -m644 $(LOCAL_OBJDIR)/pyxplot.1 ${MANDIR}/pyxplot.1 install -m644 $(LOCAL_OBJDIR)/pyxplot_watch.1 ${MANDIR}/pyxplot_watch.1 install-doc: install -d ${DOCDIR} install -m644 doc/*.tex doc/pyxplot.pdf ${DOCDIR} # # Clean macros # clean: rm -f src/parser/cmdList.c src/parser/cmdList.h src/settings/epsColors.c src/settings/epsColors.h rm -vfR $(LOCAL_OBJDIR) $(LOCAL_BINDIR) afresh: clean all pyxplot-0.9.2/doc/0000775000175000017500000000000012026340554012371 5ustar dcf21dcf21pyxplot-0.9.2/doc/pyxplot-plain.tex0000664000175000017500000000211412026340554015731 0ustar dcf21dcf21% pyxplot-plain.tex % % The documentation in this file is part of Pyxplot % % % Copyright (C) 2006-2012 Dominic Ford % 2008-2012 Ross Church % % $Id: pyxplot-plain.tex 1261 2012-07-11 21:38:05Z dcf21 $ % % Pyxplot 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. % % You should have received a copy of the GNU General Public License along with % Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin % Street, Fifth Floor, Boston, MA 02110-1301, USA % ---------------------------------------------------------------------------- % LaTeX source for the Pyxplot Users' Guide \documentclass[a4paper,onecolumn,10pt]{book} \usepackage[dvips]{graphicx} \usepackage{afterpage,amssymb,amsmath,bbding,color,colortbl,enumerate,lscape,longtable,multirow,nicefrac,fancyvrb,makeidx,pstricks,supertabular,upgreek,url,wasysym} \input{main} pyxplot-0.9.2/doc/gnuplot_diffs.tex0000664000175000017500000001467612026340554015774 0ustar dcf21dcf21% gnuplot_diffs.tex % % The documentation in this file is part of Pyxplot % % % Copyright (C) 2006-2012 Dominic Ford % 2008-2012 Ross Church % % $Id: gnuplot_diffs.tex 1302 2012-09-05 17:30:27Z dcf21 $ % % Pyxplot 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. % % You should have received a copy of the GNU General Public License along with % Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin % Street, Fifth Floor, Boston, MA 02110-1301, USA % ---------------------------------------------------------------------------- % LaTeX source for the Pyxplot Users' Guide \chapter{Summary of differences between Pyxplot and \gnuplot} \chaptermark{Differences between Pyxplot \& \gnuplot} \label{ch:gnuplot_diffs} Pyxplot's command-line interface is based loosely upon that of \gnuplot, but does not completely re-implement the entirety of \gnuplot's command language. Moreover, Pyxplot's command language includes many extensions of \gnuplot's interface. In this Appendix, we outline some of the most significant areas in which \gnuplot\ and Pyxplot differ. This is far from an exhaustive list, but may provide a useful reference for \gnuplot\ users. \section{The typesetting of text} Pyxplot renders all text labels automatically in the \latexdcf\ typesetting environment. This brings many advantages: it produces neater labels than the default typesetting engine used by \gnuplot, makes it straightforward to label graphs with mathematical expressions, and moreover makes it straightforward when importing graphs into \latexdcf\ documents to match the fonts used in figures with those used in the main text of the document. It does, however, also necessarily introduce some incompatibility with \gnuplot. Some strings which are valid in \gnuplot\ are not valid in Pyxplot (see Section~\ref{sec:latex_incompatibility} for more details). For example,\index{latex} \begin{dontdo} set xlabel 'x\^{}2' \end{dontdo} \noindent is a valid label in \gnuplot, but is not valid input for \latexdcf\ and therefore fails in Pyxplot. In Pyxplot, it needs to be written in \latexdcf\ mathmode as: \begin{dodo} set xlabel '\$x\^{}2\$' \end{dodo} \noindent A useful introduction to \latexdcf's syntax can be found in Tobias Oetiker's\index{Tobias Oetiker} excellent free tutorial, {\it The Not So Short Guide to \latexdcf\ $2\epsilon$}\index{Not So Short Guide to \latexdcf\ $2\epsilon$, The}, which is available for free download from: \noindent \url{http://www.ctan.org/tex-archive/info/lshort/english/lshort.pdf} Two built-in functions provide some assistance in generating \latexdcf\ labels. The \indfunt{texify()} takes as its argument a string containing a mathematical expression, and returns a \latexdcf\ representation of it. The \indfunt{texifyText()} takes as its argument a text string, and returns a \latexdcf\ representation of it, with any necessary escape characters added. For example: \vspace{3mm} \input{fragments/tex/fs_texify.tex} \vspace{3mm} Two built-in functions provide some assistance in generating \latexdcf\ labels. The \indfunt{texify()} takes as its argument a string containing a mathematical expression, and returns a \latexdcf\ representation of it. The \indfunt{texifyText()} takes as its argument a text string, and returns a \latexdcf\ representation of it, with any necessary escape characters added. For example: \vspace{3mm} \input{fragments/tex/fs_texify.tex} \vspace{3mm} \section{Complex numbers} The syntax used for representing complex numbers in Pyxplot differs from that used in \gnuplot. Whereas \gnuplot\ expects the real and imaginary components of complex numbers to be represented {\tt \{a,b\}}, Pyxplot uses the syntax {\tt a+b*i}, assuming that the variable {\tt i} has been defined to equal {\tt sqrt(-1)}. In addition, in Pyxplot complex arithmetic must first be enabled using the {\tt set numerics complex} command before complex numbers may be entered. This is illustrated by the following example: \vspace{3mm} \noindent{\tt gnuplot> {\bf print \{1,2\} + \{3,4\}}}\newline \noindent{\tt \{4.0, 6.0\}} \vspace{3mm}\newline \input{fragments/tex/gnu_complex.tex} \vspace{3mm} \section{The multiplot environment} \gnuplot's multiplot environment, used for placing many graphs alongside one another, is massively extended in Pyxplot. As well as making it much easier to produce galleries of plots and inset graphs, a wide range of vector graphs objects can also be added to the multiplot canvas. This is described in detail in Chapter~\ref{ch:vector_graphics}. \section{Plots with multiple axes} In \gnuplot, a maximum of two horizontal and two vertical axes may be associated with each graph, placed in each case with one on either side of the plot. These are referred to as the {\tt x} (bottom) and {\tt x2} (top), or {\tt y} (left) and {\tt y2} (right) axes. This behaviour is reproduced in Pyxplot, and so the syntax \begin{verbatim} set x2label 'Axis label' \end{verbatim} \noindent works similarly in both programs. However, in Pyxplot the position of each axis may be set individually using syntax such as \begin{verbatim} set axis x2 top \end{verbatim} \noindent and furthermore up to~128 axes may be placed parallel to one another: \begin{verbatim} set axis x127 top set x127label "This is axis number 127" \end{verbatim} \noindent More details of how to configure axes can be found in Section~\ref{sec:multiple_axes}. \section{Plotting parametric functions} The syntax used for plotting parametric functions differs between \gnuplot\ and Pyxplot. Whereas parametric plotting is enabled in \gnuplot\ using the {\tt set parametric} command, in Pyxplot it is enabled on a per-dataset basis by placing the keyword {\tt parametric} before the algebraic expression to be plotted: \vspace{3mm} \noindent{\tt gnuplot> {\bf set parametric}}\newline \noindent{\tt gnuplot> {\bf set trange [0:2*pi]}}\newline \noindent{\tt gnuplot> {\bf plot sin(t),cos(t)}} \vspace{3mm}\newline \noindent\texttt{pyxplot> \textbf{set trange [0:2*pi]}}\newline \noindent\texttt{pyxplot> \textbf{plot parametric sin(t):cos(t)}} \vspace{3mm} \noindent This makes it straightforward to plot parametric functions alongside non-parametric functions. For more information, see Section~\ref{sec:parametric_plotting}. %\section{Displaying Times and Dates on Axes} pyxplot-0.9.2/doc/makeFigureEps.py0000664000175000017500000000330212026340554015470 0ustar dcf21dcf21# makeFigureEps.py # # The code in this file is part of PyXPlot # # # Copyright (C) 2006-2012 Dominic Ford # # $Id: makeFigureEps.py 1281 2012-07-29 18:33:42Z dcf21 $ # # PyXPlot 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. # # You should have received a copy of the GNU General Public License along with # PyXPlot; if not, write to the Free Software Foundation, Inc., 51 Franklin # Street, Fifth Floor, Boston, MA 02110-1301, USA # ---------------------------------------------------------------------------- # Turn scripts of examples into latex import glob,os,sys,re if len(sys.argv)>=2: pyxplot = sys.argv[1] else : pyxplot = "../bin/pyxplot" os.system("rm -Rf examples/eps") os.system("mkdir examples/eps") files = glob.glob("examples/ex_*.ppl") files.sort() for fname in files: print "Working on example <%s>..."%os.path.split(fname)[1] status = os.system("%s %s"%(pyxplot,fname)) if (status): raise RuntimeError("pyxplot failed") # Make pdf and png versions of all figures files = glob.glob("examples/eps/*.eps") files.sort() for eps in files: print "Converting example <%s> to pdf..."%os.path.split(eps)[1] pdf = re.sub(r"\.eps",".pdf",eps) #png = re.sub(r"\.eps",".png",eps) os.system("gs -dQUIET -dSAFER -P- -dBATCH -dNOPAUSE -dEPSCrop -sDEVICE=pdfwrite -sOutputFile=%s %s"%(pdf,eps)) #os.system("gs -dQUIET -dSAFER -P- -dBATCH -dNOPAUSE -dEPSCrop -sDEVICE=png16m -r72 -dGraphicsAlphaBits=4 -dTextAlphaBits=4 -sOutputFile=%s %s"%(png,eps)) pyxplot-0.9.2/doc/reference.tex0000664000175000017500000045132212026340554015060 0ustar dcf21dcf21% reference.tex % % The documentation in this file is part of Pyxplot % % % Copyright (C) 2006-2012 Dominic Ford % 2008-2012 Ross Church % % $Id: reference.tex 1302 2012-09-05 17:30:27Z dcf21 $ % % Pyxplot 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. % % You should have received a copy of the GNU General Public License along with % Pyxplot; if not, write to the Free Software Foundation, Inc., 51 Franklin % Street, Fifth Floor, Boston, MA 02110-1301, USA % ---------------------------------------------------------------------------- % LaTeX source for the Pyxplot Users' Guide \chapter{Command reference} \label{ch:reference} This chapter contains an alphabetically ordered list of all of Pyxplot's commands. The syntax of each is specified in a variant of Backus-Naur notation, in which angle brackets {\tt <>} are used to indicate replaceable tokens, parentheses {\tt ()} are used to indicate mutually-exclusive options which are separated by vertical lines {\tt |}, square brackets {\tt []} are used to indicate optional items, and braces {\tt \{\}} are used to indicate items which may be repeated. Dots {\tt ...} are used to indicate arbitrary strings of text. Replaceable tokens labelled {\tt } may be specified either as a number with physical dimensions of length, e.g.\ {\tt 2*unit(m)}, or as a dimensionless number taken as a number of centimeters. Replaceable tokens labelled {\tt } may be specified either with physical dimensions of angle, e.g.\ {\tt 0.25*unit(rev)}, or as a dimensionless number of degrees, e.g. {\tt 90}. Replaceable tokens labelled {\tt } represent a physical position on the vector-graphics canvas, and can be specified either as two comma-separated co-ordinates, or as a two-component vector. In either case, the co-ordinates may either have physical demensions of length, or be a dimensionless number of centimeters. Replaceable tokens labelled {\tt } are similar, but represent a position on a graph. They may be specified either as comma-separated co-ordinates, or as a vector object. In either case, there may be either two or three components, although the third component will be ignored except on three-dimensional plots. The components should share the physical units of the axes they are plotted against. In flow control commands, tokens labelled {\tt } should be replaced by a series of Pyxplot commands enclosed by braces {\tt \{\}}. The closing brace must be placed on a new line. Where braces {\tt \{\}} are used to indicate items which may be repeated, commas or semicolons are often used to separate items. This is specified in the text below the syntax specification. Where keywords differ between US and British English, both variants are accepted. For example, {\tt color} may be spelt {\tt colour}, {\tt gray} may be spelt {\tt grey}, etc. \section{?}\indcmd{?} \begin{verbatim} ? [ { } ] \end{verbatim} The {\tt ?} symbol is a shortcut to the {\tt help} command. \section{!}\indcmd{!} \begin{verbatim} ! ... `` ... \end{verbatim} Shell commands can be executed within Pyxplot by prefixing them with pling (!) characters, as in the example: \begin{verbatim} !mkdir foo \end{verbatim} \noindent As an alternative, back-quotes (`) can be used to substitute the output of a shell command into a Pyxplot command, as in the example: \begin{verbatim} set xlabel `echo "'" ; ls ; echo "'"` \end{verbatim} \noindent Note that back-quotes cannot be used inside quote characters, and so the following would \textit{not} work: \begin{verbatim} set xlabel '`ls`' \end{verbatim} \section{arc}\indcmd{arc} \begin{verbatim} arc [ item ] [at] radius from to [ with {