Fossil SCM

fossil-scm / extsrc / pikchr.c
Source Blame History 8350 lines
b62f651… stephan 1 /* This file is automatically generated by Lemon from input grammar
f4ec8e0… drh 2 ** source file "pikchr.y".
f4ec8e0… drh 3 */
f4ec8e0… drh 4 /*
dd20f34… drh 5 ** 2000-05-29
dd20f34… drh 6 **
dd20f34… drh 7 ** The author disclaims copyright to this source code. In place of
dd20f34… drh 8 ** a legal notice, here is a blessing:
dd20f34… drh 9 **
dd20f34… drh 10 ** May you do good and not evil.
dd20f34… drh 11 ** May you find forgiveness for yourself and forgive others.
dd20f34… drh 12 ** May you share freely, never taking more than you give.
dd20f34… drh 13 **
dd20f34… drh 14 *************************************************************************
dd20f34… drh 15 ** Driver template for the LEMON parser generator.
dd20f34… drh 16 **
dd20f34… drh 17 ** The "lemon" program processes an LALR(1) input grammar file, then uses
dd20f34… drh 18 ** this template to construct a parser. The "lemon" program inserts text
dd20f34… drh 19 ** at each "%%" line. Also, any "P-a-r-s-e" identifier prefix (without the
dd20f34… drh 20 ** interstitial "-" characters) contained in this template is changed into
dd20f34… drh 21 ** the value of the %name directive from the grammar. Otherwise, the content
dd20f34… drh 22 ** of this template is copied straight through into the generate parser
dd20f34… drh 23 ** source file.
dd20f34… drh 24 **
dd20f34… drh 25 ** The following is the concatenation of all %include directives from the
dd20f34… drh 26 ** input grammar file:
dd20f34… drh 27 */
dd20f34… drh 28 /************ Begin %include sections from the grammar ************************/
dd20f34… drh 29 #line 1 "VERSION.h"
adc7bfc… drh 30 #define MANIFEST_UUID "a7f1c35bc0448daf15e2bafa36e510c1517534e620c452ecb314ed57d974f081"
adc7bfc… drh 31 #define MANIFEST_VERSION "[a7f1c35bc0]"
adc7bfc… drh 32 #define MANIFEST_DATE "2026-04-03 10:29:56"
adc7bfc… drh 33 #define MANIFEST_YEAR "2026"
adc7bfc… drh 34 #define MANIFEST_ISODATE "20260403102956"
adc7bfc… drh 35 #define MANIFEST_NUMERIC_DATE 20260403
adc7bfc… drh 36 #define MANIFEST_NUMERIC_TIME 102956
dd20f34… drh 37 #define RELEASE_VERSION "1.0"
dd20f34… drh 38 #define RELEASE_VERSION_NUMBER 10000
dd20f34… drh 39 #define RELEASE_RESOURCE_VERSION 1,0,0,0
dd20f34… drh 40 #define COMPILER "gcc-13.3.0"
dd20f34… drh 41 #line 2 "pikchr.y"
dd20f34… drh 42
dd20f34… drh 43 /*
b62f651… stephan 44 ** Zero-Clause BSD license:
b62f651… stephan 45 **
b62f651… stephan 46 ** Copyright (C) 2020-09-01 by D. Richard Hipp <[email protected]>
b62f651… stephan 47 **
b62f651… stephan 48 ** Permission to use, copy, modify, and/or distribute this software for
b62f651… stephan 49 ** any purpose with or without fee is hereby granted.
b62f651… stephan 50 **
b62f651… stephan 51 ****************************************************************************
b62f651… stephan 52 **
b62f651… stephan 53 ** This software translates a PIC-inspired diagram language into SVG.
b62f651… stephan 54 **
b62f651… stephan 55 ** PIKCHR (pronounced like "picture") is *mostly* backwards compatible
b62f651… stephan 56 ** with legacy PIC, though some features of legacy PIC are removed
b62f651… stephan 57 ** (for example, the "sh" command is removed for security) and
b62f651… stephan 58 ** many enhancements are added.
b62f651… stephan 59 **
b62f651… stephan 60 ** PIKCHR is designed for use in an internet facing web environment.
b62f651… stephan 61 ** In particular, PIKCHR is designed to safely generate benign SVG from
b62f651… stephan 62 ** source text that provided by a hostile agent.
b62f651… stephan 63 **
b62f651… stephan 64 ** This code was originally written by D. Richard Hipp using documentation
b62f651… stephan 65 ** from prior PIC implementations but without reference to prior code.
b62f651… stephan 66 ** All of the code in this project is original.
b62f651… stephan 67 **
b62f651… stephan 68 ** This file implements a C-language subroutine that accepts a string
b62f651… stephan 69 ** of PIKCHR language text and generates a second string of SVG output that
b62f651… stephan 70 ** renders the drawing defined by the input. Space to hold the returned
b62f651… stephan 71 ** string is obtained from malloc() and should be freed by the caller.
b62f651… stephan 72 ** NULL might be returned if there is a memory allocation error.
b62f651… stephan 73 **
b62f651… stephan 74 ** If there are errors in the PIKCHR input, the output will consist of an
b62f651… stephan 75 ** error message and the original PIKCHR input text (inside of <pre>...</pre>).
b62f651… stephan 76 **
b62f651… stephan 77 ** The subroutine implemented by this file is intended to be stand-alone.
b62f651… stephan 78 ** It uses no external routines other than routines commonly found in
b62f651… stephan 79 ** the standard C library.
b62f651… stephan 80 **
b62f651… stephan 81 ****************************************************************************
b62f651… stephan 82 ** COMPILING:
b62f651… stephan 83 **
b62f651… stephan 84 ** The original source text is a mixture of C99 and "Lemon"
b62f651… stephan 85 ** (See https://sqlite.org/src/file/doc/lemon.html). Lemon is an LALR(1)
b62f651… stephan 86 ** parser generator program, similar to Yacc. The grammar of the
b62f651… stephan 87 ** input language is specified in Lemon. C-code is attached. Lemon
b62f651… stephan 88 ** runs to generate a single output file ("pikchr.c") which is then
b62f651… stephan 89 ** compiled to generate the Pikchr library. This header comment is
b62f651… stephan 90 ** preserved in the Lemon output, so you might be reading this in either
b62f651… stephan 91 ** the generated "pikchr.c" file that is output by Lemon, or in the
b62f651… stephan 92 ** "pikchr.y" source file that is input into Lemon. If you make changes,
b62f651… stephan 93 ** you should change the input source file "pikchr.y", not the
b62f651… stephan 94 ** Lemon-generated output file.
b62f651… stephan 95 **
b62f651… stephan 96 ** Basic compilation steps:
b62f651… stephan 97 **
b62f651… stephan 98 ** lemon pikchr.y
b62f651… stephan 99 ** cc pikchr.c -o pikchr.o
b62f651… stephan 100 **
b62f651… stephan 101 ** Add -DPIKCHR_SHELL to add a main() routine that reads input files
b62f651… stephan 102 ** and sends them through Pikchr, for testing. Add -DPIKCHR_FUZZ for
b62f651… stephan 103 ** -fsanitizer=fuzzer testing.
43eefe6… drh 104 **
b62f651… stephan 105 ****************************************************************************
b62f651… stephan 106 ** IMPLEMENTATION NOTES (for people who want to understand the internal
b62f651… stephan 107 ** operation of this software, perhaps to extend the code or to fix bugs):
b62f651… stephan 108 **
b62f651… stephan 109 ** Each call to pikchr() uses a single instance of the Pik structure to
b62f651… stephan 110 ** track its internal state. The Pik structure lives for the duration
b62f651… stephan 111 ** of the pikchr() call.
b62f651… stephan 112 **
b62f651… stephan 113 ** The input is a sequence of objects or "statements". Each statement is
b62f651… stephan 114 ** parsed into a PObj object. These are stored on an extensible array
b62f651… stephan 115 ** called PList. All parameters to each PObj are computed as the
b62f651… stephan 116 ** object is parsed. (Hence, the parameters to a PObj may only refer
b62f651… stephan 117 ** to prior statements.) Once the PObj is completely assembled, it is
b62f651… stephan 118 ** added to the end of a PList and never changes thereafter - except,
b62f651… stephan 119 ** PObj objects that are part of a "[...]" block might have their
b62f651… stephan 120 ** absolute position shifted when the outer [...] block is positioned.
b62f651… stephan 121 ** But apart from this repositioning, PObj objects are unchanged once
b62f651… stephan 122 ** they are added to the list. The order of statements on a PList does
b62f651… stephan 123 ** not change.
b62f651… stephan 124 **
b62f651… stephan 125 ** After all input has been parsed, the top-level PList is walked to
b62f651… stephan 126 ** generate output. Sub-lists resulting from [...] blocks are scanned
b62f651… stephan 127 ** as they are encountered. All input must be collected and parsed ahead
b62f651… stephan 128 ** of output generation because the size and position of statements must be
b62f651… stephan 129 ** known in order to compute a bounding box on the output.
b62f651… stephan 130 **
b62f651… stephan 131 ** Each PObj is on a "layer". (The common case is that all PObj's are
b62f651… stephan 132 ** on a single layer, but multiple layers are possible.) A separate pass
b62f651… stephan 133 ** is made through the list for each layer.
b62f651… stephan 134 **
b62f651… stephan 135 ** After all output is generated, the Pik object and all the PList
b62f651… stephan 136 ** and PObj objects are deallocated and the generated output string is
b62f651… stephan 137 ** returned. Upon any error, the Pik.nErr flag is set, processing quickly
b62f651… stephan 138 ** stops, and the stack unwinds. No attempt is made to continue reading
b62f651… stephan 139 ** input after an error.
b62f651… stephan 140 **
b62f651… stephan 141 ** Most statements begin with a class name like "box" or "arrow" or "move".
b62f651… stephan 142 ** There is a class named "text" which is used for statements that begin
b62f651… stephan 143 ** with a string literal. You can also specify the "text" class.
b62f651… stephan 144 ** A Sublist ("[...]") is a single object that contains a pointer to
b62f651… stephan 145 ** its substatements, all gathered onto a separate PList object.
b62f651… stephan 146 **
b62f651… stephan 147 ** Variables go into PVar objects that form a linked list.
b62f651… stephan 148 **
b62f651… stephan 149 ** Each PObj has zero or one names. Input constructs that attempt
b62f651… stephan 150 ** to assign a new name from an older name, for example:
b62f651… stephan 151 **
b62f651… stephan 152 ** Abc: Abc + (0.5cm, 0)
b62f651… stephan 153 **
b62f651… stephan 154 ** Statements like these generate a new "noop" object at the specified
b62f651… stephan 155 ** place and with the given name. As place-names are searched by scanning
b62f651… stephan 156 ** the list in reverse order, this has the effect of overriding the "Abc"
b62f651… stephan 157 ** name when referenced by subsequent objects.
b62f651… stephan 158 */
b62f651… stephan 159 #include <stdio.h>
b62f651… stephan 160 #include <stdlib.h>
b62f651… stephan 161 #include <string.h>
b62f651… stephan 162 #include <ctype.h>
b62f651… stephan 163 #include <math.h>
b62f651… stephan 164 #include <assert.h>
b62f651… stephan 165 #define count(X) (sizeof(X)/sizeof(X[0]))
b62f651… stephan 166 #ifndef M_PI
b62f651… stephan 167 # define M_PI 3.1415926535897932385
b62f651… stephan 168 #endif
c6285e1… stephan 169
c6285e1… stephan 170 /*
c6285e1… stephan 171 ** Typesafe version of ctype.h macros. Cygwin requires this, I'm told.
c6285e1… stephan 172 */
c6285e1… stephan 173 #define IsUpper(X) isupper((unsigned char)(X))
c6285e1… stephan 174 #define IsLower(X) islower((unsigned char)(X))
c6285e1… stephan 175 #define ToLower(X) tolower((unsigned char)(X))
c6285e1… stephan 176 #define IsDigit(X) isdigit((unsigned char)(X))
c6285e1… stephan 177 #define IsXDigit(X) isxdigit((unsigned char)(X))
c6285e1… stephan 178 #define IsSpace(X) isspace((unsigned char)(X))
c6285e1… stephan 179 #define IsAlnum(X) isalnum((unsigned char)(X))
c6285e1… stephan 180
f753041… drh 181
f753041… drh 182 /* Limit the number of tokens in a single script to avoid run-away
f753041… drh 183 ** macro expansion attacks. See forum post
f753041… drh 184 ** https://pikchr.org/home/forumpost/ef8684c6955a411a
f753041… drh 185 */
f753041… drh 186 #ifndef PIKCHR_TOKEN_LIMIT
f753041… drh 187 # define PIKCHR_TOKEN_LIMIT 100000
f753041… drh 188 #endif
f753041… drh 189
b62f651… stephan 190
b62f651… stephan 191 /* Tag intentionally unused parameters with this macro to prevent
b62f651… stephan 192 ** compiler warnings with -Wextra */
b62f651… stephan 193 #define UNUSED_PARAMETER(X) (void)(X)
b62f651… stephan 194
b62f651… stephan 195 typedef struct Pik Pik; /* Complete parsing context */
b62f651… stephan 196 typedef struct PToken PToken; /* A single token */
b62f651… stephan 197 typedef struct PObj PObj; /* A single diagram object */
b62f651… stephan 198 typedef struct PList PList; /* A list of diagram objects */
b62f651… stephan 199 typedef struct PClass PClass; /* Description of statements types */
b62f651… stephan 200 typedef double PNum; /* Numeric value */
b62f651… stephan 201 typedef struct PRel PRel; /* Absolute or percentage value */
b62f651… stephan 202 typedef struct PPoint PPoint; /* A position in 2-D space */
b62f651… stephan 203 typedef struct PVar PVar; /* script-defined variable */
b62f651… stephan 204 typedef struct PBox PBox; /* A bounding box */
b62f651… stephan 205 typedef struct PMacro PMacro; /* A "define" macro */
b62f651… stephan 206
b62f651… stephan 207 /* Compass points */
b62f651… stephan 208 #define CP_N 1
b62f651… stephan 209 #define CP_NE 2
b62f651… stephan 210 #define CP_E 3
b62f651… stephan 211 #define CP_SE 4
b62f651… stephan 212 #define CP_S 5
b62f651… stephan 213 #define CP_SW 6
b62f651… stephan 214 #define CP_W 7
b62f651… stephan 215 #define CP_NW 8
b62f651… stephan 216 #define CP_C 9 /* .center or .c */
b62f651… stephan 217 #define CP_END 10 /* .end */
b62f651… stephan 218 #define CP_START 11 /* .start */
b62f651… stephan 219
b62f651… stephan 220 /* Heading angles corresponding to compass points */
b62f651… stephan 221 static const PNum pik_hdg_angle[] = {
b62f651… stephan 222 /* none */ 0.0,
b62f651… stephan 223 /* N */ 0.0,
b62f651… stephan 224 /* NE */ 45.0,
b62f651… stephan 225 /* E */ 90.0,
b62f651… stephan 226 /* SE */ 135.0,
b62f651… stephan 227 /* S */ 180.0,
b62f651… stephan 228 /* SW */ 225.0,
b62f651… stephan 229 /* W */ 270.0,
b62f651… stephan 230 /* NW */ 315.0,
b62f651… stephan 231 /* C */ 0.0,
b62f651… stephan 232 };
b62f651… stephan 233
b62f651… stephan 234 /* Built-in functions */
b62f651… stephan 235 #define FN_ABS 0
b62f651… stephan 236 #define FN_COS 1
b62f651… stephan 237 #define FN_INT 2
b62f651… stephan 238 #define FN_MAX 3
b62f651… stephan 239 #define FN_MIN 4
b62f651… stephan 240 #define FN_SIN 5
b62f651… stephan 241 #define FN_SQRT 6
b62f651… stephan 242
b62f651… stephan 243 /* Text position and style flags. Stored in PToken.eCode so limited
b62f651… stephan 244 ** to 15 bits. */
b62f651… stephan 245 #define TP_LJUST 0x0001 /* left justify...... */
b62f651… stephan 246 #define TP_RJUST 0x0002 /* ...Right justify */
b62f651… stephan 247 #define TP_JMASK 0x0003 /* Mask for justification bits */
b62f651… stephan 248 #define TP_ABOVE2 0x0004 /* Position text way above PObj.ptAt */
b62f651… stephan 249 #define TP_ABOVE 0x0008 /* Position text above PObj.ptAt */
b62f651… stephan 250 #define TP_CENTER 0x0010 /* On the line */
b62f651… stephan 251 #define TP_BELOW 0x0020 /* Position text below PObj.ptAt */
b62f651… stephan 252 #define TP_BELOW2 0x0040 /* Position text way below PObj.ptAt */
b62f651… stephan 253 #define TP_VMASK 0x007c /* Mask for text positioning flags */
b62f651… stephan 254 #define TP_BIG 0x0100 /* Larger font */
b62f651… stephan 255 #define TP_SMALL 0x0200 /* Smaller font */
b62f651… stephan 256 #define TP_XTRA 0x0400 /* Amplify TP_BIG or TP_SMALL */
b62f651… stephan 257 #define TP_SZMASK 0x0700 /* Font size mask */
b62f651… stephan 258 #define TP_ITALIC 0x1000 /* Italic font */
b62f651… stephan 259 #define TP_BOLD 0x2000 /* Bold font */
43eefe6… drh 260 #define TP_MONO 0x4000 /* Monospace font family */
43eefe6… drh 261 #define TP_FMASK 0x7000 /* Mask for font style */
43eefe6… drh 262 #define TP_ALIGN 0x8000 /* Rotate to align with the line */
b62f651… stephan 263
b62f651… stephan 264 /* An object to hold a position in 2-D space */
b62f651… stephan 265 struct PPoint {
b62f651… stephan 266 PNum x, y; /* X and Y coordinates */
b62f651… stephan 267 };
b62f651… stephan 268 static const PPoint cZeroPoint = {0.0,0.0};
b62f651… stephan 269
b62f651… stephan 270 /* A bounding box */
b62f651… stephan 271 struct PBox {
b62f651… stephan 272 PPoint sw, ne; /* Lower-left and top-right corners */
b62f651… stephan 273 };
b62f651… stephan 274
b62f651… stephan 275 /* An Absolute or a relative distance. The absolute distance
b62f651… stephan 276 ** is stored in rAbs and the relative distance is stored in rRel.
b62f651… stephan 277 ** Usually, one or the other will be 0.0. When using a PRel to
b62f651… stephan 278 ** update an existing value, the computation is usually something
b62f651… stephan 279 ** like this:
b62f651… stephan 280 **
b62f651… stephan 281 ** value = PRel.rAbs + value*PRel.rRel
b62f651… stephan 282 **
b62f651… stephan 283 */
b62f651… stephan 284 struct PRel {
b62f651… stephan 285 PNum rAbs; /* Absolute value */
b62f651… stephan 286 PNum rRel; /* Value relative to current value */
b62f651… stephan 287 };
b62f651… stephan 288
b62f651… stephan 289 /* A variable created by the ID = EXPR construct of the PIKCHR script
b62f651… stephan 290 **
b62f651… stephan 291 ** PIKCHR (and PIC) scripts do not use many varaibles, so it is reasonable
b62f651… stephan 292 ** to store them all on a linked list.
b62f651… stephan 293 */
b62f651… stephan 294 struct PVar {
b62f651… stephan 295 const char *zName; /* Name of the variable */
b62f651… stephan 296 PNum val; /* Value of the variable */
b62f651… stephan 297 PVar *pNext; /* Next variable in a list of them all */
b62f651… stephan 298 };
b62f651… stephan 299
b62f651… stephan 300 /* A single token in the parser input stream
b62f651… stephan 301 */
b62f651… stephan 302 struct PToken {
b62f651… stephan 303 const char *z; /* Pointer to the token text */
b62f651… stephan 304 unsigned int n; /* Length of the token in bytes */
b62f651… stephan 305 short int eCode; /* Auxiliary code */
b62f651… stephan 306 unsigned char eType; /* The numeric parser code */
b62f651… stephan 307 unsigned char eEdge; /* Corner value for corner keywords */
b62f651… stephan 308 };
b62f651… stephan 309
b62f651… stephan 310 /* Return negative, zero, or positive if pToken is less than, equal to
b62f651… stephan 311 ** or greater than the zero-terminated string z[]
b62f651… stephan 312 */
b62f651… stephan 313 static int pik_token_eq(PToken *pToken, const char *z){
b62f651… stephan 314 int c = strncmp(pToken->z,z,pToken->n);
b62f651… stephan 315 if( c==0 && z[pToken->n]!=0 ) c = -1;
b62f651… stephan 316 return c;
b62f651… stephan 317 }
b62f651… stephan 318
b62f651… stephan 319 /* Extra token types not generated by LEMON but needed by the
b62f651… stephan 320 ** tokenizer
b62f651… stephan 321 */
b62f651… stephan 322 #define T_PARAMETER 253 /* $1, $2, ..., $9 */
390e001… drh 323 #define T_WHITESPACE 254 /* Whitespace or comments */
b62f651… stephan 324 #define T_ERROR 255 /* Any text that is not a valid token */
b62f651… stephan 325
b62f651… stephan 326 /* Directions of movement */
b62f651… stephan 327 #define DIR_RIGHT 0
b62f651… stephan 328 #define DIR_DOWN 1
b62f651… stephan 329 #define DIR_LEFT 2
b62f651… stephan 330 #define DIR_UP 3
b62f651… stephan 331 #define ValidDir(X) ((X)>=0 && (X)<=3)
b62f651… stephan 332 #define IsUpDown(X) (((X)&1)==1)
b62f651… stephan 333 #define IsLeftRight(X) (((X)&1)==0)
b62f651… stephan 334
b62f651… stephan 335 /* Bitmask for the various attributes for PObj. These bits are
b62f651… stephan 336 ** collected in PObj.mProp and PObj.mCalc to check for constraint
b62f651… stephan 337 ** errors. */
b62f651… stephan 338 #define A_WIDTH 0x0001
b62f651… stephan 339 #define A_HEIGHT 0x0002
b62f651… stephan 340 #define A_RADIUS 0x0004
b62f651… stephan 341 #define A_THICKNESS 0x0008
b62f651… stephan 342 #define A_DASHED 0x0010 /* Includes "dotted" */
b62f651… stephan 343 #define A_FILL 0x0020
b62f651… stephan 344 #define A_COLOR 0x0040
b62f651… stephan 345 #define A_ARROW 0x0080
b62f651… stephan 346 #define A_FROM 0x0100
b62f651… stephan 347 #define A_CW 0x0200
b62f651… stephan 348 #define A_AT 0x0400
b62f651… stephan 349 #define A_TO 0x0800 /* one or more movement attributes */
b62f651… stephan 350 #define A_FIT 0x1000
b62f651… stephan 351
b62f651… stephan 352
b62f651… stephan 353 /* A single graphics object */
b62f651… stephan 354 struct PObj {
b62f651… stephan 355 const PClass *type; /* Object type or class */
b62f651… stephan 356 PToken errTok; /* Reference token for error messages */
b62f651… stephan 357 PPoint ptAt; /* Reference point for the object */
b62f651… stephan 358 PPoint ptEnter, ptExit; /* Entry and exit points */
b62f651… stephan 359 PList *pSublist; /* Substructure for [...] objects */
b62f651… stephan 360 char *zName; /* Name assigned to this statement */
b62f651… stephan 361 PNum w; /* "width" property */
b62f651… stephan 362 PNum h; /* "height" property */
b62f651… stephan 363 PNum rad; /* "radius" property */
b62f651… stephan 364 PNum sw; /* "thickness" property. (Mnemonic: "stroke width")*/
b62f651… stephan 365 PNum dotted; /* "dotted" property. <=0.0 for off */
b62f651… stephan 366 PNum dashed; /* "dashed" property. <=0.0 for off */
b62f651… stephan 367 PNum fill; /* "fill" property. Negative for off */
b62f651… stephan 368 PNum color; /* "color" property */
b62f651… stephan 369 PPoint with; /* Position constraint from WITH clause */
b62f651… stephan 370 char eWith; /* Type of heading point on WITH clause */
b62f651… stephan 371 char cw; /* True for clockwise arc */
b62f651… stephan 372 char larrow; /* Arrow at beginning (<- or <->) */
b62f651… stephan 373 char rarrow; /* Arrow at end (-> or <->) */
b62f651… stephan 374 char bClose; /* True if "close" is seen */
b62f651… stephan 375 char bChop; /* True if "chop" is seen */
f4ec8e0… drh 376 char bAltAutoFit; /* Always send both h and w into xFit() */
b62f651… stephan 377 unsigned char nTxt; /* Number of text values */
b62f651… stephan 378 unsigned mProp; /* Masks of properties set so far */
b62f651… stephan 379 unsigned mCalc; /* Values computed from other constraints */
b62f651… stephan 380 PToken aTxt[5]; /* Text with .eCode holding TP flags */
b62f651… stephan 381 int iLayer; /* Rendering order */
b62f651… stephan 382 int inDir, outDir; /* Entry and exit directions */
b62f651… stephan 383 int nPath; /* Number of path points */
b62f651… stephan 384 PPoint *aPath; /* Array of path points */
b62f651… stephan 385 PObj *pFrom, *pTo; /* End-point objects of a path */
b62f651… stephan 386 PBox bbox; /* Bounding box */
b62f651… stephan 387 };
b62f651… stephan 388
b62f651… stephan 389 /* A list of graphics objects */
b62f651… stephan 390 struct PList {
b62f651… stephan 391 int n; /* Number of statements in the list */
b62f651… stephan 392 int nAlloc; /* Allocated slots in a[] */
b62f651… stephan 393 PObj **a; /* Pointers to individual objects */
b62f651… stephan 394 };
b62f651… stephan 395
b62f651… stephan 396 /* A macro definition */
b62f651… stephan 397 struct PMacro {
b62f651… stephan 398 PMacro *pNext; /* Next in the list */
b62f651… stephan 399 PToken macroName; /* Name of the macro */
b62f651… stephan 400 PToken macroBody; /* Body of the macro */
b62f651… stephan 401 int inUse; /* Do not allow recursion */
b62f651… stephan 402 };
b62f651… stephan 403
b62f651… stephan 404 /* Each call to the pikchr() subroutine uses an instance of the following
b62f651… stephan 405 ** object to pass around context to all of its subroutines.
b62f651… stephan 406 */
b62f651… stephan 407 struct Pik {
b62f651… stephan 408 unsigned nErr; /* Number of errors seen */
f753041… drh 409 unsigned nToken; /* Number of tokens parsed */
b62f651… stephan 410 PToken sIn; /* Input Pikchr-language text */
b62f651… stephan 411 char *zOut; /* Result accumulates here */
b62f651… stephan 412 unsigned int nOut; /* Bytes written to zOut[] so far */
b62f651… stephan 413 unsigned int nOutAlloc; /* Space allocated to zOut[] */
b62f651… stephan 414 unsigned char eDir; /* Current direction */
b62f651… stephan 415 unsigned int mFlags; /* Flags passed to pikchr() */
b62f651… stephan 416 PObj *cur; /* Object under construction */
b62f651… stephan 417 PObj *lastRef; /* Last object references by name */
b62f651… stephan 418 PList *list; /* Object list under construction */
b62f651… stephan 419 PMacro *pMacros; /* List of all defined macros */
b62f651… stephan 420 PVar *pVar; /* Application-defined variables */
b62f651… stephan 421 PBox bbox; /* Bounding box around all statements */
b62f651… stephan 422 /* Cache of layout values. <=0.0 for unknown... */
b62f651… stephan 423 PNum rScale; /* Multiply to convert inches to pixels */
b62f651… stephan 424 PNum fontScale; /* Scale fonts by this percent */
b62f651… stephan 425 PNum charWidth; /* Character width */
b62f651… stephan 426 PNum charHeight; /* Character height */
b62f651… stephan 427 PNum wArrow; /* Width of arrowhead at the fat end */
b62f651… stephan 428 PNum hArrow; /* Ht of arrowhead - dist from tip to fat end */
b62f651… stephan 429 char bLayoutVars; /* True if cache is valid */
b62f651… stephan 430 char thenFlag; /* True if "then" seen */
b62f651… stephan 431 char samePath; /* aTPath copied by "same" */
b62f651… stephan 432 const char *zClass; /* Class name for the <svg> */
b62f651… stephan 433 int wSVG, hSVG; /* Width and height of the <svg> */
b62f651… stephan 434 int fgcolor; /* foreground color value, or -1 for none */
b62f651… stephan 435 int bgcolor; /* background color value, or -1 for none */
b62f651… stephan 436 /* Paths for lines are constructed here first, then transferred into
b62f651… stephan 437 ** the PObj object at the end: */
b62f651… stephan 438 int nTPath; /* Number of entries on aTPath[] */
b62f651… stephan 439 int mTPath; /* For last entry, 1: x set, 2: y set */
b62f651… stephan 440 PPoint aTPath[1000]; /* Path under construction */
b62f651… stephan 441 /* Error contexts */
b62f651… stephan 442 unsigned int nCtx; /* Number of error contexts */
b62f651… stephan 443 PToken aCtx[10]; /* Nested error contexts */
b62f651… stephan 444 };
b62f651… stephan 445
b62f651… stephan 446 /* Include PIKCHR_PLAINTEXT_ERRORS among the bits of mFlags on the 3rd
b62f651… stephan 447 ** argument to pikchr() in order to cause error message text to come out
b62f651… stephan 448 ** as text/plain instead of as text/html
b62f651… stephan 449 */
b62f651… stephan 450 #define PIKCHR_PLAINTEXT_ERRORS 0x0001
b62f651… stephan 451
b62f651… stephan 452 /* Include PIKCHR_DARK_MODE among the mFlag bits to invert colors.
b62f651… stephan 453 */
b62f651… stephan 454 #define PIKCHR_DARK_MODE 0x0002
b62f651… stephan 455
b62f651… stephan 456 /*
b62f651… stephan 457 ** The behavior of an object class is defined by an instance of
b62f651… stephan 458 ** this structure. This is the "virtual method" table.
b62f651… stephan 459 */
b62f651… stephan 460 struct PClass {
b62f651… stephan 461 const char *zName; /* Name of class */
b62f651… stephan 462 char isLine; /* True if a line class */
b62f651… stephan 463 char eJust; /* Use box-style text justification */
b62f651… stephan 464 void (*xInit)(Pik*,PObj*); /* Initializer */
b62f651… stephan 465 void (*xNumProp)(Pik*,PObj*,PToken*); /* Value change notification */
b62f651… stephan 466 void (*xCheck)(Pik*,PObj*); /* Checks to do after parsing */
b62f651… stephan 467 PPoint (*xChop)(Pik*,PObj*,PPoint*); /* Chopper */
b62f651… stephan 468 PPoint (*xOffset)(Pik*,PObj*,int); /* Offset from .c to edge point */
b62f651… stephan 469 void (*xFit)(Pik*,PObj*,PNum w,PNum h); /* Size to fit text */
b62f651… stephan 470 void (*xRender)(Pik*,PObj*); /* Render */
b62f651… stephan 471 };
b62f651… stephan 472
b62f651… stephan 473
b62f651… stephan 474 /* Forward declarations */
b62f651… stephan 475 static void pik_append(Pik*, const char*,int);
b62f651… stephan 476 static void pik_append_text(Pik*,const char*,int,int);
b62f651… stephan 477 static void pik_append_num(Pik*,const char*,PNum);
b62f651… stephan 478 static void pik_append_point(Pik*,const char*,PPoint*);
b62f651… stephan 479 static void pik_append_x(Pik*,const char*,PNum,const char*);
b62f651… stephan 480 static void pik_append_y(Pik*,const char*,PNum,const char*);
b62f651… stephan 481 static void pik_append_xy(Pik*,const char*,PNum,PNum);
b62f651… stephan 482 static void pik_append_dis(Pik*,const char*,PNum,const char*);
b62f651… stephan 483 static void pik_append_arc(Pik*,PNum,PNum,PNum,PNum);
b62f651… stephan 484 static void pik_append_clr(Pik*,const char*,PNum,const char*,int);
b62f651… stephan 485 static void pik_append_style(Pik*,PObj*,int);
b62f651… stephan 486 static void pik_append_txt(Pik*,PObj*, PBox*);
b62f651… stephan 487 static void pik_draw_arrowhead(Pik*,PPoint*pFrom,PPoint*pTo,PObj*);
b62f651… stephan 488 static void pik_chop(PPoint*pFrom,PPoint*pTo,PNum);
b62f651… stephan 489 static void pik_error(Pik*,PToken*,const char*);
b62f651… stephan 490 static void pik_elist_free(Pik*,PList*);
b62f651… stephan 491 static void pik_elem_free(Pik*,PObj*);
b62f651… stephan 492 static void pik_render(Pik*,PList*);
b62f651… stephan 493 static PList *pik_elist_append(Pik*,PList*,PObj*);
b62f651… stephan 494 static PObj *pik_elem_new(Pik*,PToken*,PToken*,PList*);
b62f651… stephan 495 static void pik_set_direction(Pik*,int);
b62f651… stephan 496 static void pik_elem_setname(Pik*,PObj*,PToken*);
b62f651… stephan 497 static int pik_round(PNum);
b62f651… stephan 498 static void pik_set_var(Pik*,PToken*,PNum,PToken*);
b62f651… stephan 499 static PNum pik_value(Pik*,const char*,int,int*);
b62f651… stephan 500 static int pik_value_int(Pik*,const char*,int,int*);
b62f651… stephan 501 static PNum pik_lookup_color(Pik*,PToken*);
b62f651… stephan 502 static PNum pik_get_var(Pik*,PToken*);
b62f651… stephan 503 static PNum pik_atof(PToken*);
b62f651… stephan 504 static void pik_after_adding_attributes(Pik*,PObj*);
b62f651… stephan 505 static void pik_elem_move(PObj*,PNum dx, PNum dy);
b62f651… stephan 506 static void pik_elist_move(PList*,PNum dx, PNum dy);
b62f651… stephan 507 static void pik_set_numprop(Pik*,PToken*,PRel*);
b62f651… stephan 508 static void pik_set_clrprop(Pik*,PToken*,PNum);
b62f651… stephan 509 static void pik_set_dashed(Pik*,PToken*,PNum*);
b62f651… stephan 510 static void pik_then(Pik*,PToken*,PObj*);
b62f651… stephan 511 static void pik_add_direction(Pik*,PToken*,PRel*);
b62f651… stephan 512 static void pik_move_hdg(Pik*,PRel*,PToken*,PNum,PToken*,PToken*);
b62f651… stephan 513 static void pik_evenwith(Pik*,PToken*,PPoint*);
b62f651… stephan 514 static void pik_set_from(Pik*,PObj*,PToken*,PPoint*);
b62f651… stephan 515 static void pik_add_to(Pik*,PObj*,PToken*,PPoint*);
b62f651… stephan 516 static void pik_close_path(Pik*,PToken*);
b62f651… stephan 517 static void pik_set_at(Pik*,PToken*,PPoint*,PToken*);
b62f651… stephan 518 static short int pik_nth_value(Pik*,PToken*);
b62f651… stephan 519 static PObj *pik_find_nth(Pik*,PObj*,PToken*);
b62f651… stephan 520 static PObj *pik_find_byname(Pik*,PObj*,PToken*);
b62f651… stephan 521 static PPoint pik_place_of_elem(Pik*,PObj*,PToken*);
b62f651… stephan 522 static int pik_bbox_isempty(PBox*);
b62f651… stephan 523 static int pik_bbox_contains_point(PBox*,PPoint*);
b62f651… stephan 524 static void pik_bbox_init(PBox*);
b62f651… stephan 525 static void pik_bbox_addbox(PBox*,PBox*);
b62f651… stephan 526 static void pik_bbox_add_xy(PBox*,PNum,PNum);
b62f651… stephan 527 static void pik_bbox_addellipse(PBox*,PNum x,PNum y,PNum rx,PNum ry);
b62f651… stephan 528 static void pik_add_txt(Pik*,PToken*,int);
43eefe6… drh 529 static int pik_text_length(const PToken *pToken, const int isMonospace);
c32f97e… drh 530 static void pik_size_to_fit(Pik*,PObj*,PToken*,int);
b62f651… stephan 531 static int pik_text_position(int,PToken*);
b62f651… stephan 532 static PNum pik_property_of(PObj*,PToken*);
b62f651… stephan 533 static PNum pik_func(Pik*,PToken*,PNum,PNum);
b62f651… stephan 534 static PPoint pik_position_between(PNum x, PPoint p1, PPoint p2);
b62f651… stephan 535 static PPoint pik_position_at_angle(PNum dist, PNum r, PPoint pt);
b62f651… stephan 536 static PPoint pik_position_at_hdg(PNum dist, PToken *pD, PPoint pt);
b62f651… stephan 537 static void pik_same(Pik *p, PObj*, PToken*);
b62f651… stephan 538 static PPoint pik_nth_vertex(Pik *p, PToken *pNth, PToken *pErr, PObj *pObj);
b62f651… stephan 539 static PToken pik_next_semantic_token(PToken *pThis);
b62f651… stephan 540 static void pik_compute_layout_settings(Pik*);
b62f651… stephan 541 static void pik_behind(Pik*,PObj*);
b62f651… stephan 542 static PObj *pik_assert(Pik*,PNum,PToken*,PNum);
b62f651… stephan 543 static PObj *pik_position_assert(Pik*,PPoint*,PToken*,PPoint*);
b62f651… stephan 544 static PNum pik_dist(PPoint*,PPoint*);
b62f651… stephan 545 static void pik_add_macro(Pik*,PToken *pId,PToken *pCode);
b62f651… stephan 546
b62f651… stephan 547
dd20f34… drh 548 #line 549 "pikchr.c"
b62f651… stephan 549 /**************** End of %include directives **********************************/
b62f651… stephan 550 /* These constants specify the various numeric values for terminal symbols.
b62f651… stephan 551 ***************** Begin token definitions *************************************/
b62f651… stephan 552 #ifndef T_ID
b62f651… stephan 553 #define T_ID 1
b62f651… stephan 554 #define T_EDGEPT 2
b62f651… stephan 555 #define T_OF 3
b62f651… stephan 556 #define T_PLUS 4
b62f651… stephan 557 #define T_MINUS 5
b62f651… stephan 558 #define T_STAR 6
b62f651… stephan 559 #define T_SLASH 7
b62f651… stephan 560 #define T_PERCENT 8
b62f651… stephan 561 #define T_UMINUS 9
b62f651… stephan 562 #define T_EOL 10
b62f651… stephan 563 #define T_ASSIGN 11
b62f651… stephan 564 #define T_PLACENAME 12
b62f651… stephan 565 #define T_COLON 13
b62f651… stephan 566 #define T_ASSERT 14
b62f651… stephan 567 #define T_LP 15
b62f651… stephan 568 #define T_EQ 16
b62f651… stephan 569 #define T_RP 17
b62f651… stephan 570 #define T_DEFINE 18
b62f651… stephan 571 #define T_CODEBLOCK 19
b62f651… stephan 572 #define T_FILL 20
b62f651… stephan 573 #define T_COLOR 21
b62f651… stephan 574 #define T_THICKNESS 22
b62f651… stephan 575 #define T_PRINT 23
b62f651… stephan 576 #define T_STRING 24
b62f651… stephan 577 #define T_COMMA 25
dd20f34… drh 578 #define T_ISODATE 26
dd20f34… drh 579 #define T_CLASSNAME 27
dd20f34… drh 580 #define T_LB 28
dd20f34… drh 581 #define T_RB 29
dd20f34… drh 582 #define T_UP 30
dd20f34… drh 583 #define T_DOWN 31
dd20f34… drh 584 #define T_LEFT 32
dd20f34… drh 585 #define T_RIGHT 33
dd20f34… drh 586 #define T_CLOSE 34
dd20f34… drh 587 #define T_CHOP 35
dd20f34… drh 588 #define T_FROM 36
dd20f34… drh 589 #define T_TO 37
dd20f34… drh 590 #define T_THEN 38
dd20f34… drh 591 #define T_HEADING 39
dd20f34… drh 592 #define T_GO 40
dd20f34… drh 593 #define T_AT 41
dd20f34… drh 594 #define T_WITH 42
dd20f34… drh 595 #define T_SAME 43
dd20f34… drh 596 #define T_AS 44
dd20f34… drh 597 #define T_FIT 45
dd20f34… drh 598 #define T_BEHIND 46
dd20f34… drh 599 #define T_UNTIL 47
dd20f34… drh 600 #define T_EVEN 48
dd20f34… drh 601 #define T_DOT_E 49
dd20f34… drh 602 #define T_HEIGHT 50
dd20f34… drh 603 #define T_WIDTH 51
dd20f34… drh 604 #define T_RADIUS 52
dd20f34… drh 605 #define T_DIAMETER 53
dd20f34… drh 606 #define T_DOTTED 54
dd20f34… drh 607 #define T_DASHED 55
dd20f34… drh 608 #define T_CW 56
dd20f34… drh 609 #define T_CCW 57
dd20f34… drh 610 #define T_LARROW 58
dd20f34… drh 611 #define T_RARROW 59
dd20f34… drh 612 #define T_LRARROW 60
dd20f34… drh 613 #define T_INVIS 61
dd20f34… drh 614 #define T_THICK 62
dd20f34… drh 615 #define T_THIN 63
dd20f34… drh 616 #define T_SOLID 64
dd20f34… drh 617 #define T_CENTER 65
dd20f34… drh 618 #define T_LJUST 66
dd20f34… drh 619 #define T_RJUST 67
dd20f34… drh 620 #define T_ABOVE 68
dd20f34… drh 621 #define T_BELOW 69
dd20f34… drh 622 #define T_ITALIC 70
dd20f34… drh 623 #define T_BOLD 71
dd20f34… drh 624 #define T_MONO 72
dd20f34… drh 625 #define T_ALIGNED 73
dd20f34… drh 626 #define T_BIG 74
dd20f34… drh 627 #define T_SMALL 75
dd20f34… drh 628 #define T_AND 76
dd20f34… drh 629 #define T_LT 77
dd20f34… drh 630 #define T_GT 78
dd20f34… drh 631 #define T_ON 79
dd20f34… drh 632 #define T_WAY 80
dd20f34… drh 633 #define T_BETWEEN 81
dd20f34… drh 634 #define T_THE 82
dd20f34… drh 635 #define T_NTH 83
dd20f34… drh 636 #define T_VERTEX 84
dd20f34… drh 637 #define T_TOP 85
dd20f34… drh 638 #define T_BOTTOM 86
dd20f34… drh 639 #define T_START 87
dd20f34… drh 640 #define T_END 88
dd20f34… drh 641 #define T_IN 89
dd20f34… drh 642 #define T_THIS 90
dd20f34… drh 643 #define T_DOT_U 91
dd20f34… drh 644 #define T_LAST 92
dd20f34… drh 645 #define T_NUMBER 93
dd20f34… drh 646 #define T_FUNC1 94
dd20f34… drh 647 #define T_FUNC2 95
dd20f34… drh 648 #define T_DIST 96
dd20f34… drh 649 #define T_DOT_XY 97
dd20f34… drh 650 #define T_X 98
dd20f34… drh 651 #define T_Y 99
dd20f34… drh 652 #define T_DOT_L 100
b62f651… stephan 653 #endif
b62f651… stephan 654 /**************** End token definitions ***************************************/
b62f651… stephan 655
b62f651… stephan 656 /* The next sections is a series of control #defines.
b62f651… stephan 657 ** various aspects of the generated parser.
b62f651… stephan 658 ** YYCODETYPE is the data type used to store the integer codes
b62f651… stephan 659 ** that represent terminal and non-terminal symbols.
b62f651… stephan 660 ** "unsigned char" is used if there are fewer than
b62f651… stephan 661 ** 256 symbols. Larger types otherwise.
b62f651… stephan 662 ** YYNOCODE is a number of type YYCODETYPE that is not used for
b62f651… stephan 663 ** any terminal or nonterminal symbol.
b62f651… stephan 664 ** YYFALLBACK If defined, this indicates that one or more tokens
b62f651… stephan 665 ** (also known as: "terminal symbols") have fall-back
b62f651… stephan 666 ** values which should be used if the original symbol
b62f651… stephan 667 ** would not parse. This permits keywords to sometimes
b62f651… stephan 668 ** be used as identifiers, for example.
b62f651… stephan 669 ** YYACTIONTYPE is the data type used for "action codes" - numbers
b62f651… stephan 670 ** that indicate what to do in response to the next
b62f651… stephan 671 ** token.
b62f651… stephan 672 ** pik_parserTOKENTYPE is the data type used for minor type for terminal
b62f651… stephan 673 ** symbols. Background: A "minor type" is a semantic
b62f651… stephan 674 ** value associated with a terminal or non-terminal
b62f651… stephan 675 ** symbols. For example, for an "ID" terminal symbol,
b62f651… stephan 676 ** the minor type might be the name of the identifier.
b62f651… stephan 677 ** Each non-terminal can have a different minor type.
b62f651… stephan 678 ** Terminal symbols all have the same minor type, though.
b62f651… stephan 679 ** This macros defines the minor type for terminal
b62f651… stephan 680 ** symbols.
b62f651… stephan 681 ** YYMINORTYPE is the data type used for all minor types.
b62f651… stephan 682 ** This is typically a union of many types, one of
b62f651… stephan 683 ** which is pik_parserTOKENTYPE. The entry in the union
b62f651… stephan 684 ** for terminal symbols is called "yy0".
b62f651… stephan 685 ** YYSTACKDEPTH is the maximum depth of the parser's stack. If
b62f651… stephan 686 ** zero the stack is dynamically sized using realloc()
b62f651… stephan 687 ** pik_parserARG_SDECL A static variable declaration for the %extra_argument
b62f651… stephan 688 ** pik_parserARG_PDECL A parameter declaration for the %extra_argument
b62f651… stephan 689 ** pik_parserARG_PARAM Code to pass %extra_argument as a subroutine parameter
b62f651… stephan 690 ** pik_parserARG_STORE Code to store %extra_argument into yypParser
b62f651… stephan 691 ** pik_parserARG_FETCH Code to extract %extra_argument from yypParser
b62f651… stephan 692 ** pik_parserCTX_* As pik_parserARG_ except for %extra_context
f4ec8e0… drh 693 ** YYREALLOC Name of the realloc() function to use
f4ec8e0… drh 694 ** YYFREE Name of the free() function to use
f4ec8e0… drh 695 ** YYDYNSTACK True if stack space should be extended on heap
b62f651… stephan 696 ** YYERRORSYMBOL is the code number of the error symbol. If not
b62f651… stephan 697 ** defined, then do no error processing.
b62f651… stephan 698 ** YYNSTATE the combined number of states.
b62f651… stephan 699 ** YYNRULE the number of rules in the grammar
b62f651… stephan 700 ** YYNTOKEN Number of terminal symbols
b62f651… stephan 701 ** YY_MAX_SHIFT Maximum value for shift actions
b62f651… stephan 702 ** YY_MIN_SHIFTREDUCE Minimum value for shift-reduce actions
b62f651… stephan 703 ** YY_MAX_SHIFTREDUCE Maximum value for shift-reduce actions
b62f651… stephan 704 ** YY_ERROR_ACTION The yy_action[] code for syntax error
b62f651… stephan 705 ** YY_ACCEPT_ACTION The yy_action[] code for accept
b62f651… stephan 706 ** YY_NO_ACTION The yy_action[] code for no-op
b62f651… stephan 707 ** YY_MIN_REDUCE Minimum value for reduce actions
b62f651… stephan 708 ** YY_MAX_REDUCE Maximum value for reduce actions
f4ec8e0… drh 709 ** YY_MIN_DSTRCTR Minimum symbol value that has a destructor
f4ec8e0… drh 710 ** YY_MAX_DSTRCTR Maximum symbol value that has a destructor
b62f651… stephan 711 */
b62f651… stephan 712 #ifndef INTERFACE
b62f651… stephan 713 # define INTERFACE 1
b62f651… stephan 714 #endif
b62f651… stephan 715 /************* Begin control #defines *****************************************/
b62f651… stephan 716 #define YYCODETYPE unsigned char
dd20f34… drh 717 #define YYNOCODE 138
b62f651… stephan 718 #define YYACTIONTYPE unsigned short int
b62f651… stephan 719 #define pik_parserTOKENTYPE PToken
b62f651… stephan 720 typedef union {
b62f651… stephan 721 int yyinit;
b62f651… stephan 722 pik_parserTOKENTYPE yy0;
dd20f34… drh 723 PList* yy23;
dd20f34… drh 724 PRel yy28;
dd20f34… drh 725 PObj* yy54;
dd20f34… drh 726 PNum yy129;
dd20f34… drh 727 PPoint yy187;
dd20f34… drh 728 short int yy272;
b62f651… stephan 729 } YYMINORTYPE;
b62f651… stephan 730 #ifndef YYSTACKDEPTH
b62f651… stephan 731 #define YYSTACKDEPTH 100
b62f651… stephan 732 #endif
b62f651… stephan 733 #define pik_parserARG_SDECL
b62f651… stephan 734 #define pik_parserARG_PDECL
b62f651… stephan 735 #define pik_parserARG_PARAM
b62f651… stephan 736 #define pik_parserARG_FETCH
b62f651… stephan 737 #define pik_parserARG_STORE
f4ec8e0… drh 738 #define YYREALLOC realloc
f4ec8e0… drh 739 #define YYFREE free
f4ec8e0… drh 740 #define YYDYNSTACK 0
b62f651… stephan 741 #define pik_parserCTX_SDECL Pik *p;
b62f651… stephan 742 #define pik_parserCTX_PDECL ,Pik *p
b62f651… stephan 743 #define pik_parserCTX_PARAM ,p
b62f651… stephan 744 #define pik_parserCTX_FETCH Pik *p=yypParser->p;
b62f651… stephan 745 #define pik_parserCTX_STORE yypParser->p=p;
b62f651… stephan 746 #define YYFALLBACK 1
b62f651… stephan 747 #define YYNSTATE 164
b62f651… stephan 748 #define YYNRULE 156
b62f651… stephan 749 #define YYNRULE_WITH_ACTION 116
dd20f34… drh 750 #define YYNTOKEN 101
b62f651… stephan 751 #define YY_MAX_SHIFT 163
b62f651… stephan 752 #define YY_MIN_SHIFTREDUCE 287
b62f651… stephan 753 #define YY_MAX_SHIFTREDUCE 442
b62f651… stephan 754 #define YY_ERROR_ACTION 443
b62f651… stephan 755 #define YY_ACCEPT_ACTION 444
b62f651… stephan 756 #define YY_NO_ACTION 445
b62f651… stephan 757 #define YY_MIN_REDUCE 446
b62f651… stephan 758 #define YY_MAX_REDUCE 601
dd20f34… drh 759 #define YY_MIN_DSTRCTR 101
dd20f34… drh 760 #define YY_MAX_DSTRCTR 104
b62f651… stephan 761 /************* End control #defines *******************************************/
b62f651… stephan 762 #define YY_NLOOKAHEAD ((int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])))
b62f651… stephan 763
b62f651… stephan 764 /* Define the yytestcase() macro to be a no-op if is not already defined
b62f651… stephan 765 ** otherwise.
b62f651… stephan 766 **
b62f651… stephan 767 ** Applications can choose to define yytestcase() in the %include section
b62f651… stephan 768 ** to a macro that can assist in verifying code coverage. For production
b62f651… stephan 769 ** code the yytestcase() macro should be turned off. But it is useful
b62f651… stephan 770 ** for testing.
b62f651… stephan 771 */
b62f651… stephan 772 #ifndef yytestcase
b62f651… stephan 773 # define yytestcase(X)
f4ec8e0… drh 774 #endif
f4ec8e0… drh 775
f4ec8e0… drh 776 /* Macro to determine if stack space has the ability to grow using
f4ec8e0… drh 777 ** heap memory.
f4ec8e0… drh 778 */
f4ec8e0… drh 779 #if YYSTACKDEPTH<=0 || YYDYNSTACK
f4ec8e0… drh 780 # define YYGROWABLESTACK 1
f4ec8e0… drh 781 #else
f4ec8e0… drh 782 # define YYGROWABLESTACK 0
f4ec8e0… drh 783 #endif
f4ec8e0… drh 784
f4ec8e0… drh 785 /* Guarantee a minimum number of initial stack slots.
f4ec8e0… drh 786 */
f4ec8e0… drh 787 #if YYSTACKDEPTH<=0
f4ec8e0… drh 788 # undef YYSTACKDEPTH
f4ec8e0… drh 789 # define YYSTACKDEPTH 2 /* Need a minimum stack size */
b62f651… stephan 790 #endif
b62f651… stephan 791
b62f651… stephan 792
b62f651… stephan 793 /* Next are the tables used to determine what action to take based on the
b62f651… stephan 794 ** current state and lookahead token. These tables are used to implement
b62f651… stephan 795 ** functions that take a state number and lookahead value and return an
b62f651… stephan 796 ** action integer.
b62f651… stephan 797 **
b62f651… stephan 798 ** Suppose the action integer is N. Then the action is determined as
b62f651… stephan 799 ** follows
b62f651… stephan 800 **
b62f651… stephan 801 ** 0 <= N <= YY_MAX_SHIFT Shift N. That is, push the lookahead
b62f651… stephan 802 ** token onto the stack and goto state N.
b62f651… stephan 803 **
b62f651… stephan 804 ** N between YY_MIN_SHIFTREDUCE Shift to an arbitrary state then
b62f651… stephan 805 ** and YY_MAX_SHIFTREDUCE reduce by rule N-YY_MIN_SHIFTREDUCE.
b62f651… stephan 806 **
b62f651… stephan 807 ** N == YY_ERROR_ACTION A syntax error has occurred.
b62f651… stephan 808 **
b62f651… stephan 809 ** N == YY_ACCEPT_ACTION The parser accepts its input.
b62f651… stephan 810 **
b62f651… stephan 811 ** N == YY_NO_ACTION No such action. Denotes unused
b62f651… stephan 812 ** slots in the yy_action[] table.
b62f651… stephan 813 **
b62f651… stephan 814 ** N between YY_MIN_REDUCE Reduce by rule N-YY_MIN_REDUCE
b62f651… stephan 815 ** and YY_MAX_REDUCE
b62f651… stephan 816 **
b62f651… stephan 817 ** The action table is constructed as a single large table named yy_action[].
b62f651… stephan 818 ** Given state S and lookahead X, the action is computed as either:
b62f651… stephan 819 **
b62f651… stephan 820 ** (A) N = yy_action[ yy_shift_ofst[S] + X ]
b62f651… stephan 821 ** (B) N = yy_default[S]
b62f651… stephan 822 **
b62f651… stephan 823 ** The (A) formula is preferred. The B formula is used instead if
b62f651… stephan 824 ** yy_lookahead[yy_shift_ofst[S]+X] is not equal to X.
b62f651… stephan 825 **
b62f651… stephan 826 ** The formulas above are for computing the action when the lookahead is
b62f651… stephan 827 ** a terminal symbol. If the lookahead is a non-terminal (as occurs after
b62f651… stephan 828 ** a reduce action) then the yy_reduce_ofst[] array is used in place of
b62f651… stephan 829 ** the yy_shift_ofst[] array.
b62f651… stephan 830 **
b62f651… stephan 831 ** The following are the tables generated in this section:
b62f651… stephan 832 **
b62f651… stephan 833 ** yy_action[] A single table containing all actions.
b62f651… stephan 834 ** yy_lookahead[] A table containing the lookahead for each entry in
b62f651… stephan 835 ** yy_action. Used to detect hash collisions.
b62f651… stephan 836 ** yy_shift_ofst[] For each state, the offset into yy_action for
b62f651… stephan 837 ** shifting terminals.
b62f651… stephan 838 ** yy_reduce_ofst[] For each state, the offset into yy_action for
b62f651… stephan 839 ** shifting non-terminals after a reduce.
b62f651… stephan 840 ** yy_default[] Default action for each state.
b62f651… stephan 841 **
b62f651… stephan 842 *********** Begin parsing tables **********************************************/
dd20f34… drh 843 #define YY_ACTTAB_COUNT (1305)
b62f651… stephan 844 static const YYACTIONTYPE yy_action[] = {
b62f651… stephan 845 /* 0 */ 575, 495, 161, 119, 25, 452, 29, 74, 129, 148,
dd20f34… drh 846 /* 10 */ 575, 64, 63, 62, 61, 453, 113, 120, 161, 119,
dd20f34… drh 847 /* 20 */ 427, 428, 339, 357, 81, 121, 447, 454, 29, 575,
dd20f34… drh 848 /* 30 */ 530, 13, 50, 450, 322, 323, 9, 8, 33, 149,
dd20f34… drh 849 /* 40 */ 32, 7, 71, 127, 163, 335, 66, 28, 444, 27,
dd20f34… drh 850 /* 50 */ 339, 339, 339, 339, 425, 426, 340, 341, 342, 343,
dd20f34… drh 851 /* 60 */ 344, 345, 346, 347, 348, 474, 64, 63, 62, 61,
dd20f34… drh 852 /* 70 */ 54, 51, 73, 306, 148, 474, 492, 161, 119, 297,
dd20f34… drh 853 /* 80 */ 112, 113, 120, 161, 119, 427, 428, 339, 30, 81,
dd20f34… drh 854 /* 90 */ 109, 447, 454, 29, 474, 528, 161, 119, 450, 322,
dd20f34… drh 855 /* 100 */ 323, 9, 8, 33, 149, 32, 7, 71, 127, 163,
dd20f34… drh 856 /* 110 */ 335, 66, 535, 36, 27, 339, 339, 339, 339, 425,
dd20f34… drh 857 /* 120 */ 426, 340, 341, 342, 343, 344, 345, 346, 347, 348,
dd20f34… drh 858 /* 130 */ 394, 435, 310, 59, 60, 64, 63, 62, 61, 313,
dd20f34… drh 859 /* 140 */ 74, 376, 148, 69, 2, 533, 161, 119, 124, 113,
dd20f34… drh 860 /* 150 */ 120, 161, 119, 80, 535, 31, 308, 79, 83, 107,
dd20f34… drh 861 /* 160 */ 535, 441, 440, 535, 394, 435, 299, 59, 60, 120,
dd20f34… drh 862 /* 170 */ 161, 119, 149, 463, 376, 376, 330, 84, 2, 122,
dd20f34… drh 863 /* 180 */ 78, 78, 38, 156, 156, 156, 48, 37, 559, 328,
dd20f34… drh 864 /* 190 */ 128, 152, 560, 561, 434, 441, 440, 350, 350, 350,
dd20f34… drh 865 /* 200 */ 350, 350, 350, 350, 350, 350, 350, 350, 577, 77,
dd20f34… drh 866 /* 210 */ 577, 35, 106, 46, 436, 437, 438, 439, 579, 375,
dd20f34… drh 867 /* 220 */ 298, 117, 393, 155, 154, 153, 47, 4, 434, 69,
dd20f34… drh 868 /* 230 */ 394, 435, 3, 59, 60, 411, 412, 413, 414, 398,
dd20f34… drh 869 /* 240 */ 399, 376, 62, 61, 2, 108, 106, 5, 436, 437,
dd20f34… drh 870 /* 250 */ 438, 439, 375, 375, 117, 117, 393, 155, 154, 153,
dd20f34… drh 871 /* 260 */ 76, 441, 440, 67, 6, 142, 140, 64, 63, 62,
dd20f34… drh 872 /* 270 */ 61, 380, 157, 424, 427, 428, 339, 379, 159, 45,
dd20f34… drh 873 /* 280 */ 423, 72, 131, 148, 531, 161, 119, 1, 55, 125,
dd20f34… drh 874 /* 290 */ 113, 120, 161, 119, 434, 147, 146, 64, 63, 62,
dd20f34… drh 875 /* 300 */ 61, 397, 43, 11, 339, 339, 339, 339, 425, 426,
dd20f34… drh 876 /* 310 */ 355, 65, 106, 149, 436, 437, 438, 439, 74, 375,
dd20f34… drh 877 /* 320 */ 148, 117, 393, 155, 154, 153, 497, 113, 120, 161,
dd20f34… drh 878 /* 330 */ 119, 22, 21, 12, 142, 140, 64, 63, 62, 61,
dd20f34… drh 879 /* 340 */ 24, 356, 145, 141, 431, 64, 63, 62, 61, 391,
dd20f34… drh 880 /* 350 */ 149, 448, 454, 29, 378, 158, 85, 55, 450, 394,
dd20f34… drh 881 /* 360 */ 432, 138, 59, 60, 147, 146, 120, 161, 119, 163,
dd20f34… drh 882 /* 370 */ 102, 43, 139, 42, 27, 430, 14, 15, 301, 302,
dd20f34… drh 883 /* 380 */ 303, 446, 305, 16, 44, 74, 18, 148, 152, 19,
dd20f34… drh 884 /* 390 */ 20, 36, 68, 496, 113, 120, 161, 119, 114, 359,
dd20f34… drh 885 /* 400 */ 22, 21, 23, 142, 140, 64, 63, 62, 61, 24,
dd20f34… drh 886 /* 410 */ 107, 145, 141, 431, 26, 57, 377, 149, 58, 118,
dd20f34… drh 887 /* 420 */ 120, 161, 119, 392, 463, 384, 55, 64, 63, 62,
dd20f34… drh 888 /* 430 */ 61, 382, 569, 147, 146, 160, 383, 435, 39, 70,
dd20f34… drh 889 /* 440 */ 43, 106, 152, 445, 445, 88, 445, 445, 375, 445,
dd20f34… drh 890 /* 450 */ 117, 393, 155, 154, 153, 120, 161, 119, 445, 17,
dd20f34… drh 891 /* 460 */ 445, 10, 479, 479, 445, 445, 435, 441, 440, 22,
dd20f34… drh 892 /* 470 */ 21, 445, 403, 64, 63, 62, 61, 152, 24, 445,
dd20f34… drh 893 /* 480 */ 145, 141, 431, 133, 75, 126, 354, 445, 445, 123,
dd20f34… drh 894 /* 490 */ 445, 404, 405, 406, 408, 80, 441, 440, 308, 79,
dd20f34… drh 895 /* 500 */ 434, 411, 412, 413, 414, 394, 445, 445, 59, 60,
dd20f34… drh 896 /* 510 */ 64, 63, 62, 61, 445, 445, 376, 445, 445, 42,
dd20f34… drh 897 /* 520 */ 436, 437, 438, 439, 156, 156, 156, 394, 445, 434,
dd20f34… drh 898 /* 530 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 445,
dd20f34… drh 899 /* 540 */ 445, 42, 445, 394, 473, 391, 59, 60, 445, 436,
dd20f34… drh 900 /* 550 */ 437, 438, 439, 49, 376, 445, 74, 42, 148, 445,
dd20f34… drh 901 /* 560 */ 88, 445, 445, 445, 490, 113, 120, 161, 119, 445,
dd20f34… drh 902 /* 570 */ 120, 161, 119, 132, 130, 394, 143, 475, 59, 60,
dd20f34… drh 903 /* 580 */ 445, 473, 64, 63, 62, 61, 376, 106, 149, 42,
dd20f34… drh 904 /* 590 */ 445, 445, 152, 445, 375, 391, 117, 393, 155, 154,
dd20f34… drh 905 /* 600 */ 153, 394, 144, 52, 59, 60, 445, 445, 445, 106,
dd20f34… drh 906 /* 610 */ 445, 445, 376, 445, 445, 42, 375, 445, 117, 393,
dd20f34… drh 907 /* 620 */ 155, 154, 153, 445, 445, 106, 64, 63, 62, 61,
dd20f34… drh 908 /* 630 */ 445, 445, 375, 445, 117, 393, 155, 154, 153, 394,
dd20f34… drh 909 /* 640 */ 445, 445, 59, 60, 88, 445, 445, 53, 445, 445,
dd20f34… drh 910 /* 650 */ 376, 445, 445, 42, 120, 161, 119, 106, 445, 445,
dd20f34… drh 911 /* 660 */ 445, 110, 110, 445, 375, 445, 117, 393, 155, 154,
dd20f34… drh 912 /* 670 */ 153, 394, 445, 445, 59, 60, 152, 107, 445, 445,
dd20f34… drh 913 /* 680 */ 445, 445, 102, 106, 445, 42, 445, 120, 161, 119,
dd20f34… drh 914 /* 690 */ 375, 451, 117, 393, 155, 154, 153, 394, 445, 445,
dd20f34… drh 915 /* 700 */ 59, 60, 64, 63, 62, 61, 445, 445, 376, 152,
dd20f34… drh 916 /* 710 */ 445, 40, 445, 394, 445, 396, 59, 60, 445, 445,
dd20f34… drh 917 /* 720 */ 445, 106, 445, 445, 376, 88, 445, 41, 375, 445,
dd20f34… drh 918 /* 730 */ 117, 393, 155, 154, 153, 120, 161, 119, 74, 445,
dd20f34… drh 919 /* 740 */ 148, 445, 111, 111, 107, 445, 484, 113, 120, 161,
dd20f34… drh 920 /* 750 */ 119, 445, 445, 106, 120, 161, 119, 152, 478, 445,
dd20f34… drh 921 /* 760 */ 375, 86, 117, 393, 155, 154, 153, 445, 445, 445,
dd20f34… drh 922 /* 770 */ 149, 120, 161, 119, 445, 445, 152, 445, 445, 106,
dd20f34… drh 923 /* 780 */ 445, 64, 63, 62, 61, 445, 375, 445, 117, 393,
dd20f34… drh 924 /* 790 */ 155, 154, 153, 152, 395, 106, 64, 63, 62, 61,
dd20f34… drh 925 /* 800 */ 98, 445, 375, 445, 117, 393, 155, 154, 153, 445,
dd20f34… drh 926 /* 810 */ 120, 161, 119, 445, 74, 445, 148, 56, 445, 74,
dd20f34… drh 927 /* 820 */ 445, 148, 483, 113, 120, 161, 119, 480, 113, 120,
dd20f34… drh 928 /* 830 */ 161, 119, 152, 74, 445, 148, 445, 89, 445, 445,
dd20f34… drh 929 /* 840 */ 445, 134, 113, 120, 161, 119, 149, 120, 161, 119,
dd20f34… drh 930 /* 850 */ 445, 149, 74, 445, 148, 445, 445, 445, 378, 158,
dd20f34… drh 931 /* 860 */ 517, 113, 120, 161, 119, 149, 74, 445, 148, 152,
dd20f34… drh 932 /* 870 */ 445, 74, 445, 148, 137, 113, 120, 161, 119, 525,
dd20f34… drh 933 /* 880 */ 113, 120, 161, 119, 149, 74, 445, 148, 64, 63,
dd20f34… drh 934 /* 890 */ 62, 61, 445, 527, 113, 120, 161, 119, 149, 445,
dd20f34… drh 935 /* 900 */ 445, 391, 445, 149, 445, 445, 445, 445, 445, 445,
dd20f34… drh 936 /* 910 */ 74, 445, 148, 445, 445, 162, 445, 149, 524, 113,
dd20f34… drh 937 /* 920 */ 120, 161, 119, 118, 445, 74, 445, 148, 445, 445,
dd20f34… drh 938 /* 930 */ 445, 445, 445, 526, 113, 120, 161, 119, 445, 74,
dd20f34… drh 939 /* 940 */ 445, 148, 149, 445, 445, 445, 445, 523, 113, 120,
dd20f34… drh 940 /* 950 */ 161, 119, 74, 445, 148, 445, 445, 149, 445, 445,
dd20f34… drh 941 /* 960 */ 522, 113, 120, 161, 119, 445, 74, 445, 148, 445,
dd20f34… drh 942 /* 970 */ 445, 149, 445, 445, 521, 113, 120, 161, 119, 74,
dd20f34… drh 943 /* 980 */ 445, 148, 445, 445, 149, 445, 445, 520, 113, 120,
dd20f34… drh 944 /* 990 */ 161, 119, 445, 74, 445, 148, 445, 445, 149, 445,
dd20f34… drh 945 /* 1000 */ 445, 519, 113, 120, 161, 119, 445, 445, 445, 445,
dd20f34… drh 946 /* 1010 */ 445, 149, 445, 445, 445, 445, 445, 445, 74, 445,
dd20f34… drh 947 /* 1020 */ 148, 445, 445, 445, 445, 149, 150, 113, 120, 161,
dd20f34… drh 948 /* 1030 */ 119, 74, 445, 148, 445, 445, 445, 445, 445, 151,
dd20f34… drh 949 /* 1040 */ 113, 120, 161, 119, 445, 74, 445, 148, 445, 445,
dd20f34… drh 950 /* 1050 */ 149, 445, 445, 136, 113, 120, 161, 119, 74, 445,
dd20f34… drh 951 /* 1060 */ 148, 445, 445, 149, 445, 445, 135, 113, 120, 161,
dd20f34… drh 952 /* 1070 */ 119, 445, 88, 445, 445, 445, 445, 149, 445, 445,
dd20f34… drh 953 /* 1080 */ 445, 90, 120, 161, 119, 445, 445, 445, 445, 82,
dd20f34… drh 954 /* 1090 */ 149, 120, 161, 119, 445, 87, 466, 445, 34, 99,
dd20f34… drh 955 /* 1100 */ 445, 445, 445, 445, 152, 120, 161, 119, 100, 120,
dd20f34… drh 956 /* 1110 */ 161, 119, 445, 152, 445, 445, 445, 445, 120, 161,
dd20f34… drh 957 /* 1120 */ 119, 445, 445, 445, 101, 445, 445, 152, 445, 445,
dd20f34… drh 958 /* 1130 */ 445, 152, 91, 445, 120, 161, 119, 103, 445, 445,
dd20f34… drh 959 /* 1140 */ 152, 445, 120, 161, 119, 445, 445, 120, 161, 119,
dd20f34… drh 960 /* 1150 */ 445, 92, 445, 445, 445, 445, 152, 445, 445, 445,
dd20f34… drh 961 /* 1160 */ 93, 120, 161, 119, 152, 445, 104, 445, 445, 152,
dd20f34… drh 962 /* 1170 */ 120, 161, 119, 445, 94, 445, 120, 161, 119, 445,
dd20f34… drh 963 /* 1180 */ 445, 445, 445, 152, 120, 161, 119, 445, 445, 105,
dd20f34… drh 964 /* 1190 */ 445, 445, 152, 445, 445, 445, 445, 95, 152, 120,
dd20f34… drh 965 /* 1200 */ 161, 119, 96, 445, 445, 97, 152, 120, 161, 119,
dd20f34… drh 966 /* 1210 */ 445, 445, 120, 161, 119, 120, 161, 119, 445, 445,
dd20f34… drh 967 /* 1220 */ 445, 152, 445, 445, 445, 445, 445, 445, 445, 152,
dd20f34… drh 968 /* 1230 */ 549, 445, 445, 548, 152, 445, 445, 152, 547, 445,
dd20f34… drh 969 /* 1240 */ 120, 161, 119, 120, 161, 119, 546, 445, 120, 161,
dd20f34… drh 970 /* 1250 */ 119, 445, 445, 445, 445, 445, 120, 161, 119, 445,
dd20f34… drh 971 /* 1260 */ 445, 445, 152, 445, 445, 152, 445, 445, 445, 115,
dd20f34… drh 972 /* 1270 */ 152, 445, 116, 445, 445, 445, 445, 445, 152, 120,
dd20f34… drh 973 /* 1280 */ 161, 119, 120, 161, 119, 445, 445, 445, 445, 445,
dd20f34… drh 974 /* 1290 */ 445, 445, 445, 445, 445, 445, 445, 445, 445, 445,
dd20f34… drh 975 /* 1300 */ 445, 152, 445, 445, 152,
b62f651… stephan 976 };
b62f651… stephan 977 static const YYCODETYPE yy_lookahead[] = {
dd20f34… drh 978 /* 0 */ 0, 115, 116, 117, 136, 103, 104, 105, 107, 107,
dd20f34… drh 979 /* 10 */ 10, 4, 5, 6, 7, 113, 114, 115, 116, 117,
dd20f34… drh 980 /* 20 */ 20, 21, 22, 17, 24, 101, 102, 103, 104, 29,
dd20f34… drh 981 /* 30 */ 107, 25, 25, 109, 34, 35, 36, 37, 38, 137,
dd20f34… drh 982 /* 40 */ 40, 41, 42, 43, 120, 45, 46, 109, 124, 125,
b62f651… stephan 983 /* 50 */ 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
dd20f34… drh 984 /* 60 */ 60, 61, 62, 63, 64, 0, 4, 5, 6, 7,
dd20f34… drh 985 /* 70 */ 4, 5, 105, 25, 107, 10, 115, 116, 117, 17,
dd20f34… drh 986 /* 80 */ 113, 114, 115, 116, 117, 20, 21, 22, 128, 24,
dd20f34… drh 987 /* 90 */ 101, 102, 103, 104, 29, 115, 116, 117, 109, 34,
dd20f34… drh 988 /* 100 */ 35, 36, 37, 38, 137, 40, 41, 42, 43, 120,
dd20f34… drh 989 /* 110 */ 45, 46, 49, 10, 125, 50, 51, 52, 53, 54,
dd20f34… drh 990 /* 120 */ 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
dd20f34… drh 991 /* 130 */ 1, 2, 29, 4, 5, 4, 5, 6, 7, 8,
dd20f34… drh 992 /* 140 */ 105, 12, 107, 3, 15, 115, 116, 117, 113, 114,
dd20f34… drh 993 /* 150 */ 115, 116, 117, 24, 91, 130, 27, 28, 118, 105,
dd20f34… drh 994 /* 160 */ 97, 32, 33, 100, 1, 2, 19, 4, 5, 115,
dd20f34… drh 995 /* 170 */ 116, 117, 137, 119, 12, 12, 2, 118, 15, 1,
dd20f34… drh 996 /* 180 */ 126, 127, 106, 20, 21, 22, 110, 111, 106, 2,
dd20f34… drh 997 /* 190 */ 107, 137, 110, 111, 65, 32, 33, 65, 66, 67,
dd20f34… drh 998 /* 200 */ 68, 69, 70, 71, 72, 73, 74, 75, 132, 133,
dd20f34… drh 999 /* 210 */ 134, 131, 83, 39, 85, 86, 87, 88, 135, 90,
dd20f34… drh 1000 /* 220 */ 17, 92, 93, 94, 95, 96, 39, 15, 65, 89,
dd20f34… drh 1001 /* 230 */ 1, 2, 16, 4, 5, 30, 31, 32, 33, 98,
dd20f34… drh 1002 /* 240 */ 99, 12, 6, 7, 15, 83, 83, 41, 85, 86,
dd20f34… drh 1003 /* 250 */ 87, 88, 90, 90, 92, 92, 93, 94, 95, 96,
dd20f34… drh 1004 /* 260 */ 49, 32, 33, 44, 41, 2, 3, 4, 5, 6,
dd20f34… drh 1005 /* 270 */ 7, 27, 28, 42, 20, 21, 22, 27, 28, 16,
dd20f34… drh 1006 /* 280 */ 42, 105, 48, 107, 115, 116, 117, 13, 25, 113,
dd20f34… drh 1007 /* 290 */ 114, 115, 116, 117, 65, 32, 33, 4, 5, 6,
dd20f34… drh 1008 /* 300 */ 7, 17, 39, 25, 50, 51, 52, 53, 54, 55,
dd20f34… drh 1009 /* 310 */ 17, 100, 83, 137, 85, 86, 87, 88, 105, 90,
dd20f34… drh 1010 /* 320 */ 107, 92, 93, 94, 95, 96, 113, 114, 115, 116,
dd20f34… drh 1011 /* 330 */ 117, 68, 69, 76, 2, 3, 4, 5, 6, 7,
dd20f34… drh 1012 /* 340 */ 77, 17, 79, 80, 81, 4, 5, 6, 7, 17,
dd20f34… drh 1013 /* 350 */ 137, 102, 103, 104, 27, 28, 105, 25, 109, 1,
dd20f34… drh 1014 /* 360 */ 81, 80, 4, 5, 32, 33, 115, 116, 117, 120,
dd20f34… drh 1015 /* 370 */ 12, 39, 82, 15, 125, 81, 3, 36, 20, 21,
dd20f34… drh 1016 /* 380 */ 22, 0, 24, 3, 39, 105, 3, 107, 137, 3,
dd20f34… drh 1017 /* 390 */ 3, 10, 3, 113, 114, 115, 116, 117, 97, 78,
dd20f34… drh 1018 /* 400 */ 68, 69, 25, 2, 3, 4, 5, 6, 7, 77,
dd20f34… drh 1019 /* 410 */ 105, 79, 80, 81, 15, 15, 12, 137, 15, 92,
dd20f34… drh 1020 /* 420 */ 115, 116, 117, 17, 119, 29, 25, 4, 5, 6,
dd20f34… drh 1021 /* 430 */ 7, 29, 127, 32, 33, 91, 29, 2, 11, 3,
dd20f34… drh 1022 /* 440 */ 39, 83, 137, 138, 138, 105, 138, 138, 90, 138,
dd20f34… drh 1023 /* 450 */ 92, 93, 94, 95, 96, 115, 116, 117, 138, 36,
dd20f34… drh 1024 /* 460 */ 138, 121, 122, 123, 138, 138, 2, 32, 33, 68,
dd20f34… drh 1025 /* 470 */ 69, 138, 1, 4, 5, 6, 7, 137, 77, 138,
dd20f34… drh 1026 /* 480 */ 79, 80, 81, 12, 49, 14, 17, 138, 138, 18,
dd20f34… drh 1027 /* 490 */ 138, 20, 21, 22, 23, 24, 32, 33, 27, 28,
dd20f34… drh 1028 /* 500 */ 65, 30, 31, 32, 33, 1, 138, 138, 4, 5,
dd20f34… drh 1029 /* 510 */ 4, 5, 6, 7, 138, 138, 12, 138, 138, 15,
dd20f34… drh 1030 /* 520 */ 85, 86, 87, 88, 20, 21, 22, 1, 138, 65,
dd20f34… drh 1031 /* 530 */ 4, 5, 4, 5, 6, 7, 138, 138, 12, 138,
dd20f34… drh 1032 /* 540 */ 138, 15, 138, 1, 2, 17, 4, 5, 138, 85,
dd20f34… drh 1033 /* 550 */ 86, 87, 88, 25, 12, 138, 105, 15, 107, 138,
dd20f34… drh 1034 /* 560 */ 105, 138, 138, 138, 113, 114, 115, 116, 117, 138,
dd20f34… drh 1035 /* 570 */ 115, 116, 117, 47, 48, 1, 2, 122, 4, 5,
dd20f34… drh 1036 /* 580 */ 138, 39, 4, 5, 6, 7, 12, 83, 137, 15,
dd20f34… drh 1037 /* 590 */ 138, 138, 137, 138, 90, 17, 92, 93, 94, 95,
dd20f34… drh 1038 /* 600 */ 96, 1, 2, 25, 4, 5, 138, 138, 138, 83,
dd20f34… drh 1039 /* 610 */ 138, 138, 12, 138, 138, 15, 90, 138, 92, 93,
dd20f34… drh 1040 /* 620 */ 94, 95, 96, 138, 138, 83, 4, 5, 6, 7,
dd20f34… drh 1041 /* 630 */ 138, 138, 90, 138, 92, 93, 94, 95, 96, 1,
dd20f34… drh 1042 /* 640 */ 138, 138, 4, 5, 105, 138, 138, 25, 138, 138,
dd20f34… drh 1043 /* 650 */ 12, 138, 138, 15, 115, 116, 117, 83, 138, 138,
dd20f34… drh 1044 /* 660 */ 138, 122, 123, 138, 90, 138, 92, 93, 94, 95,
dd20f34… drh 1045 /* 670 */ 96, 1, 138, 138, 4, 5, 137, 105, 138, 138,
dd20f34… drh 1046 /* 680 */ 138, 138, 12, 83, 138, 15, 138, 115, 116, 117,
dd20f34… drh 1047 /* 690 */ 90, 119, 92, 93, 94, 95, 96, 1, 138, 138,
dd20f34… drh 1048 /* 700 */ 4, 5, 4, 5, 6, 7, 138, 138, 12, 137,
dd20f34… drh 1049 /* 710 */ 138, 15, 138, 1, 138, 17, 4, 5, 138, 138,
dd20f34… drh 1050 /* 720 */ 138, 83, 138, 138, 12, 105, 138, 15, 90, 138,
dd20f34… drh 1051 /* 730 */ 92, 93, 94, 95, 96, 115, 116, 117, 105, 138,
dd20f34… drh 1052 /* 740 */ 107, 138, 122, 123, 105, 138, 113, 114, 115, 116,
dd20f34… drh 1053 /* 750 */ 117, 138, 138, 83, 115, 116, 117, 137, 119, 138,
dd20f34… drh 1054 /* 760 */ 90, 105, 92, 93, 94, 95, 96, 138, 138, 138,
dd20f34… drh 1055 /* 770 */ 137, 115, 116, 117, 138, 138, 137, 138, 138, 83,
dd20f34… drh 1056 /* 780 */ 138, 4, 5, 6, 7, 138, 90, 138, 92, 93,
dd20f34… drh 1057 /* 790 */ 94, 95, 96, 137, 17, 83, 4, 5, 6, 7,
dd20f34… drh 1058 /* 800 */ 105, 138, 90, 138, 92, 93, 94, 95, 96, 138,
dd20f34… drh 1059 /* 810 */ 115, 116, 117, 138, 105, 138, 107, 25, 138, 105,
dd20f34… drh 1060 /* 820 */ 138, 107, 113, 114, 115, 116, 117, 113, 114, 115,
dd20f34… drh 1061 /* 830 */ 116, 117, 137, 105, 138, 107, 138, 105, 138, 138,
dd20f34… drh 1062 /* 840 */ 138, 113, 114, 115, 116, 117, 137, 115, 116, 117,
dd20f34… drh 1063 /* 850 */ 138, 137, 105, 138, 107, 138, 138, 138, 27, 28,
dd20f34… drh 1064 /* 860 */ 113, 114, 115, 116, 117, 137, 105, 138, 107, 137,
dd20f34… drh 1065 /* 870 */ 138, 105, 138, 107, 113, 114, 115, 116, 117, 113,
dd20f34… drh 1066 /* 880 */ 114, 115, 116, 117, 137, 105, 138, 107, 4, 5,
dd20f34… drh 1067 /* 890 */ 6, 7, 138, 113, 114, 115, 116, 117, 137, 138,
dd20f34… drh 1068 /* 900 */ 138, 17, 138, 137, 138, 138, 138, 138, 138, 138,
dd20f34… drh 1069 /* 910 */ 105, 138, 107, 138, 138, 84, 138, 137, 113, 114,
dd20f34… drh 1070 /* 920 */ 115, 116, 117, 92, 138, 105, 138, 107, 138, 138,
dd20f34… drh 1071 /* 930 */ 138, 138, 138, 113, 114, 115, 116, 117, 138, 105,
dd20f34… drh 1072 /* 940 */ 138, 107, 137, 138, 138, 138, 138, 113, 114, 115,
dd20f34… drh 1073 /* 950 */ 116, 117, 105, 138, 107, 138, 138, 137, 138, 138,
dd20f34… drh 1074 /* 960 */ 113, 114, 115, 116, 117, 138, 105, 138, 107, 138,
dd20f34… drh 1075 /* 970 */ 138, 137, 138, 138, 113, 114, 115, 116, 117, 105,
dd20f34… drh 1076 /* 980 */ 138, 107, 138, 138, 137, 138, 138, 113, 114, 115,
dd20f34… drh 1077 /* 990 */ 116, 117, 138, 105, 138, 107, 138, 138, 137, 138,
dd20f34… drh 1078 /* 1000 */ 138, 113, 114, 115, 116, 117, 138, 138, 138, 138,
dd20f34… drh 1079 /* 1010 */ 138, 137, 138, 138, 138, 138, 138, 138, 105, 138,
dd20f34… drh 1080 /* 1020 */ 107, 138, 138, 138, 138, 137, 113, 114, 115, 116,
dd20f34… drh 1081 /* 1030 */ 117, 105, 138, 107, 138, 138, 138, 138, 138, 113,
dd20f34… drh 1082 /* 1040 */ 114, 115, 116, 117, 138, 105, 138, 107, 138, 138,
dd20f34… drh 1083 /* 1050 */ 137, 138, 138, 113, 114, 115, 116, 117, 105, 138,
dd20f34… drh 1084 /* 1060 */ 107, 138, 138, 137, 138, 138, 113, 114, 115, 116,
dd20f34… drh 1085 /* 1070 */ 117, 138, 105, 138, 138, 138, 138, 137, 138, 138,
dd20f34… drh 1086 /* 1080 */ 138, 105, 115, 116, 117, 138, 138, 138, 138, 122,
dd20f34… drh 1087 /* 1090 */ 137, 115, 116, 117, 138, 105, 129, 138, 131, 105,
dd20f34… drh 1088 /* 1100 */ 138, 138, 138, 138, 137, 115, 116, 117, 105, 115,
dd20f34… drh 1089 /* 1110 */ 116, 117, 138, 137, 138, 138, 138, 138, 115, 116,
dd20f34… drh 1090 /* 1120 */ 117, 138, 138, 138, 105, 138, 138, 137, 138, 138,
dd20f34… drh 1091 /* 1130 */ 138, 137, 105, 138, 115, 116, 117, 105, 138, 138,
dd20f34… drh 1092 /* 1140 */ 137, 138, 115, 116, 117, 138, 138, 115, 116, 117,
dd20f34… drh 1093 /* 1150 */ 138, 105, 138, 138, 138, 138, 137, 138, 138, 138,
dd20f34… drh 1094 /* 1160 */ 105, 115, 116, 117, 137, 138, 105, 138, 138, 137,
dd20f34… drh 1095 /* 1170 */ 115, 116, 117, 138, 105, 138, 115, 116, 117, 138,
dd20f34… drh 1096 /* 1180 */ 138, 138, 138, 137, 115, 116, 117, 138, 138, 105,
dd20f34… drh 1097 /* 1190 */ 138, 138, 137, 138, 138, 138, 138, 105, 137, 115,
dd20f34… drh 1098 /* 1200 */ 116, 117, 105, 138, 138, 105, 137, 115, 116, 117,
dd20f34… drh 1099 /* 1210 */ 138, 138, 115, 116, 117, 115, 116, 117, 138, 138,
dd20f34… drh 1100 /* 1220 */ 138, 137, 138, 138, 138, 138, 138, 138, 138, 137,
dd20f34… drh 1101 /* 1230 */ 105, 138, 138, 105, 137, 138, 138, 137, 105, 138,
dd20f34… drh 1102 /* 1240 */ 115, 116, 117, 115, 116, 117, 105, 138, 115, 116,
dd20f34… drh 1103 /* 1250 */ 117, 138, 138, 138, 138, 138, 115, 116, 117, 138,
dd20f34… drh 1104 /* 1260 */ 138, 138, 137, 138, 138, 137, 138, 138, 138, 105,
dd20f34… drh 1105 /* 1270 */ 137, 138, 105, 138, 138, 138, 138, 138, 137, 115,
dd20f34… drh 1106 /* 1280 */ 116, 117, 115, 116, 117, 138, 138, 138, 138, 138,
dd20f34… drh 1107 /* 1290 */ 138, 138, 138, 138, 138, 138, 138, 138, 138, 138,
dd20f34… drh 1108 /* 1300 */ 138, 137, 138, 138, 137, 101, 101, 101, 101, 101,
dd20f34… drh 1109 /* 1310 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1110 /* 1320 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1111 /* 1330 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1112 /* 1340 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1113 /* 1350 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1114 /* 1360 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1115 /* 1370 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1116 /* 1380 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1117 /* 1390 */ 101, 101, 101, 101, 101, 101, 101, 101, 101, 101,
dd20f34… drh 1118 /* 1400 */ 101, 101, 101, 101, 101, 101,
b62f651… stephan 1119 };
b62f651… stephan 1120 #define YY_SHIFT_COUNT (163)
b62f651… stephan 1121 #define YY_SHIFT_MIN (0)
dd20f34… drh 1122 #define YY_SHIFT_MAX (884)
b62f651… stephan 1123 static const unsigned short int yy_shift_ofst[] = {
dd20f34… drh 1124 /* 0 */ 471, 129, 163, 229, 229, 229, 229, 229, 229, 229,
dd20f34… drh 1125 /* 10 */ 229, 229, 229, 229, 229, 229, 229, 229, 229, 229,
dd20f34… drh 1126 /* 20 */ 229, 229, 229, 229, 229, 229, 229, 358, 526, 638,
dd20f34… drh 1127 /* 30 */ 358, 471, 542, 542, 0, 65, 471, 670, 638, 670,
dd20f34… drh 1128 /* 40 */ 504, 504, 504, 574, 600, 638, 638, 638, 638, 638,
dd20f34… drh 1129 /* 50 */ 638, 696, 638, 638, 712, 638, 638, 638, 638, 638,
dd20f34… drh 1130 /* 60 */ 638, 638, 638, 638, 638, 254, 162, 162, 162, 162,
dd20f34… drh 1131 /* 70 */ 162, 435, 263, 332, 401, 464, 464, 205, 48, 1305,
dd20f34… drh 1132 /* 80 */ 1305, 1305, 1305, 132, 132, 528, 578, 62, 131, 341,
dd20f34… drh 1133 /* 90 */ 423, 293, 7, 469, 622, 698, 792, 777, 884, 506,
dd20f34… drh 1134 /* 100 */ 506, 506, 63, 506, 506, 506, 831, 506, 327, 103,
dd20f34… drh 1135 /* 110 */ 174, 187, 6, 66, 141, 236, 236, 244, 250, 140,
dd20f34… drh 1136 /* 120 */ 211, 381, 147, 178, 203, 216, 212, 219, 206, 223,
dd20f34… drh 1137 /* 130 */ 231, 238, 234, 274, 284, 278, 257, 324, 279, 281,
dd20f34… drh 1138 /* 140 */ 290, 294, 373, 380, 383, 345, 386, 387, 389, 301,
dd20f34… drh 1139 /* 150 */ 321, 377, 301, 399, 400, 403, 406, 396, 402, 407,
dd20f34… drh 1140 /* 160 */ 404, 344, 436, 427,
b62f651… stephan 1141 };
b62f651… stephan 1142 #define YY_REDUCE_COUNT (82)
dd20f34… drh 1143 #define YY_REDUCE_MIN (-132)
dd20f34… drh 1144 #define YY_REDUCE_MAX (1167)
b62f651… stephan 1145 static const short yy_reduce_ofst[] = {
dd20f34… drh 1146 /* 0 */ -76, -98, -33, 35, 176, 213, 280, 451, 633, 709,
dd20f34… drh 1147 /* 10 */ 714, 728, 747, 761, 766, 780, 805, 820, 834, 847,
dd20f34… drh 1148 /* 20 */ 861, 874, 888, 913, 926, 940, 953, 54, 340, 967,
dd20f34… drh 1149 /* 30 */ 305, -11, 539, 620, 76, 76, 249, 639, 455, 572,
dd20f34… drh 1150 /* 40 */ 251, 656, 695, 732, 976, 990, 994, 1003, 1019, 1027,
dd20f34… drh 1151 /* 50 */ 1032, 1046, 1055, 1061, 1069, 1084, 1092, 1097, 1100, 1125,
dd20f34… drh 1152 /* 60 */ 1128, 1133, 1141, 1164, 1167, 82, -114, -39, -20, 30,
dd20f34… drh 1153 /* 70 */ 169, 83, -132, -132, -132, -99, -77, -62, -40, 25,
dd20f34… drh 1154 /* 80 */ 40, 59, 80,
b62f651… stephan 1155 };
b62f651… stephan 1156 static const YYACTIONTYPE yy_default[] = {
b62f651… stephan 1157 /* 0 */ 449, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1158 /* 10 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1159 /* 20 */ 443, 443, 443, 443, 443, 443, 443, 443, 473, 576,
b62f651… stephan 1160 /* 30 */ 443, 449, 580, 485, 581, 581, 449, 443, 443, 443,
b62f651… stephan 1161 /* 40 */ 443, 443, 443, 443, 443, 443, 443, 443, 477, 443,
b62f651… stephan 1162 /* 50 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1163 /* 60 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1164 /* 70 */ 443, 443, 443, 443, 443, 443, 443, 443, 455, 470,
b62f651… stephan 1165 /* 80 */ 508, 508, 576, 468, 493, 443, 443, 443, 471, 443,
b62f651… stephan 1166 /* 90 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 488,
b62f651… stephan 1167 /* 100 */ 486, 476, 459, 512, 511, 510, 443, 566, 443, 443,
b62f651… stephan 1168 /* 110 */ 443, 443, 443, 588, 443, 545, 544, 540, 443, 532,
b62f651… stephan 1169 /* 120 */ 529, 443, 443, 443, 443, 443, 443, 491, 443, 443,
b62f651… stephan 1170 /* 130 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1171 /* 140 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 592,
b62f651… stephan 1172 /* 150 */ 443, 443, 443, 443, 443, 443, 443, 443, 443, 443,
b62f651… stephan 1173 /* 160 */ 443, 601, 443, 443,
b62f651… stephan 1174 };
b62f651… stephan 1175 /********** End of lemon-generated parsing tables *****************************/
b62f651… stephan 1176
b62f651… stephan 1177 /* The next table maps tokens (terminal symbols) into fallback tokens.
b62f651… stephan 1178 ** If a construct like the following:
b62f651… stephan 1179 **
b62f651… stephan 1180 ** %fallback ID X Y Z.
b62f651… stephan 1181 **
b62f651… stephan 1182 ** appears in the grammar, then ID becomes a fallback token for X, Y,
b62f651… stephan 1183 ** and Z. Whenever one of the tokens X, Y, or Z is input to the parser
b62f651… stephan 1184 ** but it does not parse, the type of the token is changed to ID and
b62f651… stephan 1185 ** the parse is retried before an error is thrown.
b62f651… stephan 1186 **
b62f651… stephan 1187 ** This feature can be used, for example, to cause some keywords in a language
b62f651… stephan 1188 ** to revert to identifiers if they keyword does not apply in the context where
b62f651… stephan 1189 ** it appears.
b62f651… stephan 1190 */
b62f651… stephan 1191 #ifdef YYFALLBACK
b62f651… stephan 1192 static const YYCODETYPE yyFallback[] = {
b62f651… stephan 1193 0, /* $ => nothing */
b62f651… stephan 1194 0, /* ID => nothing */
b62f651… stephan 1195 1, /* EDGEPT => ID */
b62f651… stephan 1196 0, /* OF => nothing */
b62f651… stephan 1197 0, /* PLUS => nothing */
b62f651… stephan 1198 0, /* MINUS => nothing */
b62f651… stephan 1199 0, /* STAR => nothing */
b62f651… stephan 1200 0, /* SLASH => nothing */
b62f651… stephan 1201 0, /* PERCENT => nothing */
b62f651… stephan 1202 0, /* UMINUS => nothing */
b62f651… stephan 1203 0, /* EOL => nothing */
b62f651… stephan 1204 0, /* ASSIGN => nothing */
b62f651… stephan 1205 0, /* PLACENAME => nothing */
b62f651… stephan 1206 0, /* COLON => nothing */
b62f651… stephan 1207 0, /* ASSERT => nothing */
b62f651… stephan 1208 0, /* LP => nothing */
b62f651… stephan 1209 0, /* EQ => nothing */
b62f651… stephan 1210 0, /* RP => nothing */
b62f651… stephan 1211 0, /* DEFINE => nothing */
b62f651… stephan 1212 0, /* CODEBLOCK => nothing */
b62f651… stephan 1213 0, /* FILL => nothing */
b62f651… stephan 1214 0, /* COLOR => nothing */
b62f651… stephan 1215 0, /* THICKNESS => nothing */
b62f651… stephan 1216 0, /* PRINT => nothing */
b62f651… stephan 1217 0, /* STRING => nothing */
b62f651… stephan 1218 0, /* COMMA => nothing */
dd20f34… drh 1219 0, /* ISODATE => nothing */
b62f651… stephan 1220 0, /* CLASSNAME => nothing */
b62f651… stephan 1221 0, /* LB => nothing */
b62f651… stephan 1222 0, /* RB => nothing */
b62f651… stephan 1223 0, /* UP => nothing */
b62f651… stephan 1224 0, /* DOWN => nothing */
b62f651… stephan 1225 0, /* LEFT => nothing */
b62f651… stephan 1226 0, /* RIGHT => nothing */
b62f651… stephan 1227 0, /* CLOSE => nothing */
b62f651… stephan 1228 0, /* CHOP => nothing */
b62f651… stephan 1229 0, /* FROM => nothing */
b62f651… stephan 1230 0, /* TO => nothing */
b62f651… stephan 1231 0, /* THEN => nothing */
b62f651… stephan 1232 0, /* HEADING => nothing */
b62f651… stephan 1233 0, /* GO => nothing */
b62f651… stephan 1234 0, /* AT => nothing */
b62f651… stephan 1235 0, /* WITH => nothing */
b62f651… stephan 1236 0, /* SAME => nothing */
b62f651… stephan 1237 0, /* AS => nothing */
b62f651… stephan 1238 0, /* FIT => nothing */
b62f651… stephan 1239 0, /* BEHIND => nothing */
b62f651… stephan 1240 0, /* UNTIL => nothing */
b62f651… stephan 1241 0, /* EVEN => nothing */
b62f651… stephan 1242 0, /* DOT_E => nothing */
b62f651… stephan 1243 0, /* HEIGHT => nothing */
b62f651… stephan 1244 0, /* WIDTH => nothing */
b62f651… stephan 1245 0, /* RADIUS => nothing */
b62f651… stephan 1246 0, /* DIAMETER => nothing */
b62f651… stephan 1247 0, /* DOTTED => nothing */
b62f651… stephan 1248 0, /* DASHED => nothing */
b62f651… stephan 1249 0, /* CW => nothing */
b62f651… stephan 1250 0, /* CCW => nothing */
b62f651… stephan 1251 0, /* LARROW => nothing */
b62f651… stephan 1252 0, /* RARROW => nothing */
b62f651… stephan 1253 0, /* LRARROW => nothing */
b62f651… stephan 1254 0, /* INVIS => nothing */
b62f651… stephan 1255 0, /* THICK => nothing */
b62f651… stephan 1256 0, /* THIN => nothing */
b62f651… stephan 1257 0, /* SOLID => nothing */
b62f651… stephan 1258 0, /* CENTER => nothing */
b62f651… stephan 1259 0, /* LJUST => nothing */
b62f651… stephan 1260 0, /* RJUST => nothing */
b62f651… stephan 1261 0, /* ABOVE => nothing */
b62f651… stephan 1262 0, /* BELOW => nothing */
b62f651… stephan 1263 0, /* ITALIC => nothing */
b62f651… stephan 1264 0, /* BOLD => nothing */
43eefe6… drh 1265 0, /* MONO => nothing */
b62f651… stephan 1266 0, /* ALIGNED => nothing */
b62f651… stephan 1267 0, /* BIG => nothing */
b62f651… stephan 1268 0, /* SMALL => nothing */
b62f651… stephan 1269 0, /* AND => nothing */
b62f651… stephan 1270 0, /* LT => nothing */
b62f651… stephan 1271 0, /* GT => nothing */
b62f651… stephan 1272 0, /* ON => nothing */
b62f651… stephan 1273 0, /* WAY => nothing */
b62f651… stephan 1274 0, /* BETWEEN => nothing */
b62f651… stephan 1275 0, /* THE => nothing */
b62f651… stephan 1276 0, /* NTH => nothing */
b62f651… stephan 1277 0, /* VERTEX => nothing */
b62f651… stephan 1278 0, /* TOP => nothing */
b62f651… stephan 1279 0, /* BOTTOM => nothing */
b62f651… stephan 1280 0, /* START => nothing */
b62f651… stephan 1281 0, /* END => nothing */
b62f651… stephan 1282 0, /* IN => nothing */
b62f651… stephan 1283 0, /* THIS => nothing */
b62f651… stephan 1284 0, /* DOT_U => nothing */
b62f651… stephan 1285 0, /* LAST => nothing */
b62f651… stephan 1286 0, /* NUMBER => nothing */
b62f651… stephan 1287 0, /* FUNC1 => nothing */
b62f651… stephan 1288 0, /* FUNC2 => nothing */
b62f651… stephan 1289 0, /* DIST => nothing */
b62f651… stephan 1290 0, /* DOT_XY => nothing */
b62f651… stephan 1291 0, /* X => nothing */
b62f651… stephan 1292 0, /* Y => nothing */
b62f651… stephan 1293 0, /* DOT_L => nothing */
b62f651… stephan 1294 };
b62f651… stephan 1295 #endif /* YYFALLBACK */
b62f651… stephan 1296
b62f651… stephan 1297 /* The following structure represents a single element of the
b62f651… stephan 1298 ** parser's stack. Information stored includes:
b62f651… stephan 1299 **
b62f651… stephan 1300 ** + The state number for the parser at this level of the stack.
b62f651… stephan 1301 **
b62f651… stephan 1302 ** + The value of the token stored at this level of the stack.
b62f651… stephan 1303 ** (In other words, the "major" token.)
b62f651… stephan 1304 **
b62f651… stephan 1305 ** + The semantic value stored at this level of the stack. This is
b62f651… stephan 1306 ** the information used by the action routines in the grammar.
b62f651… stephan 1307 ** It is sometimes called the "minor" token.
b62f651… stephan 1308 **
b62f651… stephan 1309 ** After the "shift" half of a SHIFTREDUCE action, the stateno field
b62f651… stephan 1310 ** actually contains the reduce action for the second half of the
b62f651… stephan 1311 ** SHIFTREDUCE.
b62f651… stephan 1312 */
b62f651… stephan 1313 struct yyStackEntry {
b62f651… stephan 1314 YYACTIONTYPE stateno; /* The state-number, or reduce action in SHIFTREDUCE */
b62f651… stephan 1315 YYCODETYPE major; /* The major token value. This is the code
b62f651… stephan 1316 ** number for the token at this stack level */
b62f651… stephan 1317 YYMINORTYPE minor; /* The user-supplied minor token value. This
b62f651… stephan 1318 ** is the value of the token */
b62f651… stephan 1319 };
b62f651… stephan 1320 typedef struct yyStackEntry yyStackEntry;
b62f651… stephan 1321
b62f651… stephan 1322 /* The state of the parser is completely contained in an instance of
b62f651… stephan 1323 ** the following structure */
b62f651… stephan 1324 struct yyParser {
b62f651… stephan 1325 yyStackEntry *yytos; /* Pointer to top element of the stack */
b62f651… stephan 1326 #ifdef YYTRACKMAXSTACKDEPTH
b62f651… stephan 1327 int yyhwm; /* High-water mark of the stack */
b62f651… stephan 1328 #endif
b62f651… stephan 1329 #ifndef YYNOERRORRECOVERY
b62f651… stephan 1330 int yyerrcnt; /* Shifts left before out of the error */
b62f651… stephan 1331 #endif
b62f651… stephan 1332 pik_parserARG_SDECL /* A place to hold %extra_argument */
b62f651… stephan 1333 pik_parserCTX_SDECL /* A place to hold %extra_context */
f4ec8e0… drh 1334 yyStackEntry *yystackEnd; /* Last entry in the stack */
f4ec8e0… drh 1335 yyStackEntry *yystack; /* The parser stack */
f4ec8e0… drh 1336 yyStackEntry yystk0[YYSTACKDEPTH]; /* Initial stack space */
b62f651… stephan 1337 };
b62f651… stephan 1338 typedef struct yyParser yyParser;
b62f651… stephan 1339
b62f651… stephan 1340 #include <assert.h>
8f4a32c… drh 1341 #ifndef NDEBUG
8f4a32c… drh 1342 #include <stdio.h>
b62f651… stephan 1343 static FILE *yyTraceFILE = 0;
b62f651… stephan 1344 static char *yyTracePrompt = 0;
b62f651… stephan 1345 #endif /* NDEBUG */
b62f651… stephan 1346
b62f651… stephan 1347 #ifndef NDEBUG
b62f651… stephan 1348 /*
b62f651… stephan 1349 ** Turn parser tracing on by giving a stream to which to write the trace
b62f651… stephan 1350 ** and a prompt to preface each trace message. Tracing is turned off
b62f651… stephan 1351 ** by making either argument NULL
b62f651… stephan 1352 **
b62f651… stephan 1353 ** Inputs:
b62f651… stephan 1354 ** <ul>
b62f651… stephan 1355 ** <li> A FILE* to which trace output should be written.
b62f651… stephan 1356 ** If NULL, then tracing is turned off.
b62f651… stephan 1357 ** <li> A prefix string written at the beginning of every
b62f651… stephan 1358 ** line of trace output. If NULL, then tracing is
b62f651… stephan 1359 ** turned off.
b62f651… stephan 1360 ** </ul>
b62f651… stephan 1361 **
b62f651… stephan 1362 ** Outputs:
b62f651… stephan 1363 ** None.
b62f651… stephan 1364 */
b62f651… stephan 1365 void pik_parserTrace(FILE *TraceFILE, char *zTracePrompt){
b62f651… stephan 1366 yyTraceFILE = TraceFILE;
b62f651… stephan 1367 yyTracePrompt = zTracePrompt;
b62f651… stephan 1368 if( yyTraceFILE==0 ) yyTracePrompt = 0;
b62f651… stephan 1369 else if( yyTracePrompt==0 ) yyTraceFILE = 0;
b62f651… stephan 1370 }
b62f651… stephan 1371 #endif /* NDEBUG */
b62f651… stephan 1372
b62f651… stephan 1373 #if defined(YYCOVERAGE) || !defined(NDEBUG)
b62f651… stephan 1374 /* For tracing shifts, the names of all terminals and nonterminals
b62f651… stephan 1375 ** are required. The following table supplies these names */
b62f651… stephan 1376 static const char *const yyTokenName[] = {
b62f651… stephan 1377 /* 0 */ "$",
b62f651… stephan 1378 /* 1 */ "ID",
b62f651… stephan 1379 /* 2 */ "EDGEPT",
b62f651… stephan 1380 /* 3 */ "OF",
b62f651… stephan 1381 /* 4 */ "PLUS",
b62f651… stephan 1382 /* 5 */ "MINUS",
b62f651… stephan 1383 /* 6 */ "STAR",
b62f651… stephan 1384 /* 7 */ "SLASH",
b62f651… stephan 1385 /* 8 */ "PERCENT",
b62f651… stephan 1386 /* 9 */ "UMINUS",
b62f651… stephan 1387 /* 10 */ "EOL",
b62f651… stephan 1388 /* 11 */ "ASSIGN",
b62f651… stephan 1389 /* 12 */ "PLACENAME",
b62f651… stephan 1390 /* 13 */ "COLON",
b62f651… stephan 1391 /* 14 */ "ASSERT",
b62f651… stephan 1392 /* 15 */ "LP",
b62f651… stephan 1393 /* 16 */ "EQ",
b62f651… stephan 1394 /* 17 */ "RP",
b62f651… stephan 1395 /* 18 */ "DEFINE",
b62f651… stephan 1396 /* 19 */ "CODEBLOCK",
b62f651… stephan 1397 /* 20 */ "FILL",
b62f651… stephan 1398 /* 21 */ "COLOR",
b62f651… stephan 1399 /* 22 */ "THICKNESS",
b62f651… stephan 1400 /* 23 */ "PRINT",
b62f651… stephan 1401 /* 24 */ "STRING",
b62f651… stephan 1402 /* 25 */ "COMMA",
dd20f34… drh 1403 /* 26 */ "ISODATE",
dd20f34… drh 1404 /* 27 */ "CLASSNAME",
dd20f34… drh 1405 /* 28 */ "LB",
dd20f34… drh 1406 /* 29 */ "RB",
dd20f34… drh 1407 /* 30 */ "UP",
dd20f34… drh 1408 /* 31 */ "DOWN",
dd20f34… drh 1409 /* 32 */ "LEFT",
dd20f34… drh 1410 /* 33 */ "RIGHT",
dd20f34… drh 1411 /* 34 */ "CLOSE",
dd20f34… drh 1412 /* 35 */ "CHOP",
dd20f34… drh 1413 /* 36 */ "FROM",
dd20f34… drh 1414 /* 37 */ "TO",
dd20f34… drh 1415 /* 38 */ "THEN",
dd20f34… drh 1416 /* 39 */ "HEADING",
dd20f34… drh 1417 /* 40 */ "GO",
dd20f34… drh 1418 /* 41 */ "AT",
dd20f34… drh 1419 /* 42 */ "WITH",
dd20f34… drh 1420 /* 43 */ "SAME",
dd20f34… drh 1421 /* 44 */ "AS",
dd20f34… drh 1422 /* 45 */ "FIT",
dd20f34… drh 1423 /* 46 */ "BEHIND",
dd20f34… drh 1424 /* 47 */ "UNTIL",
dd20f34… drh 1425 /* 48 */ "EVEN",
dd20f34… drh 1426 /* 49 */ "DOT_E",
dd20f34… drh 1427 /* 50 */ "HEIGHT",
dd20f34… drh 1428 /* 51 */ "WIDTH",
dd20f34… drh 1429 /* 52 */ "RADIUS",
dd20f34… drh 1430 /* 53 */ "DIAMETER",
dd20f34… drh 1431 /* 54 */ "DOTTED",
dd20f34… drh 1432 /* 55 */ "DASHED",
dd20f34… drh 1433 /* 56 */ "CW",
dd20f34… drh 1434 /* 57 */ "CCW",
dd20f34… drh 1435 /* 58 */ "LARROW",
dd20f34… drh 1436 /* 59 */ "RARROW",
dd20f34… drh 1437 /* 60 */ "LRARROW",
dd20f34… drh 1438 /* 61 */ "INVIS",
dd20f34… drh 1439 /* 62 */ "THICK",
dd20f34… drh 1440 /* 63 */ "THIN",
dd20f34… drh 1441 /* 64 */ "SOLID",
dd20f34… drh 1442 /* 65 */ "CENTER",
dd20f34… drh 1443 /* 66 */ "LJUST",
dd20f34… drh 1444 /* 67 */ "RJUST",
dd20f34… drh 1445 /* 68 */ "ABOVE",
dd20f34… drh 1446 /* 69 */ "BELOW",
dd20f34… drh 1447 /* 70 */ "ITALIC",
dd20f34… drh 1448 /* 71 */ "BOLD",
dd20f34… drh 1449 /* 72 */ "MONO",
dd20f34… drh 1450 /* 73 */ "ALIGNED",
dd20f34… drh 1451 /* 74 */ "BIG",
dd20f34… drh 1452 /* 75 */ "SMALL",
dd20f34… drh 1453 /* 76 */ "AND",
dd20f34… drh 1454 /* 77 */ "LT",
dd20f34… drh 1455 /* 78 */ "GT",
dd20f34… drh 1456 /* 79 */ "ON",
dd20f34… drh 1457 /* 80 */ "WAY",
dd20f34… drh 1458 /* 81 */ "BETWEEN",
dd20f34… drh 1459 /* 82 */ "THE",
dd20f34… drh 1460 /* 83 */ "NTH",
dd20f34… drh 1461 /* 84 */ "VERTEX",
dd20f34… drh 1462 /* 85 */ "TOP",
dd20f34… drh 1463 /* 86 */ "BOTTOM",
dd20f34… drh 1464 /* 87 */ "START",
dd20f34… drh 1465 /* 88 */ "END",
dd20f34… drh 1466 /* 89 */ "IN",
dd20f34… drh 1467 /* 90 */ "THIS",
dd20f34… drh 1468 /* 91 */ "DOT_U",
dd20f34… drh 1469 /* 92 */ "LAST",
dd20f34… drh 1470 /* 93 */ "NUMBER",
dd20f34… drh 1471 /* 94 */ "FUNC1",
dd20f34… drh 1472 /* 95 */ "FUNC2",
dd20f34… drh 1473 /* 96 */ "DIST",
dd20f34… drh 1474 /* 97 */ "DOT_XY",
dd20f34… drh 1475 /* 98 */ "X",
dd20f34… drh 1476 /* 99 */ "Y",
dd20f34… drh 1477 /* 100 */ "DOT_L",
dd20f34… drh 1478 /* 101 */ "statement_list",
dd20f34… drh 1479 /* 102 */ "statement",
dd20f34… drh 1480 /* 103 */ "unnamed_statement",
dd20f34… drh 1481 /* 104 */ "basetype",
dd20f34… drh 1482 /* 105 */ "expr",
dd20f34… drh 1483 /* 106 */ "numproperty",
dd20f34… drh 1484 /* 107 */ "edge",
dd20f34… drh 1485 /* 108 */ "isodate",
dd20f34… drh 1486 /* 109 */ "direction",
dd20f34… drh 1487 /* 110 */ "dashproperty",
dd20f34… drh 1488 /* 111 */ "colorproperty",
dd20f34… drh 1489 /* 112 */ "locproperty",
dd20f34… drh 1490 /* 113 */ "position",
dd20f34… drh 1491 /* 114 */ "place",
dd20f34… drh 1492 /* 115 */ "object",
dd20f34… drh 1493 /* 116 */ "objectname",
dd20f34… drh 1494 /* 117 */ "nth",
dd20f34… drh 1495 /* 118 */ "textposition",
dd20f34… drh 1496 /* 119 */ "rvalue",
dd20f34… drh 1497 /* 120 */ "lvalue",
dd20f34… drh 1498 /* 121 */ "even",
dd20f34… drh 1499 /* 122 */ "relexpr",
dd20f34… drh 1500 /* 123 */ "optrelexpr",
dd20f34… drh 1501 /* 124 */ "document",
dd20f34… drh 1502 /* 125 */ "print",
dd20f34… drh 1503 /* 126 */ "prlist",
dd20f34… drh 1504 /* 127 */ "pritem",
dd20f34… drh 1505 /* 128 */ "prsep",
dd20f34… drh 1506 /* 129 */ "attribute_list",
dd20f34… drh 1507 /* 130 */ "savelist",
dd20f34… drh 1508 /* 131 */ "alist",
dd20f34… drh 1509 /* 132 */ "attribute",
dd20f34… drh 1510 /* 133 */ "go",
dd20f34… drh 1511 /* 134 */ "boolproperty",
dd20f34… drh 1512 /* 135 */ "withclause",
dd20f34… drh 1513 /* 136 */ "between",
dd20f34… drh 1514 /* 137 */ "place2",
b62f651… stephan 1515 };
b62f651… stephan 1516 #endif /* defined(YYCOVERAGE) || !defined(NDEBUG) */
b62f651… stephan 1517
b62f651… stephan 1518 #ifndef NDEBUG
b62f651… stephan 1519 /* For tracing reduce actions, the names of all rules are required.
b62f651… stephan 1520 */
b62f651… stephan 1521 static const char *const yyRuleName[] = {
b62f651… stephan 1522 /* 0 */ "document ::= statement_list",
b62f651… stephan 1523 /* 1 */ "statement_list ::= statement",
b62f651… stephan 1524 /* 2 */ "statement_list ::= statement_list EOL statement",
b62f651… stephan 1525 /* 3 */ "statement ::=",
b62f651… stephan 1526 /* 4 */ "statement ::= direction",
b62f651… stephan 1527 /* 5 */ "statement ::= lvalue ASSIGN rvalue",
b62f651… stephan 1528 /* 6 */ "statement ::= PLACENAME COLON unnamed_statement",
b62f651… stephan 1529 /* 7 */ "statement ::= PLACENAME COLON position",
b62f651… stephan 1530 /* 8 */ "statement ::= unnamed_statement",
b62f651… stephan 1531 /* 9 */ "statement ::= print prlist",
b62f651… stephan 1532 /* 10 */ "statement ::= ASSERT LP expr EQ expr RP",
b62f651… stephan 1533 /* 11 */ "statement ::= ASSERT LP position EQ position RP",
b62f651… stephan 1534 /* 12 */ "statement ::= DEFINE ID CODEBLOCK",
b62f651… stephan 1535 /* 13 */ "rvalue ::= PLACENAME",
b62f651… stephan 1536 /* 14 */ "pritem ::= FILL",
b62f651… stephan 1537 /* 15 */ "pritem ::= COLOR",
b62f651… stephan 1538 /* 16 */ "pritem ::= THICKNESS",
b62f651… stephan 1539 /* 17 */ "pritem ::= rvalue",
b62f651… stephan 1540 /* 18 */ "pritem ::= STRING",
b62f651… stephan 1541 /* 19 */ "prsep ::= COMMA",
b62f651… stephan 1542 /* 20 */ "unnamed_statement ::= basetype attribute_list",
b62f651… stephan 1543 /* 21 */ "basetype ::= CLASSNAME",
b62f651… stephan 1544 /* 22 */ "basetype ::= STRING textposition",
b62f651… stephan 1545 /* 23 */ "basetype ::= LB savelist statement_list RB",
b62f651… stephan 1546 /* 24 */ "savelist ::=",
b62f651… stephan 1547 /* 25 */ "relexpr ::= expr",
b62f651… stephan 1548 /* 26 */ "relexpr ::= expr PERCENT",
b62f651… stephan 1549 /* 27 */ "optrelexpr ::=",
b62f651… stephan 1550 /* 28 */ "attribute_list ::= relexpr alist",
b62f651… stephan 1551 /* 29 */ "attribute ::= numproperty relexpr",
b62f651… stephan 1552 /* 30 */ "attribute ::= dashproperty expr",
b62f651… stephan 1553 /* 31 */ "attribute ::= dashproperty",
b62f651… stephan 1554 /* 32 */ "attribute ::= colorproperty rvalue",
b62f651… stephan 1555 /* 33 */ "attribute ::= go direction optrelexpr",
b62f651… stephan 1556 /* 34 */ "attribute ::= go direction even position",
b62f651… stephan 1557 /* 35 */ "attribute ::= CLOSE",
b62f651… stephan 1558 /* 36 */ "attribute ::= CHOP",
b62f651… stephan 1559 /* 37 */ "attribute ::= FROM position",
b62f651… stephan 1560 /* 38 */ "attribute ::= TO position",
b62f651… stephan 1561 /* 39 */ "attribute ::= THEN",
b62f651… stephan 1562 /* 40 */ "attribute ::= THEN optrelexpr HEADING expr",
b62f651… stephan 1563 /* 41 */ "attribute ::= THEN optrelexpr EDGEPT",
b62f651… stephan 1564 /* 42 */ "attribute ::= GO optrelexpr HEADING expr",
b62f651… stephan 1565 /* 43 */ "attribute ::= GO optrelexpr EDGEPT",
b62f651… stephan 1566 /* 44 */ "attribute ::= AT position",
b62f651… stephan 1567 /* 45 */ "attribute ::= SAME",
b62f651… stephan 1568 /* 46 */ "attribute ::= SAME AS object",
b62f651… stephan 1569 /* 47 */ "attribute ::= STRING textposition",
b62f651… stephan 1570 /* 48 */ "attribute ::= FIT",
b62f651… stephan 1571 /* 49 */ "attribute ::= BEHIND object",
b62f651… stephan 1572 /* 50 */ "withclause ::= DOT_E edge AT position",
b62f651… stephan 1573 /* 51 */ "withclause ::= edge AT position",
b62f651… stephan 1574 /* 52 */ "numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS",
b62f651… stephan 1575 /* 53 */ "boolproperty ::= CW",
b62f651… stephan 1576 /* 54 */ "boolproperty ::= CCW",
b62f651… stephan 1577 /* 55 */ "boolproperty ::= LARROW",
b62f651… stephan 1578 /* 56 */ "boolproperty ::= RARROW",
b62f651… stephan 1579 /* 57 */ "boolproperty ::= LRARROW",
b62f651… stephan 1580 /* 58 */ "boolproperty ::= INVIS",
b62f651… stephan 1581 /* 59 */ "boolproperty ::= THICK",
b62f651… stephan 1582 /* 60 */ "boolproperty ::= THIN",
b62f651… stephan 1583 /* 61 */ "boolproperty ::= SOLID",
b62f651… stephan 1584 /* 62 */ "textposition ::=",
43eefe6… drh 1585 /* 63 */ "textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL",
b62f651… stephan 1586 /* 64 */ "position ::= expr COMMA expr",
b62f651… stephan 1587 /* 65 */ "position ::= place PLUS expr COMMA expr",
b62f651… stephan 1588 /* 66 */ "position ::= place MINUS expr COMMA expr",
b62f651… stephan 1589 /* 67 */ "position ::= place PLUS LP expr COMMA expr RP",
b62f651… stephan 1590 /* 68 */ "position ::= place MINUS LP expr COMMA expr RP",
b62f651… stephan 1591 /* 69 */ "position ::= LP position COMMA position RP",
b62f651… stephan 1592 /* 70 */ "position ::= LP position RP",
b62f651… stephan 1593 /* 71 */ "position ::= expr between position AND position",
b62f651… stephan 1594 /* 72 */ "position ::= expr LT position COMMA position GT",
b62f651… stephan 1595 /* 73 */ "position ::= expr ABOVE position",
b62f651… stephan 1596 /* 74 */ "position ::= expr BELOW position",
b62f651… stephan 1597 /* 75 */ "position ::= expr LEFT OF position",
b62f651… stephan 1598 /* 76 */ "position ::= expr RIGHT OF position",
b62f651… stephan 1599 /* 77 */ "position ::= expr ON HEADING EDGEPT OF position",
b62f651… stephan 1600 /* 78 */ "position ::= expr HEADING EDGEPT OF position",
b62f651… stephan 1601 /* 79 */ "position ::= expr EDGEPT OF position",
b62f651… stephan 1602 /* 80 */ "position ::= expr ON HEADING expr FROM position",
b62f651… stephan 1603 /* 81 */ "position ::= expr HEADING expr FROM position",
b62f651… stephan 1604 /* 82 */ "place ::= edge OF object",
b62f651… stephan 1605 /* 83 */ "place2 ::= object",
b62f651… stephan 1606 /* 84 */ "place2 ::= object DOT_E edge",
b62f651… stephan 1607 /* 85 */ "place2 ::= NTH VERTEX OF object",
b62f651… stephan 1608 /* 86 */ "object ::= nth",
b62f651… stephan 1609 /* 87 */ "object ::= nth OF|IN object",
b62f651… stephan 1610 /* 88 */ "objectname ::= THIS",
b62f651… stephan 1611 /* 89 */ "objectname ::= PLACENAME",
b62f651… stephan 1612 /* 90 */ "objectname ::= objectname DOT_U PLACENAME",
b62f651… stephan 1613 /* 91 */ "nth ::= NTH CLASSNAME",
b62f651… stephan 1614 /* 92 */ "nth ::= NTH LAST CLASSNAME",
b62f651… stephan 1615 /* 93 */ "nth ::= LAST CLASSNAME",
b62f651… stephan 1616 /* 94 */ "nth ::= LAST",
b62f651… stephan 1617 /* 95 */ "nth ::= NTH LB RB",
b62f651… stephan 1618 /* 96 */ "nth ::= NTH LAST LB RB",
b62f651… stephan 1619 /* 97 */ "nth ::= LAST LB RB",
b62f651… stephan 1620 /* 98 */ "expr ::= expr PLUS expr",
b62f651… stephan 1621 /* 99 */ "expr ::= expr MINUS expr",
b62f651… stephan 1622 /* 100 */ "expr ::= expr STAR expr",
b62f651… stephan 1623 /* 101 */ "expr ::= expr SLASH expr",
b62f651… stephan 1624 /* 102 */ "expr ::= MINUS expr",
b62f651… stephan 1625 /* 103 */ "expr ::= PLUS expr",
b62f651… stephan 1626 /* 104 */ "expr ::= LP expr RP",
b62f651… stephan 1627 /* 105 */ "expr ::= LP FILL|COLOR|THICKNESS RP",
b62f651… stephan 1628 /* 106 */ "expr ::= NUMBER",
b62f651… stephan 1629 /* 107 */ "expr ::= ID",
b62f651… stephan 1630 /* 108 */ "expr ::= FUNC1 LP expr RP",
b62f651… stephan 1631 /* 109 */ "expr ::= FUNC2 LP expr COMMA expr RP",
b62f651… stephan 1632 /* 110 */ "expr ::= DIST LP position COMMA position RP",
b62f651… stephan 1633 /* 111 */ "expr ::= place2 DOT_XY X",
b62f651… stephan 1634 /* 112 */ "expr ::= place2 DOT_XY Y",
b62f651… stephan 1635 /* 113 */ "expr ::= object DOT_L numproperty",
b62f651… stephan 1636 /* 114 */ "expr ::= object DOT_L dashproperty",
b62f651… stephan 1637 /* 115 */ "expr ::= object DOT_L colorproperty",
b62f651… stephan 1638 /* 116 */ "lvalue ::= ID",
b62f651… stephan 1639 /* 117 */ "lvalue ::= FILL",
b62f651… stephan 1640 /* 118 */ "lvalue ::= COLOR",
b62f651… stephan 1641 /* 119 */ "lvalue ::= THICKNESS",
b62f651… stephan 1642 /* 120 */ "rvalue ::= expr",
b62f651… stephan 1643 /* 121 */ "print ::= PRINT",
b62f651… stephan 1644 /* 122 */ "prlist ::= pritem",
b62f651… stephan 1645 /* 123 */ "prlist ::= prlist prsep pritem",
b62f651… stephan 1646 /* 124 */ "direction ::= UP",
b62f651… stephan 1647 /* 125 */ "direction ::= DOWN",
b62f651… stephan 1648 /* 126 */ "direction ::= LEFT",
b62f651… stephan 1649 /* 127 */ "direction ::= RIGHT",
b62f651… stephan 1650 /* 128 */ "optrelexpr ::= relexpr",
b62f651… stephan 1651 /* 129 */ "attribute_list ::= alist",
b62f651… stephan 1652 /* 130 */ "alist ::=",
b62f651… stephan 1653 /* 131 */ "alist ::= alist attribute",
b62f651… stephan 1654 /* 132 */ "attribute ::= boolproperty",
b62f651… stephan 1655 /* 133 */ "attribute ::= WITH withclause",
b62f651… stephan 1656 /* 134 */ "go ::= GO",
b62f651… stephan 1657 /* 135 */ "go ::=",
b62f651… stephan 1658 /* 136 */ "even ::= UNTIL EVEN WITH",
b62f651… stephan 1659 /* 137 */ "even ::= EVEN WITH",
b62f651… stephan 1660 /* 138 */ "dashproperty ::= DOTTED",
b62f651… stephan 1661 /* 139 */ "dashproperty ::= DASHED",
b62f651… stephan 1662 /* 140 */ "colorproperty ::= FILL",
b62f651… stephan 1663 /* 141 */ "colorproperty ::= COLOR",
b62f651… stephan 1664 /* 142 */ "position ::= place",
b62f651… stephan 1665 /* 143 */ "between ::= WAY BETWEEN",
b62f651… stephan 1666 /* 144 */ "between ::= BETWEEN",
b62f651… stephan 1667 /* 145 */ "between ::= OF THE WAY BETWEEN",
b62f651… stephan 1668 /* 146 */ "place ::= place2",
b62f651… stephan 1669 /* 147 */ "edge ::= CENTER",
b62f651… stephan 1670 /* 148 */ "edge ::= EDGEPT",
b62f651… stephan 1671 /* 149 */ "edge ::= TOP",
b62f651… stephan 1672 /* 150 */ "edge ::= BOTTOM",
b62f651… stephan 1673 /* 151 */ "edge ::= START",
b62f651… stephan 1674 /* 152 */ "edge ::= END",
b62f651… stephan 1675 /* 153 */ "edge ::= RIGHT",
b62f651… stephan 1676 /* 154 */ "edge ::= LEFT",
b62f651… stephan 1677 /* 155 */ "object ::= objectname",
b62f651… stephan 1678 };
b62f651… stephan 1679 #endif /* NDEBUG */
b62f651… stephan 1680
b62f651… stephan 1681
f4ec8e0… drh 1682 #if YYGROWABLESTACK
b62f651… stephan 1683 /*
b62f651… stephan 1684 ** Try to increase the size of the parser stack. Return the number
b62f651… stephan 1685 ** of errors. Return 0 on success.
b62f651… stephan 1686 */
b62f651… stephan 1687 static int yyGrowStack(yyParser *p){
f4ec8e0… drh 1688 int oldSize = 1 + (int)(p->yystackEnd - p->yystack);
b62f651… stephan 1689 int newSize;
b62f651… stephan 1690 int idx;
b62f651… stephan 1691 yyStackEntry *pNew;
b62f651… stephan 1692
f4ec8e0… drh 1693 newSize = oldSize*2 + 100;
f4ec8e0… drh 1694 idx = (int)(p->yytos - p->yystack);
f4ec8e0… drh 1695 if( p->yystack==p->yystk0 ){
f4ec8e0… drh 1696 pNew = YYREALLOC(0, newSize*sizeof(pNew[0]));
f4ec8e0… drh 1697 if( pNew==0 ) return 1;
f4ec8e0… drh 1698 memcpy(pNew, p->yystack, oldSize*sizeof(pNew[0]));
b62f651… stephan 1699 }else{
f4ec8e0… drh 1700 pNew = YYREALLOC(p->yystack, newSize*sizeof(pNew[0]));
f4ec8e0… drh 1701 if( pNew==0 ) return 1;
b62f651… stephan 1702 }
f4ec8e0… drh 1703 p->yystack = pNew;
f4ec8e0… drh 1704 p->yytos = &p->yystack[idx];
b62f651… stephan 1705 #ifndef NDEBUG
f4ec8e0… drh 1706 if( yyTraceFILE ){
f4ec8e0… drh 1707 fprintf(yyTraceFILE,"%sStack grows from %d to %d entries.\n",
f4ec8e0… drh 1708 yyTracePrompt, oldSize, newSize);
f4ec8e0… drh 1709 }
b62f651… stephan 1710 #endif
f4ec8e0… drh 1711 p->yystackEnd = &p->yystack[newSize-1];
f4ec8e0… drh 1712 return 0;
b62f651… stephan 1713 }
f4ec8e0… drh 1714 #endif /* YYGROWABLESTACK */
f4ec8e0… drh 1715
f4ec8e0… drh 1716 #if !YYGROWABLESTACK
f4ec8e0… drh 1717 /* For builds that do no have a growable stack, yyGrowStack always
f4ec8e0… drh 1718 ** returns an error.
f4ec8e0… drh 1719 */
f4ec8e0… drh 1720 # define yyGrowStack(X) 1
b62f651… stephan 1721 #endif
b62f651… stephan 1722
b62f651… stephan 1723 /* Datatype of the argument to the memory allocated passed as the
b62f651… stephan 1724 ** second argument to pik_parserAlloc() below. This can be changed by
b62f651… stephan 1725 ** putting an appropriate #define in the %include section of the input
b62f651… stephan 1726 ** grammar.
b62f651… stephan 1727 */
b62f651… stephan 1728 #ifndef YYMALLOCARGTYPE
b62f651… stephan 1729 # define YYMALLOCARGTYPE size_t
b62f651… stephan 1730 #endif
b62f651… stephan 1731
b62f651… stephan 1732 /* Initialize a new parser that has already been allocated.
b62f651… stephan 1733 */
b62f651… stephan 1734 void pik_parserInit(void *yypRawParser pik_parserCTX_PDECL){
b62f651… stephan 1735 yyParser *yypParser = (yyParser*)yypRawParser;
b62f651… stephan 1736 pik_parserCTX_STORE
b62f651… stephan 1737 #ifdef YYTRACKMAXSTACKDEPTH
b62f651… stephan 1738 yypParser->yyhwm = 0;
b62f651… stephan 1739 #endif
f4ec8e0… drh 1740 yypParser->yystack = yypParser->yystk0;
f4ec8e0… drh 1741 yypParser->yystackEnd = &yypParser->yystack[YYSTACKDEPTH-1];
b62f651… stephan 1742 #ifndef YYNOERRORRECOVERY
b62f651… stephan 1743 yypParser->yyerrcnt = -1;
b62f651… stephan 1744 #endif
b62f651… stephan 1745 yypParser->yytos = yypParser->yystack;
b62f651… stephan 1746 yypParser->yystack[0].stateno = 0;
b62f651… stephan 1747 yypParser->yystack[0].major = 0;
b62f651… stephan 1748 }
b62f651… stephan 1749
b62f651… stephan 1750 #ifndef pik_parser_ENGINEALWAYSONSTACK
b62f651… stephan 1751 /*
b62f651… stephan 1752 ** This function allocates a new parser.
b62f651… stephan 1753 ** The only argument is a pointer to a function which works like
b62f651… stephan 1754 ** malloc.
b62f651… stephan 1755 **
b62f651… stephan 1756 ** Inputs:
b62f651… stephan 1757 ** A pointer to the function used to allocate memory.
b62f651… stephan 1758 **
b62f651… stephan 1759 ** Outputs:
b62f651… stephan 1760 ** A pointer to a parser. This pointer is used in subsequent calls
b62f651… stephan 1761 ** to pik_parser and pik_parserFree.
b62f651… stephan 1762 */
b62f651… stephan 1763 void *pik_parserAlloc(void *(*mallocProc)(YYMALLOCARGTYPE) pik_parserCTX_PDECL){
b62f651… stephan 1764 yyParser *yypParser;
b62f651… stephan 1765 yypParser = (yyParser*)(*mallocProc)( (YYMALLOCARGTYPE)sizeof(yyParser) );
b62f651… stephan 1766 if( yypParser ){
b62f651… stephan 1767 pik_parserCTX_STORE
b62f651… stephan 1768 pik_parserInit(yypParser pik_parserCTX_PARAM);
b62f651… stephan 1769 }
b62f651… stephan 1770 return (void*)yypParser;
b62f651… stephan 1771 }
b62f651… stephan 1772 #endif /* pik_parser_ENGINEALWAYSONSTACK */
b62f651… stephan 1773
b62f651… stephan 1774
b62f651… stephan 1775 /* The following function deletes the "minor type" or semantic value
b62f651… stephan 1776 ** associated with a symbol. The symbol can be either a terminal
b62f651… stephan 1777 ** or nonterminal. "yymajor" is the symbol code, and "yypminor" is
b62f651… stephan 1778 ** a pointer to the value to be deleted. The code used to do the
b62f651… stephan 1779 ** deletions is derived from the %destructor and/or %token_destructor
b62f651… stephan 1780 ** directives of the input grammar.
b62f651… stephan 1781 */
b62f651… stephan 1782 static void yy_destructor(
b62f651… stephan 1783 yyParser *yypParser, /* The parser */
b62f651… stephan 1784 YYCODETYPE yymajor, /* Type code for object to destroy */
b62f651… stephan 1785 YYMINORTYPE *yypminor /* The object to be destroyed */
b62f651… stephan 1786 ){
b62f651… stephan 1787 pik_parserARG_FETCH
b62f651… stephan 1788 pik_parserCTX_FETCH
b62f651… stephan 1789 switch( yymajor ){
b62f651… stephan 1790 /* Here is inserted the actions which take place when a
b62f651… stephan 1791 ** terminal or non-terminal is destroyed. This can happen
b62f651… stephan 1792 ** when the symbol is popped from the stack during a
b62f651… stephan 1793 ** reduce or during error processing or when a parser is
b62f651… stephan 1794 ** being destroyed before it is finished parsing.
b62f651… stephan 1795 **
b62f651… stephan 1796 ** Note: during a reduce, the only symbols destroyed are those
b62f651… stephan 1797 ** which appear on the RHS of the rule, but which are *not* used
b62f651… stephan 1798 ** inside the C code.
b62f651… stephan 1799 */
b62f651… stephan 1800 /********* Begin destructor definitions ***************************************/
dd20f34… drh 1801 case 101: /* statement_list */
dd20f34… drh 1802 {
dd20f34… drh 1803 #line 524 "pikchr.y"
dd20f34… drh 1804 pik_elist_free(p,(yypminor->yy23));
dd20f34… drh 1805 #line 1805 "pikchr.c"
dd20f34… drh 1806 }
dd20f34… drh 1807 break;
dd20f34… drh 1808 case 102: /* statement */
dd20f34… drh 1809 case 103: /* unnamed_statement */
dd20f34… drh 1810 case 104: /* basetype */
dd20f34… drh 1811 {
dd20f34… drh 1812 #line 526 "pikchr.y"
dd20f34… drh 1813 pik_elem_free(p,(yypminor->yy54));
dd20f34… drh 1814 #line 1814 "pikchr.c"
b62f651… stephan 1815 }
b62f651… stephan 1816 break;
b62f651… stephan 1817 /********* End destructor definitions *****************************************/
b62f651… stephan 1818 default: break; /* If no destructor action specified: do nothing */
b62f651… stephan 1819 }
b62f651… stephan 1820 }
b62f651… stephan 1821
b62f651… stephan 1822 /*
b62f651… stephan 1823 ** Pop the parser's stack once.
b62f651… stephan 1824 **
b62f651… stephan 1825 ** If there is a destructor routine associated with the token which
b62f651… stephan 1826 ** is popped from the stack, then call it.
b62f651… stephan 1827 */
b62f651… stephan 1828 static void yy_pop_parser_stack(yyParser *pParser){
b62f651… stephan 1829 yyStackEntry *yytos;
b62f651… stephan 1830 assert( pParser->yytos!=0 );
b62f651… stephan 1831 assert( pParser->yytos > pParser->yystack );
b62f651… stephan 1832 yytos = pParser->yytos--;
b62f651… stephan 1833 #ifndef NDEBUG
b62f651… stephan 1834 if( yyTraceFILE ){
b62f651… stephan 1835 fprintf(yyTraceFILE,"%sPopping %s\n",
b62f651… stephan 1836 yyTracePrompt,
b62f651… stephan 1837 yyTokenName[yytos->major]);
b62f651… stephan 1838 }
b62f651… stephan 1839 #endif
b62f651… stephan 1840 yy_destructor(pParser, yytos->major, &yytos->minor);
b62f651… stephan 1841 }
b62f651… stephan 1842
b62f651… stephan 1843 /*
b62f651… stephan 1844 ** Clear all secondary memory allocations from the parser
b62f651… stephan 1845 */
b62f651… stephan 1846 void pik_parserFinalize(void *p){
b62f651… stephan 1847 yyParser *pParser = (yyParser*)p;
f4ec8e0… drh 1848
f4ec8e0… drh 1849 /* In-lined version of calling yy_pop_parser_stack() for each
f4ec8e0… drh 1850 ** element left in the stack */
f4ec8e0… drh 1851 yyStackEntry *yytos = pParser->yytos;
f4ec8e0… drh 1852 while( yytos>pParser->yystack ){
f4ec8e0… drh 1853 #ifndef NDEBUG
f4ec8e0… drh 1854 if( yyTraceFILE ){
f4ec8e0… drh 1855 fprintf(yyTraceFILE,"%sPopping %s\n",
f4ec8e0… drh 1856 yyTracePrompt,
f4ec8e0… drh 1857 yyTokenName[yytos->major]);
f4ec8e0… drh 1858 }
f4ec8e0… drh 1859 #endif
f4ec8e0… drh 1860 if( yytos->major>=YY_MIN_DSTRCTR ){
f4ec8e0… drh 1861 yy_destructor(pParser, yytos->major, &yytos->minor);
f4ec8e0… drh 1862 }
f4ec8e0… drh 1863 yytos--;
f4ec8e0… drh 1864 }
f4ec8e0… drh 1865
f4ec8e0… drh 1866 #if YYGROWABLESTACK
f4ec8e0… drh 1867 if( pParser->yystack!=pParser->yystk0 ) YYFREE(pParser->yystack);
b62f651… stephan 1868 #endif
b62f651… stephan 1869 }
b62f651… stephan 1870
b62f651… stephan 1871 #ifndef pik_parser_ENGINEALWAYSONSTACK
b62f651… stephan 1872 /*
b62f651… stephan 1873 ** Deallocate and destroy a parser. Destructors are called for
b62f651… stephan 1874 ** all stack elements before shutting the parser down.
b62f651… stephan 1875 **
b62f651… stephan 1876 ** If the YYPARSEFREENEVERNULL macro exists (for example because it
b62f651… stephan 1877 ** is defined in a %include section of the input grammar) then it is
b62f651… stephan 1878 ** assumed that the input pointer is never NULL.
b62f651… stephan 1879 */
b62f651… stephan 1880 void pik_parserFree(
b62f651… stephan 1881 void *p, /* The parser to be deleted */
b62f651… stephan 1882 void (*freeProc)(void*) /* Function used to reclaim memory */
b62f651… stephan 1883 ){
b62f651… stephan 1884 #ifndef YYPARSEFREENEVERNULL
b62f651… stephan 1885 if( p==0 ) return;
b62f651… stephan 1886 #endif
b62f651… stephan 1887 pik_parserFinalize(p);
b62f651… stephan 1888 (*freeProc)(p);
b62f651… stephan 1889 }
b62f651… stephan 1890 #endif /* pik_parser_ENGINEALWAYSONSTACK */
b62f651… stephan 1891
b62f651… stephan 1892 /*
b62f651… stephan 1893 ** Return the peak depth of the stack for a parser.
b62f651… stephan 1894 */
b62f651… stephan 1895 #ifdef YYTRACKMAXSTACKDEPTH
b62f651… stephan 1896 int pik_parserStackPeak(void *p){
b62f651… stephan 1897 yyParser *pParser = (yyParser*)p;
b62f651… stephan 1898 return pParser->yyhwm;
b62f651… stephan 1899 }
b62f651… stephan 1900 #endif
b62f651… stephan 1901
b62f651… stephan 1902 /* This array of booleans keeps track of the parser statement
b62f651… stephan 1903 ** coverage. The element yycoverage[X][Y] is set when the parser
b62f651… stephan 1904 ** is in state X and has a lookahead token Y. In a well-tested
b62f651… stephan 1905 ** systems, every element of this matrix should end up being set.
b62f651… stephan 1906 */
b62f651… stephan 1907 #if defined(YYCOVERAGE)
b62f651… stephan 1908 static unsigned char yycoverage[YYNSTATE][YYNTOKEN];
b62f651… stephan 1909 #endif
b62f651… stephan 1910
b62f651… stephan 1911 /*
b62f651… stephan 1912 ** Write into out a description of every state/lookahead combination that
b62f651… stephan 1913 **
b62f651… stephan 1914 ** (1) has not been used by the parser, and
b62f651… stephan 1915 ** (2) is not a syntax error.
b62f651… stephan 1916 **
b62f651… stephan 1917 ** Return the number of missed state/lookahead combinations.
b62f651… stephan 1918 */
b62f651… stephan 1919 #if defined(YYCOVERAGE)
b62f651… stephan 1920 int pik_parserCoverage(FILE *out){
b62f651… stephan 1921 int stateno, iLookAhead, i;
b62f651… stephan 1922 int nMissed = 0;
b62f651… stephan 1923 for(stateno=0; stateno<YYNSTATE; stateno++){
b62f651… stephan 1924 i = yy_shift_ofst[stateno];
b62f651… stephan 1925 for(iLookAhead=0; iLookAhead<YYNTOKEN; iLookAhead++){
b62f651… stephan 1926 if( yy_lookahead[i+iLookAhead]!=iLookAhead ) continue;
b62f651… stephan 1927 if( yycoverage[stateno][iLookAhead]==0 ) nMissed++;
b62f651… stephan 1928 if( out ){
b62f651… stephan 1929 fprintf(out,"State %d lookahead %s %s\n", stateno,
b62f651… stephan 1930 yyTokenName[iLookAhead],
b62f651… stephan 1931 yycoverage[stateno][iLookAhead] ? "ok" : "missed");
b62f651… stephan 1932 }
b62f651… stephan 1933 }
b62f651… stephan 1934 }
b62f651… stephan 1935 return nMissed;
b62f651… stephan 1936 }
b62f651… stephan 1937 #endif
b62f651… stephan 1938
b62f651… stephan 1939 /*
b62f651… stephan 1940 ** Find the appropriate action for a parser given the terminal
b62f651… stephan 1941 ** look-ahead token iLookAhead.
b62f651… stephan 1942 */
b62f651… stephan 1943 static YYACTIONTYPE yy_find_shift_action(
b62f651… stephan 1944 YYCODETYPE iLookAhead, /* The look-ahead token */
b62f651… stephan 1945 YYACTIONTYPE stateno /* Current state number */
b62f651… stephan 1946 ){
b62f651… stephan 1947 int i;
b62f651… stephan 1948
b62f651… stephan 1949 if( stateno>YY_MAX_SHIFT ) return stateno;
b62f651… stephan 1950 assert( stateno <= YY_SHIFT_COUNT );
b62f651… stephan 1951 #if defined(YYCOVERAGE)
b62f651… stephan 1952 yycoverage[stateno][iLookAhead] = 1;
b62f651… stephan 1953 #endif
b62f651… stephan 1954 do{
b62f651… stephan 1955 i = yy_shift_ofst[stateno];
b62f651… stephan 1956 assert( i>=0 );
b62f651… stephan 1957 assert( i<=YY_ACTTAB_COUNT );
b62f651… stephan 1958 assert( i+YYNTOKEN<=(int)YY_NLOOKAHEAD );
b62f651… stephan 1959 assert( iLookAhead!=YYNOCODE );
b62f651… stephan 1960 assert( iLookAhead < YYNTOKEN );
b62f651… stephan 1961 i += iLookAhead;
b62f651… stephan 1962 assert( i<(int)YY_NLOOKAHEAD );
b62f651… stephan 1963 if( yy_lookahead[i]!=iLookAhead ){
b62f651… stephan 1964 #ifdef YYFALLBACK
b62f651… stephan 1965 YYCODETYPE iFallback; /* Fallback token */
b62f651… stephan 1966 assert( iLookAhead<sizeof(yyFallback)/sizeof(yyFallback[0]) );
b62f651… stephan 1967 iFallback = yyFallback[iLookAhead];
b62f651… stephan 1968 if( iFallback!=0 ){
b62f651… stephan 1969 #ifndef NDEBUG
b62f651… stephan 1970 if( yyTraceFILE ){
b62f651… stephan 1971 fprintf(yyTraceFILE, "%sFALLBACK %s => %s\n",
b62f651… stephan 1972 yyTracePrompt, yyTokenName[iLookAhead], yyTokenName[iFallback]);
b62f651… stephan 1973 }
b62f651… stephan 1974 #endif
b62f651… stephan 1975 assert( yyFallback[iFallback]==0 ); /* Fallback loop must terminate */
b62f651… stephan 1976 iLookAhead = iFallback;
b62f651… stephan 1977 continue;
b62f651… stephan 1978 }
b62f651… stephan 1979 #endif
b62f651… stephan 1980 #ifdef YYWILDCARD
b62f651… stephan 1981 {
b62f651… stephan 1982 int j = i - iLookAhead + YYWILDCARD;
b62f651… stephan 1983 assert( j<(int)(sizeof(yy_lookahead)/sizeof(yy_lookahead[0])) );
b62f651… stephan 1984 if( yy_lookahead[j]==YYWILDCARD && iLookAhead>0 ){
b62f651… stephan 1985 #ifndef NDEBUG
b62f651… stephan 1986 if( yyTraceFILE ){
b62f651… stephan 1987 fprintf(yyTraceFILE, "%sWILDCARD %s => %s\n",
b62f651… stephan 1988 yyTracePrompt, yyTokenName[iLookAhead],
b62f651… stephan 1989 yyTokenName[YYWILDCARD]);
b62f651… stephan 1990 }
b62f651… stephan 1991 #endif /* NDEBUG */
b62f651… stephan 1992 return yy_action[j];
b62f651… stephan 1993 }
b62f651… stephan 1994 }
b62f651… stephan 1995 #endif /* YYWILDCARD */
b62f651… stephan 1996 return yy_default[stateno];
b62f651… stephan 1997 }else{
b62f651… stephan 1998 assert( i>=0 && i<(int)(sizeof(yy_action)/sizeof(yy_action[0])) );
b62f651… stephan 1999 return yy_action[i];
b62f651… stephan 2000 }
b62f651… stephan 2001 }while(1);
b62f651… stephan 2002 }
b62f651… stephan 2003
b62f651… stephan 2004 /*
b62f651… stephan 2005 ** Find the appropriate action for a parser given the non-terminal
b62f651… stephan 2006 ** look-ahead token iLookAhead.
b62f651… stephan 2007 */
b62f651… stephan 2008 static YYACTIONTYPE yy_find_reduce_action(
b62f651… stephan 2009 YYACTIONTYPE stateno, /* Current state number */
b62f651… stephan 2010 YYCODETYPE iLookAhead /* The look-ahead token */
b62f651… stephan 2011 ){
b62f651… stephan 2012 int i;
b62f651… stephan 2013 #ifdef YYERRORSYMBOL
b62f651… stephan 2014 if( stateno>YY_REDUCE_COUNT ){
b62f651… stephan 2015 return yy_default[stateno];
b62f651… stephan 2016 }
b62f651… stephan 2017 #else
b62f651… stephan 2018 assert( stateno<=YY_REDUCE_COUNT );
b62f651… stephan 2019 #endif
b62f651… stephan 2020 i = yy_reduce_ofst[stateno];
b62f651… stephan 2021 assert( iLookAhead!=YYNOCODE );
b62f651… stephan 2022 i += iLookAhead;
b62f651… stephan 2023 #ifdef YYERRORSYMBOL
b62f651… stephan 2024 if( i<0 || i>=YY_ACTTAB_COUNT || yy_lookahead[i]!=iLookAhead ){
b62f651… stephan 2025 return yy_default[stateno];
b62f651… stephan 2026 }
b62f651… stephan 2027 #else
b62f651… stephan 2028 assert( i>=0 && i<YY_ACTTAB_COUNT );
b62f651… stephan 2029 assert( yy_lookahead[i]==iLookAhead );
b62f651… stephan 2030 #endif
b62f651… stephan 2031 return yy_action[i];
b62f651… stephan 2032 }
b62f651… stephan 2033
b62f651… stephan 2034 /*
b62f651… stephan 2035 ** The following routine is called if the stack overflows.
b62f651… stephan 2036 */
b62f651… stephan 2037 static void yyStackOverflow(yyParser *yypParser){
b62f651… stephan 2038 pik_parserARG_FETCH
b62f651… stephan 2039 pik_parserCTX_FETCH
b62f651… stephan 2040 #ifndef NDEBUG
b62f651… stephan 2041 if( yyTraceFILE ){
b62f651… stephan 2042 fprintf(yyTraceFILE,"%sStack Overflow!\n",yyTracePrompt);
b62f651… stephan 2043 }
b62f651… stephan 2044 #endif
b62f651… stephan 2045 while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
b62f651… stephan 2046 /* Here code is inserted which will execute if the parser
b62f651… stephan 2047 ** stack every overflows */
b62f651… stephan 2048 /******** Begin %stack_overflow code ******************************************/
dd20f34… drh 2049 #line 559 "pikchr.y"
b62f651… stephan 2050
b62f651… stephan 2051 pik_error(p, 0, "parser stack overflow");
dd20f34… drh 2052 #line 2052 "pikchr.c"
b62f651… stephan 2053 /******** End %stack_overflow code ********************************************/
b62f651… stephan 2054 pik_parserARG_STORE /* Suppress warning about unused %extra_argument var */
b62f651… stephan 2055 pik_parserCTX_STORE
b62f651… stephan 2056 }
b62f651… stephan 2057
b62f651… stephan 2058 /*
b62f651… stephan 2059 ** Print tracing information for a SHIFT action
b62f651… stephan 2060 */
b62f651… stephan 2061 #ifndef NDEBUG
b62f651… stephan 2062 static void yyTraceShift(yyParser *yypParser, int yyNewState, const char *zTag){
b62f651… stephan 2063 if( yyTraceFILE ){
b62f651… stephan 2064 if( yyNewState<YYNSTATE ){
b62f651… stephan 2065 fprintf(yyTraceFILE,"%s%s '%s', go to state %d\n",
b62f651… stephan 2066 yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
b62f651… stephan 2067 yyNewState);
b62f651… stephan 2068 }else{
b62f651… stephan 2069 fprintf(yyTraceFILE,"%s%s '%s', pending reduce %d\n",
b62f651… stephan 2070 yyTracePrompt, zTag, yyTokenName[yypParser->yytos->major],
b62f651… stephan 2071 yyNewState - YY_MIN_REDUCE);
b62f651… stephan 2072 }
b62f651… stephan 2073 }
b62f651… stephan 2074 }
b62f651… stephan 2075 #else
b62f651… stephan 2076 # define yyTraceShift(X,Y,Z)
b62f651… stephan 2077 #endif
b62f651… stephan 2078
b62f651… stephan 2079 /*
b62f651… stephan 2080 ** Perform a shift action.
b62f651… stephan 2081 */
b62f651… stephan 2082 static void yy_shift(
b62f651… stephan 2083 yyParser *yypParser, /* The parser to be shifted */
b62f651… stephan 2084 YYACTIONTYPE yyNewState, /* The new state to shift in */
b62f651… stephan 2085 YYCODETYPE yyMajor, /* The major token to shift in */
b62f651… stephan 2086 pik_parserTOKENTYPE yyMinor /* The minor token to shift in */
b62f651… stephan 2087 ){
b62f651… stephan 2088 yyStackEntry *yytos;
b62f651… stephan 2089 yypParser->yytos++;
b62f651… stephan 2090 #ifdef YYTRACKMAXSTACKDEPTH
b62f651… stephan 2091 if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
b62f651… stephan 2092 yypParser->yyhwm++;
b62f651… stephan 2093 assert( yypParser->yyhwm == (int)(yypParser->yytos - yypParser->yystack) );
b62f651… stephan 2094 }
b62f651… stephan 2095 #endif
f4ec8e0… drh 2096 yytos = yypParser->yytos;
f4ec8e0… drh 2097 if( yytos>yypParser->yystackEnd ){
b62f651… stephan 2098 if( yyGrowStack(yypParser) ){
b62f651… stephan 2099 yypParser->yytos--;
b62f651… stephan 2100 yyStackOverflow(yypParser);
b62f651… stephan 2101 return;
b62f651… stephan 2102 }
f4ec8e0… drh 2103 yytos = yypParser->yytos;
f4ec8e0… drh 2104 assert( yytos <= yypParser->yystackEnd );
b62f651… stephan 2105 }
b62f651… stephan 2106 if( yyNewState > YY_MAX_SHIFT ){
b62f651… stephan 2107 yyNewState += YY_MIN_REDUCE - YY_MIN_SHIFTREDUCE;
b62f651… stephan 2108 }
b62f651… stephan 2109 yytos->stateno = yyNewState;
b62f651… stephan 2110 yytos->major = yyMajor;
b62f651… stephan 2111 yytos->minor.yy0 = yyMinor;
b62f651… stephan 2112 yyTraceShift(yypParser, yyNewState, "Shift");
b62f651… stephan 2113 }
b62f651… stephan 2114
b62f651… stephan 2115 /* For rule J, yyRuleInfoLhs[J] contains the symbol on the left-hand side
b62f651… stephan 2116 ** of that rule */
b62f651… stephan 2117 static const YYCODETYPE yyRuleInfoLhs[] = {
dd20f34… drh 2118 124, /* (0) document ::= statement_list */
dd20f34… drh 2119 101, /* (1) statement_list ::= statement */
dd20f34… drh 2120 101, /* (2) statement_list ::= statement_list EOL statement */
dd20f34… drh 2121 102, /* (3) statement ::= */
dd20f34… drh 2122 102, /* (4) statement ::= direction */
dd20f34… drh 2123 102, /* (5) statement ::= lvalue ASSIGN rvalue */
dd20f34… drh 2124 102, /* (6) statement ::= PLACENAME COLON unnamed_statement */
dd20f34… drh 2125 102, /* (7) statement ::= PLACENAME COLON position */
dd20f34… drh 2126 102, /* (8) statement ::= unnamed_statement */
dd20f34… drh 2127 102, /* (9) statement ::= print prlist */
dd20f34… drh 2128 102, /* (10) statement ::= ASSERT LP expr EQ expr RP */
dd20f34… drh 2129 102, /* (11) statement ::= ASSERT LP position EQ position RP */
dd20f34… drh 2130 102, /* (12) statement ::= DEFINE ID CODEBLOCK */
dd20f34… drh 2131 119, /* (13) rvalue ::= PLACENAME */
dd20f34… drh 2132 127, /* (14) pritem ::= FILL */
dd20f34… drh 2133 127, /* (15) pritem ::= COLOR */
dd20f34… drh 2134 127, /* (16) pritem ::= THICKNESS */
dd20f34… drh 2135 127, /* (17) pritem ::= rvalue */
dd20f34… drh 2136 127, /* (18) pritem ::= STRING */
dd20f34… drh 2137 128, /* (19) prsep ::= COMMA */
dd20f34… drh 2138 103, /* (20) unnamed_statement ::= basetype attribute_list */
dd20f34… drh 2139 104, /* (21) basetype ::= CLASSNAME */
dd20f34… drh 2140 104, /* (22) basetype ::= STRING textposition */
dd20f34… drh 2141 104, /* (23) basetype ::= LB savelist statement_list RB */
dd20f34… drh 2142 130, /* (24) savelist ::= */
dd20f34… drh 2143 122, /* (25) relexpr ::= expr */
dd20f34… drh 2144 122, /* (26) relexpr ::= expr PERCENT */
dd20f34… drh 2145 123, /* (27) optrelexpr ::= */
dd20f34… drh 2146 129, /* (28) attribute_list ::= relexpr alist */
dd20f34… drh 2147 132, /* (29) attribute ::= numproperty relexpr */
dd20f34… drh 2148 132, /* (30) attribute ::= dashproperty expr */
dd20f34… drh 2149 132, /* (31) attribute ::= dashproperty */
dd20f34… drh 2150 132, /* (32) attribute ::= colorproperty rvalue */
dd20f34… drh 2151 132, /* (33) attribute ::= go direction optrelexpr */
dd20f34… drh 2152 132, /* (34) attribute ::= go direction even position */
dd20f34… drh 2153 132, /* (35) attribute ::= CLOSE */
dd20f34… drh 2154 132, /* (36) attribute ::= CHOP */
dd20f34… drh 2155 132, /* (37) attribute ::= FROM position */
dd20f34… drh 2156 132, /* (38) attribute ::= TO position */
dd20f34… drh 2157 132, /* (39) attribute ::= THEN */
dd20f34… drh 2158 132, /* (40) attribute ::= THEN optrelexpr HEADING expr */
dd20f34… drh 2159 132, /* (41) attribute ::= THEN optrelexpr EDGEPT */
dd20f34… drh 2160 132, /* (42) attribute ::= GO optrelexpr HEADING expr */
dd20f34… drh 2161 132, /* (43) attribute ::= GO optrelexpr EDGEPT */
dd20f34… drh 2162 132, /* (44) attribute ::= AT position */
dd20f34… drh 2163 132, /* (45) attribute ::= SAME */
dd20f34… drh 2164 132, /* (46) attribute ::= SAME AS object */
dd20f34… drh 2165 132, /* (47) attribute ::= STRING textposition */
dd20f34… drh 2166 132, /* (48) attribute ::= FIT */
dd20f34… drh 2167 132, /* (49) attribute ::= BEHIND object */
dd20f34… drh 2168 135, /* (50) withclause ::= DOT_E edge AT position */
dd20f34… drh 2169 135, /* (51) withclause ::= edge AT position */
dd20f34… drh 2170 106, /* (52) numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
dd20f34… drh 2171 134, /* (53) boolproperty ::= CW */
dd20f34… drh 2172 134, /* (54) boolproperty ::= CCW */
dd20f34… drh 2173 134, /* (55) boolproperty ::= LARROW */
dd20f34… drh 2174 134, /* (56) boolproperty ::= RARROW */
dd20f34… drh 2175 134, /* (57) boolproperty ::= LRARROW */
dd20f34… drh 2176 134, /* (58) boolproperty ::= INVIS */
dd20f34… drh 2177 134, /* (59) boolproperty ::= THICK */
dd20f34… drh 2178 134, /* (60) boolproperty ::= THIN */
dd20f34… drh 2179 134, /* (61) boolproperty ::= SOLID */
dd20f34… drh 2180 118, /* (62) textposition ::= */
dd20f34… drh 2181 118, /* (63) textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL */
dd20f34… drh 2182 113, /* (64) position ::= expr COMMA expr */
dd20f34… drh 2183 113, /* (65) position ::= place PLUS expr COMMA expr */
dd20f34… drh 2184 113, /* (66) position ::= place MINUS expr COMMA expr */
dd20f34… drh 2185 113, /* (67) position ::= place PLUS LP expr COMMA expr RP */
dd20f34… drh 2186 113, /* (68) position ::= place MINUS LP expr COMMA expr RP */
dd20f34… drh 2187 113, /* (69) position ::= LP position COMMA position RP */
dd20f34… drh 2188 113, /* (70) position ::= LP position RP */
dd20f34… drh 2189 113, /* (71) position ::= expr between position AND position */
dd20f34… drh 2190 113, /* (72) position ::= expr LT position COMMA position GT */
dd20f34… drh 2191 113, /* (73) position ::= expr ABOVE position */
dd20f34… drh 2192 113, /* (74) position ::= expr BELOW position */
dd20f34… drh 2193 113, /* (75) position ::= expr LEFT OF position */
dd20f34… drh 2194 113, /* (76) position ::= expr RIGHT OF position */
dd20f34… drh 2195 113, /* (77) position ::= expr ON HEADING EDGEPT OF position */
dd20f34… drh 2196 113, /* (78) position ::= expr HEADING EDGEPT OF position */
dd20f34… drh 2197 113, /* (79) position ::= expr EDGEPT OF position */
dd20f34… drh 2198 113, /* (80) position ::= expr ON HEADING expr FROM position */
dd20f34… drh 2199 113, /* (81) position ::= expr HEADING expr FROM position */
dd20f34… drh 2200 114, /* (82) place ::= edge OF object */
dd20f34… drh 2201 137, /* (83) place2 ::= object */
dd20f34… drh 2202 137, /* (84) place2 ::= object DOT_E edge */
dd20f34… drh 2203 137, /* (85) place2 ::= NTH VERTEX OF object */
dd20f34… drh 2204 115, /* (86) object ::= nth */
dd20f34… drh 2205 115, /* (87) object ::= nth OF|IN object */
dd20f34… drh 2206 116, /* (88) objectname ::= THIS */
dd20f34… drh 2207 116, /* (89) objectname ::= PLACENAME */
dd20f34… drh 2208 116, /* (90) objectname ::= objectname DOT_U PLACENAME */
dd20f34… drh 2209 117, /* (91) nth ::= NTH CLASSNAME */
dd20f34… drh 2210 117, /* (92) nth ::= NTH LAST CLASSNAME */
dd20f34… drh 2211 117, /* (93) nth ::= LAST CLASSNAME */
dd20f34… drh 2212 117, /* (94) nth ::= LAST */
dd20f34… drh 2213 117, /* (95) nth ::= NTH LB RB */
dd20f34… drh 2214 117, /* (96) nth ::= NTH LAST LB RB */
dd20f34… drh 2215 117, /* (97) nth ::= LAST LB RB */
dd20f34… drh 2216 105, /* (98) expr ::= expr PLUS expr */
dd20f34… drh 2217 105, /* (99) expr ::= expr MINUS expr */
dd20f34… drh 2218 105, /* (100) expr ::= expr STAR expr */
dd20f34… drh 2219 105, /* (101) expr ::= expr SLASH expr */
dd20f34… drh 2220 105, /* (102) expr ::= MINUS expr */
dd20f34… drh 2221 105, /* (103) expr ::= PLUS expr */
dd20f34… drh 2222 105, /* (104) expr ::= LP expr RP */
dd20f34… drh 2223 105, /* (105) expr ::= LP FILL|COLOR|THICKNESS RP */
dd20f34… drh 2224 105, /* (106) expr ::= NUMBER */
dd20f34… drh 2225 105, /* (107) expr ::= ID */
dd20f34… drh 2226 105, /* (108) expr ::= FUNC1 LP expr RP */
dd20f34… drh 2227 105, /* (109) expr ::= FUNC2 LP expr COMMA expr RP */
dd20f34… drh 2228 105, /* (110) expr ::= DIST LP position COMMA position RP */
dd20f34… drh 2229 105, /* (111) expr ::= place2 DOT_XY X */
dd20f34… drh 2230 105, /* (112) expr ::= place2 DOT_XY Y */
dd20f34… drh 2231 105, /* (113) expr ::= object DOT_L numproperty */
dd20f34… drh 2232 105, /* (114) expr ::= object DOT_L dashproperty */
dd20f34… drh 2233 105, /* (115) expr ::= object DOT_L colorproperty */
dd20f34… drh 2234 120, /* (116) lvalue ::= ID */
dd20f34… drh 2235 120, /* (117) lvalue ::= FILL */
dd20f34… drh 2236 120, /* (118) lvalue ::= COLOR */
dd20f34… drh 2237 120, /* (119) lvalue ::= THICKNESS */
dd20f34… drh 2238 119, /* (120) rvalue ::= expr */
dd20f34… drh 2239 125, /* (121) print ::= PRINT */
dd20f34… drh 2240 126, /* (122) prlist ::= pritem */
dd20f34… drh 2241 126, /* (123) prlist ::= prlist prsep pritem */
dd20f34… drh 2242 109, /* (124) direction ::= UP */
dd20f34… drh 2243 109, /* (125) direction ::= DOWN */
dd20f34… drh 2244 109, /* (126) direction ::= LEFT */
dd20f34… drh 2245 109, /* (127) direction ::= RIGHT */
dd20f34… drh 2246 123, /* (128) optrelexpr ::= relexpr */
dd20f34… drh 2247 129, /* (129) attribute_list ::= alist */
dd20f34… drh 2248 131, /* (130) alist ::= */
dd20f34… drh 2249 131, /* (131) alist ::= alist attribute */
dd20f34… drh 2250 132, /* (132) attribute ::= boolproperty */
dd20f34… drh 2251 132, /* (133) attribute ::= WITH withclause */
dd20f34… drh 2252 133, /* (134) go ::= GO */
dd20f34… drh 2253 133, /* (135) go ::= */
dd20f34… drh 2254 121, /* (136) even ::= UNTIL EVEN WITH */
dd20f34… drh 2255 121, /* (137) even ::= EVEN WITH */
dd20f34… drh 2256 110, /* (138) dashproperty ::= DOTTED */
dd20f34… drh 2257 110, /* (139) dashproperty ::= DASHED */
dd20f34… drh 2258 111, /* (140) colorproperty ::= FILL */
dd20f34… drh 2259 111, /* (141) colorproperty ::= COLOR */
dd20f34… drh 2260 113, /* (142) position ::= place */
dd20f34… drh 2261 136, /* (143) between ::= WAY BETWEEN */
dd20f34… drh 2262 136, /* (144) between ::= BETWEEN */
dd20f34… drh 2263 136, /* (145) between ::= OF THE WAY BETWEEN */
dd20f34… drh 2264 114, /* (146) place ::= place2 */
dd20f34… drh 2265 107, /* (147) edge ::= CENTER */
dd20f34… drh 2266 107, /* (148) edge ::= EDGEPT */
dd20f34… drh 2267 107, /* (149) edge ::= TOP */
dd20f34… drh 2268 107, /* (150) edge ::= BOTTOM */
dd20f34… drh 2269 107, /* (151) edge ::= START */
dd20f34… drh 2270 107, /* (152) edge ::= END */
dd20f34… drh 2271 107, /* (153) edge ::= RIGHT */
dd20f34… drh 2272 107, /* (154) edge ::= LEFT */
dd20f34… drh 2273 115, /* (155) object ::= objectname */
b62f651… stephan 2274 };
b62f651… stephan 2275
b62f651… stephan 2276 /* For rule J, yyRuleInfoNRhs[J] contains the negative of the number
b62f651… stephan 2277 ** of symbols on the right-hand side of that rule. */
b62f651… stephan 2278 static const signed char yyRuleInfoNRhs[] = {
b62f651… stephan 2279 -1, /* (0) document ::= statement_list */
b62f651… stephan 2280 -1, /* (1) statement_list ::= statement */
b62f651… stephan 2281 -3, /* (2) statement_list ::= statement_list EOL statement */
b62f651… stephan 2282 0, /* (3) statement ::= */
b62f651… stephan 2283 -1, /* (4) statement ::= direction */
b62f651… stephan 2284 -3, /* (5) statement ::= lvalue ASSIGN rvalue */
b62f651… stephan 2285 -3, /* (6) statement ::= PLACENAME COLON unnamed_statement */
b62f651… stephan 2286 -3, /* (7) statement ::= PLACENAME COLON position */
b62f651… stephan 2287 -1, /* (8) statement ::= unnamed_statement */
b62f651… stephan 2288 -2, /* (9) statement ::= print prlist */
b62f651… stephan 2289 -6, /* (10) statement ::= ASSERT LP expr EQ expr RP */
b62f651… stephan 2290 -6, /* (11) statement ::= ASSERT LP position EQ position RP */
b62f651… stephan 2291 -3, /* (12) statement ::= DEFINE ID CODEBLOCK */
b62f651… stephan 2292 -1, /* (13) rvalue ::= PLACENAME */
b62f651… stephan 2293 -1, /* (14) pritem ::= FILL */
b62f651… stephan 2294 -1, /* (15) pritem ::= COLOR */
b62f651… stephan 2295 -1, /* (16) pritem ::= THICKNESS */
b62f651… stephan 2296 -1, /* (17) pritem ::= rvalue */
b62f651… stephan 2297 -1, /* (18) pritem ::= STRING */
b62f651… stephan 2298 -1, /* (19) prsep ::= COMMA */
b62f651… stephan 2299 -2, /* (20) unnamed_statement ::= basetype attribute_list */
b62f651… stephan 2300 -1, /* (21) basetype ::= CLASSNAME */
b62f651… stephan 2301 -2, /* (22) basetype ::= STRING textposition */
b62f651… stephan 2302 -4, /* (23) basetype ::= LB savelist statement_list RB */
b62f651… stephan 2303 0, /* (24) savelist ::= */
b62f651… stephan 2304 -1, /* (25) relexpr ::= expr */
b62f651… stephan 2305 -2, /* (26) relexpr ::= expr PERCENT */
b62f651… stephan 2306 0, /* (27) optrelexpr ::= */
b62f651… stephan 2307 -2, /* (28) attribute_list ::= relexpr alist */
b62f651… stephan 2308 -2, /* (29) attribute ::= numproperty relexpr */
b62f651… stephan 2309 -2, /* (30) attribute ::= dashproperty expr */
b62f651… stephan 2310 -1, /* (31) attribute ::= dashproperty */
b62f651… stephan 2311 -2, /* (32) attribute ::= colorproperty rvalue */
b62f651… stephan 2312 -3, /* (33) attribute ::= go direction optrelexpr */
b62f651… stephan 2313 -4, /* (34) attribute ::= go direction even position */
b62f651… stephan 2314 -1, /* (35) attribute ::= CLOSE */
b62f651… stephan 2315 -1, /* (36) attribute ::= CHOP */
b62f651… stephan 2316 -2, /* (37) attribute ::= FROM position */
b62f651… stephan 2317 -2, /* (38) attribute ::= TO position */
b62f651… stephan 2318 -1, /* (39) attribute ::= THEN */
b62f651… stephan 2319 -4, /* (40) attribute ::= THEN optrelexpr HEADING expr */
b62f651… stephan 2320 -3, /* (41) attribute ::= THEN optrelexpr EDGEPT */
b62f651… stephan 2321 -4, /* (42) attribute ::= GO optrelexpr HEADING expr */
b62f651… stephan 2322 -3, /* (43) attribute ::= GO optrelexpr EDGEPT */
b62f651… stephan 2323 -2, /* (44) attribute ::= AT position */
b62f651… stephan 2324 -1, /* (45) attribute ::= SAME */
b62f651… stephan 2325 -3, /* (46) attribute ::= SAME AS object */
b62f651… stephan 2326 -2, /* (47) attribute ::= STRING textposition */
b62f651… stephan 2327 -1, /* (48) attribute ::= FIT */
b62f651… stephan 2328 -2, /* (49) attribute ::= BEHIND object */
b62f651… stephan 2329 -4, /* (50) withclause ::= DOT_E edge AT position */
b62f651… stephan 2330 -3, /* (51) withclause ::= edge AT position */
b62f651… stephan 2331 -1, /* (52) numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
b62f651… stephan 2332 -1, /* (53) boolproperty ::= CW */
b62f651… stephan 2333 -1, /* (54) boolproperty ::= CCW */
b62f651… stephan 2334 -1, /* (55) boolproperty ::= LARROW */
b62f651… stephan 2335 -1, /* (56) boolproperty ::= RARROW */
b62f651… stephan 2336 -1, /* (57) boolproperty ::= LRARROW */
b62f651… stephan 2337 -1, /* (58) boolproperty ::= INVIS */
b62f651… stephan 2338 -1, /* (59) boolproperty ::= THICK */
b62f651… stephan 2339 -1, /* (60) boolproperty ::= THIN */
b62f651… stephan 2340 -1, /* (61) boolproperty ::= SOLID */
b62f651… stephan 2341 0, /* (62) textposition ::= */
43eefe6… drh 2342 -2, /* (63) textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL */
b62f651… stephan 2343 -3, /* (64) position ::= expr COMMA expr */
b62f651… stephan 2344 -5, /* (65) position ::= place PLUS expr COMMA expr */
b62f651… stephan 2345 -5, /* (66) position ::= place MINUS expr COMMA expr */
b62f651… stephan 2346 -7, /* (67) position ::= place PLUS LP expr COMMA expr RP */
b62f651… stephan 2347 -7, /* (68) position ::= place MINUS LP expr COMMA expr RP */
b62f651… stephan 2348 -5, /* (69) position ::= LP position COMMA position RP */
b62f651… stephan 2349 -3, /* (70) position ::= LP position RP */
b62f651… stephan 2350 -5, /* (71) position ::= expr between position AND position */
b62f651… stephan 2351 -6, /* (72) position ::= expr LT position COMMA position GT */
b62f651… stephan 2352 -3, /* (73) position ::= expr ABOVE position */
b62f651… stephan 2353 -3, /* (74) position ::= expr BELOW position */
b62f651… stephan 2354 -4, /* (75) position ::= expr LEFT OF position */
b62f651… stephan 2355 -4, /* (76) position ::= expr RIGHT OF position */
b62f651… stephan 2356 -6, /* (77) position ::= expr ON HEADING EDGEPT OF position */
b62f651… stephan 2357 -5, /* (78) position ::= expr HEADING EDGEPT OF position */
b62f651… stephan 2358 -4, /* (79) position ::= expr EDGEPT OF position */
b62f651… stephan 2359 -6, /* (80) position ::= expr ON HEADING expr FROM position */
b62f651… stephan 2360 -5, /* (81) position ::= expr HEADING expr FROM position */
b62f651… stephan 2361 -3, /* (82) place ::= edge OF object */
b62f651… stephan 2362 -1, /* (83) place2 ::= object */
b62f651… stephan 2363 -3, /* (84) place2 ::= object DOT_E edge */
b62f651… stephan 2364 -4, /* (85) place2 ::= NTH VERTEX OF object */
b62f651… stephan 2365 -1, /* (86) object ::= nth */
b62f651… stephan 2366 -3, /* (87) object ::= nth OF|IN object */
b62f651… stephan 2367 -1, /* (88) objectname ::= THIS */
b62f651… stephan 2368 -1, /* (89) objectname ::= PLACENAME */
b62f651… stephan 2369 -3, /* (90) objectname ::= objectname DOT_U PLACENAME */
b62f651… stephan 2370 -2, /* (91) nth ::= NTH CLASSNAME */
b62f651… stephan 2371 -3, /* (92) nth ::= NTH LAST CLASSNAME */
b62f651… stephan 2372 -2, /* (93) nth ::= LAST CLASSNAME */
b62f651… stephan 2373 -1, /* (94) nth ::= LAST */
b62f651… stephan 2374 -3, /* (95) nth ::= NTH LB RB */
b62f651… stephan 2375 -4, /* (96) nth ::= NTH LAST LB RB */
b62f651… stephan 2376 -3, /* (97) nth ::= LAST LB RB */
b62f651… stephan 2377 -3, /* (98) expr ::= expr PLUS expr */
b62f651… stephan 2378 -3, /* (99) expr ::= expr MINUS expr */
b62f651… stephan 2379 -3, /* (100) expr ::= expr STAR expr */
b62f651… stephan 2380 -3, /* (101) expr ::= expr SLASH expr */
b62f651… stephan 2381 -2, /* (102) expr ::= MINUS expr */
b62f651… stephan 2382 -2, /* (103) expr ::= PLUS expr */
b62f651… stephan 2383 -3, /* (104) expr ::= LP expr RP */
b62f651… stephan 2384 -3, /* (105) expr ::= LP FILL|COLOR|THICKNESS RP */
b62f651… stephan 2385 -1, /* (106) expr ::= NUMBER */
b62f651… stephan 2386 -1, /* (107) expr ::= ID */
b62f651… stephan 2387 -4, /* (108) expr ::= FUNC1 LP expr RP */
b62f651… stephan 2388 -6, /* (109) expr ::= FUNC2 LP expr COMMA expr RP */
b62f651… stephan 2389 -6, /* (110) expr ::= DIST LP position COMMA position RP */
b62f651… stephan 2390 -3, /* (111) expr ::= place2 DOT_XY X */
b62f651… stephan 2391 -3, /* (112) expr ::= place2 DOT_XY Y */
b62f651… stephan 2392 -3, /* (113) expr ::= object DOT_L numproperty */
b62f651… stephan 2393 -3, /* (114) expr ::= object DOT_L dashproperty */
b62f651… stephan 2394 -3, /* (115) expr ::= object DOT_L colorproperty */
b62f651… stephan 2395 -1, /* (116) lvalue ::= ID */
b62f651… stephan 2396 -1, /* (117) lvalue ::= FILL */
b62f651… stephan 2397 -1, /* (118) lvalue ::= COLOR */
b62f651… stephan 2398 -1, /* (119) lvalue ::= THICKNESS */
b62f651… stephan 2399 -1, /* (120) rvalue ::= expr */
b62f651… stephan 2400 -1, /* (121) print ::= PRINT */
b62f651… stephan 2401 -1, /* (122) prlist ::= pritem */
b62f651… stephan 2402 -3, /* (123) prlist ::= prlist prsep pritem */
b62f651… stephan 2403 -1, /* (124) direction ::= UP */
b62f651… stephan 2404 -1, /* (125) direction ::= DOWN */
b62f651… stephan 2405 -1, /* (126) direction ::= LEFT */
b62f651… stephan 2406 -1, /* (127) direction ::= RIGHT */
b62f651… stephan 2407 -1, /* (128) optrelexpr ::= relexpr */
b62f651… stephan 2408 -1, /* (129) attribute_list ::= alist */
b62f651… stephan 2409 0, /* (130) alist ::= */
b62f651… stephan 2410 -2, /* (131) alist ::= alist attribute */
b62f651… stephan 2411 -1, /* (132) attribute ::= boolproperty */
b62f651… stephan 2412 -2, /* (133) attribute ::= WITH withclause */
b62f651… stephan 2413 -1, /* (134) go ::= GO */
b62f651… stephan 2414 0, /* (135) go ::= */
b62f651… stephan 2415 -3, /* (136) even ::= UNTIL EVEN WITH */
b62f651… stephan 2416 -2, /* (137) even ::= EVEN WITH */
b62f651… stephan 2417 -1, /* (138) dashproperty ::= DOTTED */
b62f651… stephan 2418 -1, /* (139) dashproperty ::= DASHED */
b62f651… stephan 2419 -1, /* (140) colorproperty ::= FILL */
b62f651… stephan 2420 -1, /* (141) colorproperty ::= COLOR */
b62f651… stephan 2421 -1, /* (142) position ::= place */
b62f651… stephan 2422 -2, /* (143) between ::= WAY BETWEEN */
b62f651… stephan 2423 -1, /* (144) between ::= BETWEEN */
b62f651… stephan 2424 -4, /* (145) between ::= OF THE WAY BETWEEN */
b62f651… stephan 2425 -1, /* (146) place ::= place2 */
b62f651… stephan 2426 -1, /* (147) edge ::= CENTER */
b62f651… stephan 2427 -1, /* (148) edge ::= EDGEPT */
b62f651… stephan 2428 -1, /* (149) edge ::= TOP */
b62f651… stephan 2429 -1, /* (150) edge ::= BOTTOM */
b62f651… stephan 2430 -1, /* (151) edge ::= START */
b62f651… stephan 2431 -1, /* (152) edge ::= END */
b62f651… stephan 2432 -1, /* (153) edge ::= RIGHT */
b62f651… stephan 2433 -1, /* (154) edge ::= LEFT */
b62f651… stephan 2434 -1, /* (155) object ::= objectname */
b62f651… stephan 2435 };
b62f651… stephan 2436
b62f651… stephan 2437 static void yy_accept(yyParser*); /* Forward Declaration */
b62f651… stephan 2438
b62f651… stephan 2439 /*
b62f651… stephan 2440 ** Perform a reduce action and the shift that must immediately
b62f651… stephan 2441 ** follow the reduce.
b62f651… stephan 2442 **
b62f651… stephan 2443 ** The yyLookahead and yyLookaheadToken parameters provide reduce actions
b62f651… stephan 2444 ** access to the lookahead token (if any). The yyLookahead will be YYNOCODE
b62f651… stephan 2445 ** if the lookahead token has already been consumed. As this procedure is
b62f651… stephan 2446 ** only called from one place, optimizing compilers will in-line it, which
b62f651… stephan 2447 ** means that the extra parameters have no performance impact.
b62f651… stephan 2448 */
b62f651… stephan 2449 static YYACTIONTYPE yy_reduce(
b62f651… stephan 2450 yyParser *yypParser, /* The parser */
b62f651… stephan 2451 unsigned int yyruleno, /* Number of the rule by which to reduce */
b62f651… stephan 2452 int yyLookahead, /* Lookahead token, or YYNOCODE if none */
b62f651… stephan 2453 pik_parserTOKENTYPE yyLookaheadToken /* Value of the lookahead token */
b62f651… stephan 2454 pik_parserCTX_PDECL /* %extra_context */
b62f651… stephan 2455 ){
b62f651… stephan 2456 int yygoto; /* The next state */
b62f651… stephan 2457 YYACTIONTYPE yyact; /* The next action */
b62f651… stephan 2458 yyStackEntry *yymsp; /* The top of the parser's stack */
b62f651… stephan 2459 int yysize; /* Amount to pop the stack */
b62f651… stephan 2460 pik_parserARG_FETCH
b62f651… stephan 2461 (void)yyLookahead;
b62f651… stephan 2462 (void)yyLookaheadToken;
b62f651… stephan 2463 yymsp = yypParser->yytos;
b62f651… stephan 2464
b62f651… stephan 2465 switch( yyruleno ){
b62f651… stephan 2466 /* Beginning here are the reduction cases. A typical example
b62f651… stephan 2467 ** follows:
b62f651… stephan 2468 ** case 0:
b62f651… stephan 2469 ** #line <lineno> <grammarfile>
b62f651… stephan 2470 ** { ... } // User supplied code
b62f651… stephan 2471 ** #line <lineno> <thisfile>
b62f651… stephan 2472 ** break;
b62f651… stephan 2473 */
b62f651… stephan 2474 /********** Begin reduce actions **********************************************/
b62f651… stephan 2475 YYMINORTYPE yylhsminor;
b62f651… stephan 2476 case 0: /* document ::= statement_list */
dd20f34… drh 2477 #line 563 "pikchr.y"
dd20f34… drh 2478 {pik_render(p,yymsp[0].minor.yy23);}
dd20f34… drh 2479 #line 2479 "pikchr.c"
b62f651… stephan 2480 break;
b62f651… stephan 2481 case 1: /* statement_list ::= statement */
dd20f34… drh 2482 #line 566 "pikchr.y"
dd20f34… drh 2483 { yylhsminor.yy23 = pik_elist_append(p,0,yymsp[0].minor.yy54); }
dd20f34… drh 2484 #line 2484 "pikchr.c"
dd20f34… drh 2485 yymsp[0].minor.yy23 = yylhsminor.yy23;
b62f651… stephan 2486 break;
b62f651… stephan 2487 case 2: /* statement_list ::= statement_list EOL statement */
dd20f34… drh 2488 #line 568 "pikchr.y"
dd20f34… drh 2489 { yylhsminor.yy23 = pik_elist_append(p,yymsp[-2].minor.yy23,yymsp[0].minor.yy54); }
dd20f34… drh 2490 #line 2490 "pikchr.c"
dd20f34… drh 2491 yymsp[-2].minor.yy23 = yylhsminor.yy23;
b62f651… stephan 2492 break;
b62f651… stephan 2493 case 3: /* statement ::= */
dd20f34… drh 2494 #line 571 "pikchr.y"
dd20f34… drh 2495 { yymsp[1].minor.yy54 = 0; }
dd20f34… drh 2496 #line 2496 "pikchr.c"
b62f651… stephan 2497 break;
b62f651… stephan 2498 case 4: /* statement ::= direction */
dd20f34… drh 2499 #line 572 "pikchr.y"
dd20f34… drh 2500 { pik_set_direction(p,yymsp[0].minor.yy0.eCode); yylhsminor.yy54=0; }
dd20f34… drh 2501 #line 2501 "pikchr.c"
dd20f34… drh 2502 yymsp[0].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2503 break;
b62f651… stephan 2504 case 5: /* statement ::= lvalue ASSIGN rvalue */
dd20f34… drh 2505 #line 573 "pikchr.y"
dd20f34… drh 2506 {pik_set_var(p,&yymsp[-2].minor.yy0,yymsp[0].minor.yy129,&yymsp[-1].minor.yy0); yylhsminor.yy54=0;}
dd20f34… drh 2507 #line 2507 "pikchr.c"
dd20f34… drh 2508 yymsp[-2].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2509 break;
b62f651… stephan 2510 case 6: /* statement ::= PLACENAME COLON unnamed_statement */
dd20f34… drh 2511 #line 575 "pikchr.y"
dd20f34… drh 2512 { yylhsminor.yy54 = yymsp[0].minor.yy54; pik_elem_setname(p,yymsp[0].minor.yy54,&yymsp[-2].minor.yy0); }
dd20f34… drh 2513 #line 2513 "pikchr.c"
dd20f34… drh 2514 yymsp[-2].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2515 break;
b62f651… stephan 2516 case 7: /* statement ::= PLACENAME COLON position */
dd20f34… drh 2517 #line 577 "pikchr.y"
dd20f34… drh 2518 { yylhsminor.yy54 = pik_elem_new(p,0,0,0);
dd20f34… drh 2519 if(yylhsminor.yy54){ yylhsminor.yy54->ptAt = yymsp[0].minor.yy187; pik_elem_setname(p,yylhsminor.yy54,&yymsp[-2].minor.yy0); }}
dd20f34… drh 2520 #line 2520 "pikchr.c"
dd20f34… drh 2521 yymsp[-2].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2522 break;
b62f651… stephan 2523 case 8: /* statement ::= unnamed_statement */
dd20f34… drh 2524 #line 579 "pikchr.y"
dd20f34… drh 2525 {yylhsminor.yy54 = yymsp[0].minor.yy54;}
dd20f34… drh 2526 #line 2526 "pikchr.c"
dd20f34… drh 2527 yymsp[0].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2528 break;
b62f651… stephan 2529 case 9: /* statement ::= print prlist */
dd20f34… drh 2530 #line 580 "pikchr.y"
dd20f34… drh 2531 {pik_append(p,"<br>\n",5); yymsp[-1].minor.yy54=0;}
dd20f34… drh 2532 #line 2532 "pikchr.c"
b62f651… stephan 2533 break;
b62f651… stephan 2534 case 10: /* statement ::= ASSERT LP expr EQ expr RP */
dd20f34… drh 2535 #line 585 "pikchr.y"
dd20f34… drh 2536 {yymsp[-5].minor.yy54=pik_assert(p,yymsp[-3].minor.yy129,&yymsp[-2].minor.yy0,yymsp[-1].minor.yy129);}
dd20f34… drh 2537 #line 2537 "pikchr.c"
b62f651… stephan 2538 break;
b62f651… stephan 2539 case 11: /* statement ::= ASSERT LP position EQ position RP */
dd20f34… drh 2540 #line 587 "pikchr.y"
dd20f34… drh 2541 {yymsp[-5].minor.yy54=pik_position_assert(p,&yymsp[-3].minor.yy187,&yymsp[-2].minor.yy0,&yymsp[-1].minor.yy187);}
dd20f34… drh 2542 #line 2542 "pikchr.c"
b62f651… stephan 2543 break;
b62f651… stephan 2544 case 12: /* statement ::= DEFINE ID CODEBLOCK */
dd20f34… drh 2545 #line 588 "pikchr.y"
dd20f34… drh 2546 {yymsp[-2].minor.yy54=0; pik_add_macro(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy0);}
dd20f34… drh 2547 #line 2547 "pikchr.c"
b62f651… stephan 2548 break;
b62f651… stephan 2549 case 13: /* rvalue ::= PLACENAME */
dd20f34… drh 2550 #line 599 "pikchr.y"
dd20f34… drh 2551 {yylhsminor.yy129 = pik_lookup_color(p,&yymsp[0].minor.yy0);}
dd20f34… drh 2552 #line 2552 "pikchr.c"
dd20f34… drh 2553 yymsp[0].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 2554 break;
b62f651… stephan 2555 case 14: /* pritem ::= FILL */
b62f651… stephan 2556 case 15: /* pritem ::= COLOR */ yytestcase(yyruleno==15);
b62f651… stephan 2557 case 16: /* pritem ::= THICKNESS */ yytestcase(yyruleno==16);
dd20f34… drh 2558 #line 604 "pikchr.y"
b62f651… stephan 2559 {pik_append_num(p,"",pik_value(p,yymsp[0].minor.yy0.z,yymsp[0].minor.yy0.n,0));}
dd20f34… drh 2560 #line 2560 "pikchr.c"
b62f651… stephan 2561 break;
b62f651… stephan 2562 case 17: /* pritem ::= rvalue */
dd20f34… drh 2563 #line 607 "pikchr.y"
dd20f34… drh 2564 {pik_append_num(p,"",yymsp[0].minor.yy129);}
dd20f34… drh 2565 #line 2565 "pikchr.c"
b62f651… stephan 2566 break;
b62f651… stephan 2567 case 18: /* pritem ::= STRING */
dd20f34… drh 2568 #line 608 "pikchr.y"
b62f651… stephan 2569 {pik_append_text(p,yymsp[0].minor.yy0.z+1,yymsp[0].minor.yy0.n-2,0);}
dd20f34… drh 2570 #line 2570 "pikchr.c"
b62f651… stephan 2571 break;
b62f651… stephan 2572 case 19: /* prsep ::= COMMA */
dd20f34… drh 2573 #line 609 "pikchr.y"
b62f651… stephan 2574 {pik_append(p, " ", 1);}
dd20f34… drh 2575 #line 2575 "pikchr.c"
b62f651… stephan 2576 break;
b62f651… stephan 2577 case 20: /* unnamed_statement ::= basetype attribute_list */
dd20f34… drh 2578 #line 614 "pikchr.y"
dd20f34… drh 2579 {yylhsminor.yy54 = yymsp[-1].minor.yy54; pik_after_adding_attributes(p,yylhsminor.yy54);}
dd20f34… drh 2580 #line 2580 "pikchr.c"
dd20f34… drh 2581 yymsp[-1].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2582 break;
b62f651… stephan 2583 case 21: /* basetype ::= CLASSNAME */
dd20f34… drh 2584 #line 616 "pikchr.y"
dd20f34… drh 2585 {yylhsminor.yy54 = pik_elem_new(p,&yymsp[0].minor.yy0,0,0); }
dd20f34… drh 2586 #line 2586 "pikchr.c"
dd20f34… drh 2587 yymsp[0].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2588 break;
b62f651… stephan 2589 case 22: /* basetype ::= STRING textposition */
dd20f34… drh 2590 #line 618 "pikchr.y"
dd20f34… drh 2591 {yymsp[-1].minor.yy0.eCode = yymsp[0].minor.yy272; yylhsminor.yy54 = pik_elem_new(p,0,&yymsp[-1].minor.yy0,0); }
dd20f34… drh 2592 #line 2592 "pikchr.c"
dd20f34… drh 2593 yymsp[-1].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2594 break;
b62f651… stephan 2595 case 23: /* basetype ::= LB savelist statement_list RB */
dd20f34… drh 2596 #line 620 "pikchr.y"
dd20f34… drh 2597 { p->list = yymsp[-2].minor.yy23; yymsp[-3].minor.yy54 = pik_elem_new(p,0,0,yymsp[-1].minor.yy23); if(yymsp[-3].minor.yy54) yymsp[-3].minor.yy54->errTok = yymsp[0].minor.yy0; }
dd20f34… drh 2598 #line 2598 "pikchr.c"
b62f651… stephan 2599 break;
b62f651… stephan 2600 case 24: /* savelist ::= */
dd20f34… drh 2601 #line 625 "pikchr.y"
dd20f34… drh 2602 {yymsp[1].minor.yy23 = p->list; p->list = 0;}
dd20f34… drh 2603 #line 2603 "pikchr.c"
b62f651… stephan 2604 break;
b62f651… stephan 2605 case 25: /* relexpr ::= expr */
dd20f34… drh 2606 #line 632 "pikchr.y"
dd20f34… drh 2607 {yylhsminor.yy28.rAbs = yymsp[0].minor.yy129; yylhsminor.yy28.rRel = 0;}
dd20f34… drh 2608 #line 2608 "pikchr.c"
dd20f34… drh 2609 yymsp[0].minor.yy28 = yylhsminor.yy28;
b62f651… stephan 2610 break;
b62f651… stephan 2611 case 26: /* relexpr ::= expr PERCENT */
dd20f34… drh 2612 #line 633 "pikchr.y"
dd20f34… drh 2613 {yylhsminor.yy28.rAbs = 0; yylhsminor.yy28.rRel = yymsp[-1].minor.yy129/100;}
dd20f34… drh 2614 #line 2614 "pikchr.c"
dd20f34… drh 2615 yymsp[-1].minor.yy28 = yylhsminor.yy28;
b62f651… stephan 2616 break;
b62f651… stephan 2617 case 27: /* optrelexpr ::= */
dd20f34… drh 2618 #line 635 "pikchr.y"
dd20f34… drh 2619 {yymsp[1].minor.yy28.rAbs = 0; yymsp[1].minor.yy28.rRel = 1.0;}
dd20f34… drh 2620 #line 2620 "pikchr.c"
b62f651… stephan 2621 break;
b62f651… stephan 2622 case 28: /* attribute_list ::= relexpr alist */
dd20f34… drh 2623 #line 637 "pikchr.y"
dd20f34… drh 2624 {pik_add_direction(p,0,&yymsp[-1].minor.yy28);}
dd20f34… drh 2625 #line 2625 "pikchr.c"
b62f651… stephan 2626 break;
b62f651… stephan 2627 case 29: /* attribute ::= numproperty relexpr */
dd20f34… drh 2628 #line 641 "pikchr.y"
dd20f34… drh 2629 { pik_set_numprop(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy28); }
dd20f34… drh 2630 #line 2630 "pikchr.c"
b62f651… stephan 2631 break;
b62f651… stephan 2632 case 30: /* attribute ::= dashproperty expr */
dd20f34… drh 2633 #line 642 "pikchr.y"
dd20f34… drh 2634 { pik_set_dashed(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy129); }
dd20f34… drh 2635 #line 2635 "pikchr.c"
b62f651… stephan 2636 break;
b62f651… stephan 2637 case 31: /* attribute ::= dashproperty */
dd20f34… drh 2638 #line 643 "pikchr.y"
b62f651… stephan 2639 { pik_set_dashed(p,&yymsp[0].minor.yy0,0); }
dd20f34… drh 2640 #line 2640 "pikchr.c"
b62f651… stephan 2641 break;
b62f651… stephan 2642 case 32: /* attribute ::= colorproperty rvalue */
dd20f34… drh 2643 #line 644 "pikchr.y"
dd20f34… drh 2644 { pik_set_clrprop(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy129); }
dd20f34… drh 2645 #line 2645 "pikchr.c"
b62f651… stephan 2646 break;
b62f651… stephan 2647 case 33: /* attribute ::= go direction optrelexpr */
dd20f34… drh 2648 #line 645 "pikchr.y"
dd20f34… drh 2649 { pik_add_direction(p,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy28);}
dd20f34… drh 2650 #line 2650 "pikchr.c"
b62f651… stephan 2651 break;
b62f651… stephan 2652 case 34: /* attribute ::= go direction even position */
dd20f34… drh 2653 #line 646 "pikchr.y"
dd20f34… drh 2654 {pik_evenwith(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy187);}
dd20f34… drh 2655 #line 2655 "pikchr.c"
b62f651… stephan 2656 break;
b62f651… stephan 2657 case 35: /* attribute ::= CLOSE */
dd20f34… drh 2658 #line 647 "pikchr.y"
b62f651… stephan 2659 { pik_close_path(p,&yymsp[0].minor.yy0); }
dd20f34… drh 2660 #line 2660 "pikchr.c"
b62f651… stephan 2661 break;
b62f651… stephan 2662 case 36: /* attribute ::= CHOP */
dd20f34… drh 2663 #line 648 "pikchr.y"
b62f651… stephan 2664 { p->cur->bChop = 1; }
dd20f34… drh 2665 #line 2665 "pikchr.c"
b62f651… stephan 2666 break;
b62f651… stephan 2667 case 37: /* attribute ::= FROM position */
dd20f34… drh 2668 #line 649 "pikchr.y"
dd20f34… drh 2669 { pik_set_from(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy187); }
dd20f34… drh 2670 #line 2670 "pikchr.c"
b62f651… stephan 2671 break;
b62f651… stephan 2672 case 38: /* attribute ::= TO position */
dd20f34… drh 2673 #line 650 "pikchr.y"
dd20f34… drh 2674 { pik_add_to(p,p->cur,&yymsp[-1].minor.yy0,&yymsp[0].minor.yy187); }
dd20f34… drh 2675 #line 2675 "pikchr.c"
b62f651… stephan 2676 break;
b62f651… stephan 2677 case 39: /* attribute ::= THEN */
dd20f34… drh 2678 #line 651 "pikchr.y"
b62f651… stephan 2679 { pik_then(p, &yymsp[0].minor.yy0, p->cur); }
dd20f34… drh 2680 #line 2680 "pikchr.c"
b62f651… stephan 2681 break;
b62f651… stephan 2682 case 40: /* attribute ::= THEN optrelexpr HEADING expr */
b62f651… stephan 2683 case 42: /* attribute ::= GO optrelexpr HEADING expr */ yytestcase(yyruleno==42);
dd20f34… drh 2684 #line 653 "pikchr.y"
dd20f34… drh 2685 {pik_move_hdg(p,&yymsp[-2].minor.yy28,&yymsp[-1].minor.yy0,yymsp[0].minor.yy129,0,&yymsp[-3].minor.yy0);}
dd20f34… drh 2686 #line 2686 "pikchr.c"
b62f651… stephan 2687 break;
b62f651… stephan 2688 case 41: /* attribute ::= THEN optrelexpr EDGEPT */
b62f651… stephan 2689 case 43: /* attribute ::= GO optrelexpr EDGEPT */ yytestcase(yyruleno==43);
dd20f34… drh 2690 #line 654 "pikchr.y"
dd20f34… drh 2691 {pik_move_hdg(p,&yymsp[-1].minor.yy28,0,0,&yymsp[0].minor.yy0,&yymsp[-2].minor.yy0);}
dd20f34… drh 2692 #line 2692 "pikchr.c"
b62f651… stephan 2693 break;
b62f651… stephan 2694 case 44: /* attribute ::= AT position */
dd20f34… drh 2695 #line 659 "pikchr.y"
dd20f34… drh 2696 { pik_set_at(p,0,&yymsp[0].minor.yy187,&yymsp[-1].minor.yy0); }
dd20f34… drh 2697 #line 2697 "pikchr.c"
b62f651… stephan 2698 break;
b62f651… stephan 2699 case 45: /* attribute ::= SAME */
dd20f34… drh 2700 #line 661 "pikchr.y"
b62f651… stephan 2701 {pik_same(p,0,&yymsp[0].minor.yy0);}
dd20f34… drh 2702 #line 2702 "pikchr.c"
b62f651… stephan 2703 break;
b62f651… stephan 2704 case 46: /* attribute ::= SAME AS object */
dd20f34… drh 2705 #line 662 "pikchr.y"
dd20f34… drh 2706 {pik_same(p,yymsp[0].minor.yy54,&yymsp[-2].minor.yy0);}
dd20f34… drh 2707 #line 2707 "pikchr.c"
b62f651… stephan 2708 break;
b62f651… stephan 2709 case 47: /* attribute ::= STRING textposition */
dd20f34… drh 2710 #line 663 "pikchr.y"
dd20f34… drh 2711 {pik_add_txt(p,&yymsp[-1].minor.yy0,yymsp[0].minor.yy272);}
dd20f34… drh 2712 #line 2712 "pikchr.c"
b62f651… stephan 2713 break;
b62f651… stephan 2714 case 48: /* attribute ::= FIT */
dd20f34… drh 2715 #line 664 "pikchr.y"
c32f97e… drh 2716 {pik_size_to_fit(p,0,&yymsp[0].minor.yy0,3); }
dd20f34… drh 2717 #line 2717 "pikchr.c"
b62f651… stephan 2718 break;
b62f651… stephan 2719 case 49: /* attribute ::= BEHIND object */
dd20f34… drh 2720 #line 665 "pikchr.y"
dd20f34… drh 2721 {pik_behind(p,yymsp[0].minor.yy54);}
dd20f34… drh 2722 #line 2722 "pikchr.c"
b62f651… stephan 2723 break;
b62f651… stephan 2724 case 50: /* withclause ::= DOT_E edge AT position */
b62f651… stephan 2725 case 51: /* withclause ::= edge AT position */ yytestcase(yyruleno==51);
dd20f34… drh 2726 #line 673 "pikchr.y"
dd20f34… drh 2727 { pik_set_at(p,&yymsp[-2].minor.yy0,&yymsp[0].minor.yy187,&yymsp[-1].minor.yy0); }
dd20f34… drh 2728 #line 2728 "pikchr.c"
b62f651… stephan 2729 break;
b62f651… stephan 2730 case 52: /* numproperty ::= HEIGHT|WIDTH|RADIUS|DIAMETER|THICKNESS */
dd20f34… drh 2731 #line 677 "pikchr.y"
b62f651… stephan 2732 {yylhsminor.yy0 = yymsp[0].minor.yy0;}
dd20f34… drh 2733 #line 2733 "pikchr.c"
b62f651… stephan 2734 yymsp[0].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2735 break;
b62f651… stephan 2736 case 53: /* boolproperty ::= CW */
dd20f34… drh 2737 #line 688 "pikchr.y"
b62f651… stephan 2738 {p->cur->cw = 1;}
dd20f34… drh 2739 #line 2739 "pikchr.c"
b62f651… stephan 2740 break;
b62f651… stephan 2741 case 54: /* boolproperty ::= CCW */
dd20f34… drh 2742 #line 689 "pikchr.y"
b62f651… stephan 2743 {p->cur->cw = 0;}
dd20f34… drh 2744 #line 2744 "pikchr.c"
b62f651… stephan 2745 break;
b62f651… stephan 2746 case 55: /* boolproperty ::= LARROW */
dd20f34… drh 2747 #line 690 "pikchr.y"
b62f651… stephan 2748 {p->cur->larrow=1; p->cur->rarrow=0; }
dd20f34… drh 2749 #line 2749 "pikchr.c"
b62f651… stephan 2750 break;
b62f651… stephan 2751 case 56: /* boolproperty ::= RARROW */
dd20f34… drh 2752 #line 691 "pikchr.y"
b62f651… stephan 2753 {p->cur->larrow=0; p->cur->rarrow=1; }
dd20f34… drh 2754 #line 2754 "pikchr.c"
b62f651… stephan 2755 break;
b62f651… stephan 2756 case 57: /* boolproperty ::= LRARROW */
dd20f34… drh 2757 #line 692 "pikchr.y"
b62f651… stephan 2758 {p->cur->larrow=1; p->cur->rarrow=1; }
dd20f34… drh 2759 #line 2759 "pikchr.c"
b62f651… stephan 2760 break;
b62f651… stephan 2761 case 58: /* boolproperty ::= INVIS */
dd20f34… drh 2762 #line 693 "pikchr.y"
8ed25a3… drh 2763 {p->cur->sw = -0.00001;}
dd20f34… drh 2764 #line 2764 "pikchr.c"
b62f651… stephan 2765 break;
b62f651… stephan 2766 case 59: /* boolproperty ::= THICK */
dd20f34… drh 2767 #line 694 "pikchr.y"
b62f651… stephan 2768 {p->cur->sw *= 1.5;}
dd20f34… drh 2769 #line 2769 "pikchr.c"
b62f651… stephan 2770 break;
b62f651… stephan 2771 case 60: /* boolproperty ::= THIN */
dd20f34… drh 2772 #line 695 "pikchr.y"
b62f651… stephan 2773 {p->cur->sw *= 0.67;}
dd20f34… drh 2774 #line 2774 "pikchr.c"
b62f651… stephan 2775 break;
b62f651… stephan 2776 case 61: /* boolproperty ::= SOLID */
dd20f34… drh 2777 #line 696 "pikchr.y"
b62f651… stephan 2778 {p->cur->sw = pik_value(p,"thickness",9,0);
b62f651… stephan 2779 p->cur->dotted = p->cur->dashed = 0.0;}
dd20f34… drh 2780 #line 2780 "pikchr.c"
b62f651… stephan 2781 break;
b62f651… stephan 2782 case 62: /* textposition ::= */
dd20f34… drh 2783 #line 699 "pikchr.y"
dd20f34… drh 2784 {yymsp[1].minor.yy272 = 0;}
dd20f34… drh 2785 #line 2785 "pikchr.c"
b62f651… stephan 2786 break;
43eefe6… drh 2787 case 63: /* textposition ::= textposition CENTER|LJUST|RJUST|ABOVE|BELOW|ITALIC|BOLD|MONO|ALIGNED|BIG|SMALL */
dd20f34… drh 2788 #line 702 "pikchr.y"
dd20f34… drh 2789 {yylhsminor.yy272 = (short int)pik_text_position(yymsp[-1].minor.yy272,&yymsp[0].minor.yy0);}
dd20f34… drh 2790 #line 2790 "pikchr.c"
dd20f34… drh 2791 yymsp[-1].minor.yy272 = yylhsminor.yy272;
b62f651… stephan 2792 break;
b62f651… stephan 2793 case 64: /* position ::= expr COMMA expr */
dd20f34… drh 2794 #line 705 "pikchr.y"
dd20f34… drh 2795 {yylhsminor.yy187.x=yymsp[-2].minor.yy129; yylhsminor.yy187.y=yymsp[0].minor.yy129;}
dd20f34… drh 2796 #line 2796 "pikchr.c"
dd20f34… drh 2797 yymsp[-2].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2798 break;
b62f651… stephan 2799 case 65: /* position ::= place PLUS expr COMMA expr */
dd20f34… drh 2800 #line 707 "pikchr.y"
dd20f34… drh 2801 {yylhsminor.yy187.x=yymsp[-4].minor.yy187.x+yymsp[-2].minor.yy129; yylhsminor.yy187.y=yymsp[-4].minor.yy187.y+yymsp[0].minor.yy129;}
dd20f34… drh 2802 #line 2802 "pikchr.c"
dd20f34… drh 2803 yymsp[-4].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2804 break;
b62f651… stephan 2805 case 66: /* position ::= place MINUS expr COMMA expr */
dd20f34… drh 2806 #line 708 "pikchr.y"
dd20f34… drh 2807 {yylhsminor.yy187.x=yymsp[-4].minor.yy187.x-yymsp[-2].minor.yy129; yylhsminor.yy187.y=yymsp[-4].minor.yy187.y-yymsp[0].minor.yy129;}
dd20f34… drh 2808 #line 2808 "pikchr.c"
dd20f34… drh 2809 yymsp[-4].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2810 break;
b62f651… stephan 2811 case 67: /* position ::= place PLUS LP expr COMMA expr RP */
dd20f34… drh 2812 #line 710 "pikchr.y"
dd20f34… drh 2813 {yylhsminor.yy187.x=yymsp[-6].minor.yy187.x+yymsp[-3].minor.yy129; yylhsminor.yy187.y=yymsp[-6].minor.yy187.y+yymsp[-1].minor.yy129;}
dd20f34… drh 2814 #line 2814 "pikchr.c"
dd20f34… drh 2815 yymsp[-6].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2816 break;
b62f651… stephan 2817 case 68: /* position ::= place MINUS LP expr COMMA expr RP */
dd20f34… drh 2818 #line 712 "pikchr.y"
dd20f34… drh 2819 {yylhsminor.yy187.x=yymsp[-6].minor.yy187.x-yymsp[-3].minor.yy129; yylhsminor.yy187.y=yymsp[-6].minor.yy187.y-yymsp[-1].minor.yy129;}
dd20f34… drh 2820 #line 2820 "pikchr.c"
dd20f34… drh 2821 yymsp[-6].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2822 break;
b62f651… stephan 2823 case 69: /* position ::= LP position COMMA position RP */
dd20f34… drh 2824 #line 713 "pikchr.y"
dd20f34… drh 2825 {yymsp[-4].minor.yy187.x=yymsp[-3].minor.yy187.x; yymsp[-4].minor.yy187.y=yymsp[-1].minor.yy187.y;}
dd20f34… drh 2826 #line 2826 "pikchr.c"
b62f651… stephan 2827 break;
b62f651… stephan 2828 case 70: /* position ::= LP position RP */
dd20f34… drh 2829 #line 714 "pikchr.y"
dd20f34… drh 2830 {yymsp[-2].minor.yy187=yymsp[-1].minor.yy187;}
dd20f34… drh 2831 #line 2831 "pikchr.c"
b62f651… stephan 2832 break;
b62f651… stephan 2833 case 71: /* position ::= expr between position AND position */
dd20f34… drh 2834 #line 716 "pikchr.y"
dd20f34… drh 2835 {yylhsminor.yy187 = pik_position_between(yymsp[-4].minor.yy129,yymsp[-2].minor.yy187,yymsp[0].minor.yy187);}
dd20f34… drh 2836 #line 2836 "pikchr.c"
dd20f34… drh 2837 yymsp[-4].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2838 break;
b62f651… stephan 2839 case 72: /* position ::= expr LT position COMMA position GT */
dd20f34… drh 2840 #line 718 "pikchr.y"
dd20f34… drh 2841 {yylhsminor.yy187 = pik_position_between(yymsp[-5].minor.yy129,yymsp[-3].minor.yy187,yymsp[-1].minor.yy187);}
dd20f34… drh 2842 #line 2842 "pikchr.c"
dd20f34… drh 2843 yymsp[-5].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2844 break;
b62f651… stephan 2845 case 73: /* position ::= expr ABOVE position */
dd20f34… drh 2846 #line 719 "pikchr.y"
dd20f34… drh 2847 {yylhsminor.yy187=yymsp[0].minor.yy187; yylhsminor.yy187.y += yymsp[-2].minor.yy129;}
dd20f34… drh 2848 #line 2848 "pikchr.c"
dd20f34… drh 2849 yymsp[-2].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2850 break;
b62f651… stephan 2851 case 74: /* position ::= expr BELOW position */
dd20f34… drh 2852 #line 720 "pikchr.y"
dd20f34… drh 2853 {yylhsminor.yy187=yymsp[0].minor.yy187; yylhsminor.yy187.y -= yymsp[-2].minor.yy129;}
dd20f34… drh 2854 #line 2854 "pikchr.c"
dd20f34… drh 2855 yymsp[-2].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2856 break;
b62f651… stephan 2857 case 75: /* position ::= expr LEFT OF position */
dd20f34… drh 2858 #line 721 "pikchr.y"
dd20f34… drh 2859 {yylhsminor.yy187=yymsp[0].minor.yy187; yylhsminor.yy187.x -= yymsp[-3].minor.yy129;}
dd20f34… drh 2860 #line 2860 "pikchr.c"
dd20f34… drh 2861 yymsp[-3].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2862 break;
b62f651… stephan 2863 case 76: /* position ::= expr RIGHT OF position */
dd20f34… drh 2864 #line 722 "pikchr.y"
dd20f34… drh 2865 {yylhsminor.yy187=yymsp[0].minor.yy187; yylhsminor.yy187.x += yymsp[-3].minor.yy129;}
dd20f34… drh 2866 #line 2866 "pikchr.c"
dd20f34… drh 2867 yymsp[-3].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2868 break;
b62f651… stephan 2869 case 77: /* position ::= expr ON HEADING EDGEPT OF position */
dd20f34… drh 2870 #line 724 "pikchr.y"
dd20f34… drh 2871 {yylhsminor.yy187 = pik_position_at_hdg(yymsp[-5].minor.yy129,&yymsp[-2].minor.yy0,yymsp[0].minor.yy187);}
dd20f34… drh 2872 #line 2872 "pikchr.c"
dd20f34… drh 2873 yymsp[-5].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2874 break;
b62f651… stephan 2875 case 78: /* position ::= expr HEADING EDGEPT OF position */
dd20f34… drh 2876 #line 726 "pikchr.y"
dd20f34… drh 2877 {yylhsminor.yy187 = pik_position_at_hdg(yymsp[-4].minor.yy129,&yymsp[-2].minor.yy0,yymsp[0].minor.yy187);}
dd20f34… drh 2878 #line 2878 "pikchr.c"
dd20f34… drh 2879 yymsp[-4].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2880 break;
b62f651… stephan 2881 case 79: /* position ::= expr EDGEPT OF position */
dd20f34… drh 2882 #line 728 "pikchr.y"
dd20f34… drh 2883 {yylhsminor.yy187 = pik_position_at_hdg(yymsp[-3].minor.yy129,&yymsp[-2].minor.yy0,yymsp[0].minor.yy187);}
dd20f34… drh 2884 #line 2884 "pikchr.c"
dd20f34… drh 2885 yymsp[-3].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2886 break;
b62f651… stephan 2887 case 80: /* position ::= expr ON HEADING expr FROM position */
dd20f34… drh 2888 #line 730 "pikchr.y"
dd20f34… drh 2889 {yylhsminor.yy187 = pik_position_at_angle(yymsp[-5].minor.yy129,yymsp[-2].minor.yy129,yymsp[0].minor.yy187);}
dd20f34… drh 2890 #line 2890 "pikchr.c"
dd20f34… drh 2891 yymsp[-5].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2892 break;
b62f651… stephan 2893 case 81: /* position ::= expr HEADING expr FROM position */
dd20f34… drh 2894 #line 732 "pikchr.y"
dd20f34… drh 2895 {yylhsminor.yy187 = pik_position_at_angle(yymsp[-4].minor.yy129,yymsp[-2].minor.yy129,yymsp[0].minor.yy187);}
dd20f34… drh 2896 #line 2896 "pikchr.c"
dd20f34… drh 2897 yymsp[-4].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2898 break;
b62f651… stephan 2899 case 82: /* place ::= edge OF object */
dd20f34… drh 2900 #line 744 "pikchr.y"
dd20f34… drh 2901 {yylhsminor.yy187 = pik_place_of_elem(p,yymsp[0].minor.yy54,&yymsp[-2].minor.yy0);}
dd20f34… drh 2902 #line 2902 "pikchr.c"
dd20f34… drh 2903 yymsp[-2].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2904 break;
b62f651… stephan 2905 case 83: /* place2 ::= object */
dd20f34… drh 2906 #line 745 "pikchr.y"
dd20f34… drh 2907 {yylhsminor.yy187 = pik_place_of_elem(p,yymsp[0].minor.yy54,0);}
dd20f34… drh 2908 #line 2908 "pikchr.c"
dd20f34… drh 2909 yymsp[0].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2910 break;
b62f651… stephan 2911 case 84: /* place2 ::= object DOT_E edge */
dd20f34… drh 2912 #line 746 "pikchr.y"
dd20f34… drh 2913 {yylhsminor.yy187 = pik_place_of_elem(p,yymsp[-2].minor.yy54,&yymsp[0].minor.yy0);}
dd20f34… drh 2914 #line 2914 "pikchr.c"
dd20f34… drh 2915 yymsp[-2].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2916 break;
b62f651… stephan 2917 case 85: /* place2 ::= NTH VERTEX OF object */
dd20f34… drh 2918 #line 747 "pikchr.y"
dd20f34… drh 2919 {yylhsminor.yy187 = pik_nth_vertex(p,&yymsp[-3].minor.yy0,&yymsp[-2].minor.yy0,yymsp[0].minor.yy54);}
dd20f34… drh 2920 #line 2920 "pikchr.c"
dd20f34… drh 2921 yymsp[-3].minor.yy187 = yylhsminor.yy187;
b62f651… stephan 2922 break;
b62f651… stephan 2923 case 86: /* object ::= nth */
dd20f34… drh 2924 #line 759 "pikchr.y"
dd20f34… drh 2925 {yylhsminor.yy54 = pik_find_nth(p,0,&yymsp[0].minor.yy0);}
dd20f34… drh 2926 #line 2926 "pikchr.c"
dd20f34… drh 2927 yymsp[0].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2928 break;
b62f651… stephan 2929 case 87: /* object ::= nth OF|IN object */
dd20f34… drh 2930 #line 760 "pikchr.y"
dd20f34… drh 2931 {yylhsminor.yy54 = pik_find_nth(p,yymsp[0].minor.yy54,&yymsp[-2].minor.yy0);}
dd20f34… drh 2932 #line 2932 "pikchr.c"
dd20f34… drh 2933 yymsp[-2].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2934 break;
b62f651… stephan 2935 case 88: /* objectname ::= THIS */
dd20f34… drh 2936 #line 762 "pikchr.y"
dd20f34… drh 2937 {yymsp[0].minor.yy54 = p->cur;}
dd20f34… drh 2938 #line 2938 "pikchr.c"
b62f651… stephan 2939 break;
b62f651… stephan 2940 case 89: /* objectname ::= PLACENAME */
dd20f34… drh 2941 #line 763 "pikchr.y"
dd20f34… drh 2942 {yylhsminor.yy54 = pik_find_byname(p,0,&yymsp[0].minor.yy0);}
dd20f34… drh 2943 #line 2943 "pikchr.c"
dd20f34… drh 2944 yymsp[0].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2945 break;
b62f651… stephan 2946 case 90: /* objectname ::= objectname DOT_U PLACENAME */
dd20f34… drh 2947 #line 765 "pikchr.y"
dd20f34… drh 2948 {yylhsminor.yy54 = pik_find_byname(p,yymsp[-2].minor.yy54,&yymsp[0].minor.yy0);}
dd20f34… drh 2949 #line 2949 "pikchr.c"
dd20f34… drh 2950 yymsp[-2].minor.yy54 = yylhsminor.yy54;
b62f651… stephan 2951 break;
b62f651… stephan 2952 case 91: /* nth ::= NTH CLASSNAME */
dd20f34… drh 2953 #line 767 "pikchr.y"
b62f651… stephan 2954 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-1].minor.yy0); }
dd20f34… drh 2955 #line 2955 "pikchr.c"
b62f651… stephan 2956 yymsp[-1].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2957 break;
b62f651… stephan 2958 case 92: /* nth ::= NTH LAST CLASSNAME */
dd20f34… drh 2959 #line 768 "pikchr.y"
b62f651… stephan 2960 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-2].minor.yy0); }
dd20f34… drh 2961 #line 2961 "pikchr.c"
b62f651… stephan 2962 yymsp[-2].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2963 break;
b62f651… stephan 2964 case 93: /* nth ::= LAST CLASSNAME */
dd20f34… drh 2965 #line 769 "pikchr.y"
b62f651… stephan 2966 {yymsp[-1].minor.yy0=yymsp[0].minor.yy0; yymsp[-1].minor.yy0.eCode = -1;}
dd20f34… drh 2967 #line 2967 "pikchr.c"
b62f651… stephan 2968 break;
b62f651… stephan 2969 case 94: /* nth ::= LAST */
dd20f34… drh 2970 #line 770 "pikchr.y"
b62f651… stephan 2971 {yylhsminor.yy0=yymsp[0].minor.yy0; yylhsminor.yy0.eCode = -1;}
dd20f34… drh 2972 #line 2972 "pikchr.c"
b62f651… stephan 2973 yymsp[0].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2974 break;
b62f651… stephan 2975 case 95: /* nth ::= NTH LB RB */
dd20f34… drh 2976 #line 771 "pikchr.y"
b62f651… stephan 2977 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = pik_nth_value(p,&yymsp[-2].minor.yy0);}
dd20f34… drh 2978 #line 2978 "pikchr.c"
b62f651… stephan 2979 yymsp[-2].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2980 break;
b62f651… stephan 2981 case 96: /* nth ::= NTH LAST LB RB */
dd20f34… drh 2982 #line 772 "pikchr.y"
b62f651… stephan 2983 {yylhsminor.yy0=yymsp[-1].minor.yy0; yylhsminor.yy0.eCode = -pik_nth_value(p,&yymsp[-3].minor.yy0);}
dd20f34… drh 2984 #line 2984 "pikchr.c"
b62f651… stephan 2985 yymsp[-3].minor.yy0 = yylhsminor.yy0;
b62f651… stephan 2986 break;
b62f651… stephan 2987 case 97: /* nth ::= LAST LB RB */
dd20f34… drh 2988 #line 773 "pikchr.y"
b62f651… stephan 2989 {yymsp[-2].minor.yy0=yymsp[-1].minor.yy0; yymsp[-2].minor.yy0.eCode = -1; }
dd20f34… drh 2990 #line 2990 "pikchr.c"
b62f651… stephan 2991 break;
b62f651… stephan 2992 case 98: /* expr ::= expr PLUS expr */
dd20f34… drh 2993 #line 775 "pikchr.y"
dd20f34… drh 2994 {yylhsminor.yy129=yymsp[-2].minor.yy129+yymsp[0].minor.yy129;}
dd20f34… drh 2995 #line 2995 "pikchr.c"
dd20f34… drh 2996 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 2997 break;
b62f651… stephan 2998 case 99: /* expr ::= expr MINUS expr */
dd20f34… drh 2999 #line 776 "pikchr.y"
dd20f34… drh 3000 {yylhsminor.yy129=yymsp[-2].minor.yy129-yymsp[0].minor.yy129;}
dd20f34… drh 3001 #line 3001 "pikchr.c"
dd20f34… drh 3002 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3003 break;
b62f651… stephan 3004 case 100: /* expr ::= expr STAR expr */
dd20f34… drh 3005 #line 777 "pikchr.y"
dd20f34… drh 3006 {yylhsminor.yy129=yymsp[-2].minor.yy129*yymsp[0].minor.yy129;}
dd20f34… drh 3007 #line 3007 "pikchr.c"
dd20f34… drh 3008 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3009 break;
b62f651… stephan 3010 case 101: /* expr ::= expr SLASH expr */
dd20f34… drh 3011 #line 778 "pikchr.y"
b62f651… stephan 3012 {
dd20f34… drh 3013 if( yymsp[0].minor.yy129==0.0 ){ pik_error(p, &yymsp[-1].minor.yy0, "division by zero"); yylhsminor.yy129 = 0.0; }
dd20f34… drh 3014 else{ yylhsminor.yy129 = yymsp[-2].minor.yy129/yymsp[0].minor.yy129; }
b62f651… stephan 3015 }
dd20f34… drh 3016 #line 3016 "pikchr.c"
dd20f34… drh 3017 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3018 break;
b62f651… stephan 3019 case 102: /* expr ::= MINUS expr */
dd20f34… drh 3020 #line 782 "pikchr.y"
dd20f34… drh 3021 {yymsp[-1].minor.yy129=-yymsp[0].minor.yy129;}
dd20f34… drh 3022 #line 3022 "pikchr.c"
b62f651… stephan 3023 break;
b62f651… stephan 3024 case 103: /* expr ::= PLUS expr */
dd20f34… drh 3025 #line 783 "pikchr.y"
dd20f34… drh 3026 {yymsp[-1].minor.yy129=yymsp[0].minor.yy129;}
dd20f34… drh 3027 #line 3027 "pikchr.c"
b62f651… stephan 3028 break;
b62f651… stephan 3029 case 104: /* expr ::= LP expr RP */
dd20f34… drh 3030 #line 784 "pikchr.y"
dd20f34… drh 3031 {yymsp[-2].minor.yy129=yymsp[-1].minor.yy129;}
dd20f34… drh 3032 #line 3032 "pikchr.c"
b62f651… stephan 3033 break;
b62f651… stephan 3034 case 105: /* expr ::= LP FILL|COLOR|THICKNESS RP */
dd20f34… drh 3035 #line 785 "pikchr.y"
dd20f34… drh 3036 {yymsp[-2].minor.yy129=pik_get_var(p,&yymsp[-1].minor.yy0);}
dd20f34… drh 3037 #line 3037 "pikchr.c"
b62f651… stephan 3038 break;
b62f651… stephan 3039 case 106: /* expr ::= NUMBER */
dd20f34… drh 3040 #line 786 "pikchr.y"
dd20f34… drh 3041 {yylhsminor.yy129=pik_atof(&yymsp[0].minor.yy0);}
dd20f34… drh 3042 #line 3042 "pikchr.c"
dd20f34… drh 3043 yymsp[0].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3044 break;
b62f651… stephan 3045 case 107: /* expr ::= ID */
dd20f34… drh 3046 #line 787 "pikchr.y"
dd20f34… drh 3047 {yylhsminor.yy129=pik_get_var(p,&yymsp[0].minor.yy0);}
dd20f34… drh 3048 #line 3048 "pikchr.c"
dd20f34… drh 3049 yymsp[0].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3050 break;
b62f651… stephan 3051 case 108: /* expr ::= FUNC1 LP expr RP */
dd20f34… drh 3052 #line 788 "pikchr.y"
dd20f34… drh 3053 {yylhsminor.yy129 = pik_func(p,&yymsp[-3].minor.yy0,yymsp[-1].minor.yy129,0.0);}
dd20f34… drh 3054 #line 3054 "pikchr.c"
dd20f34… drh 3055 yymsp[-3].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3056 break;
b62f651… stephan 3057 case 109: /* expr ::= FUNC2 LP expr COMMA expr RP */
dd20f34… drh 3058 #line 789 "pikchr.y"
dd20f34… drh 3059 {yylhsminor.yy129 = pik_func(p,&yymsp[-5].minor.yy0,yymsp[-3].minor.yy129,yymsp[-1].minor.yy129);}
dd20f34… drh 3060 #line 3060 "pikchr.c"
dd20f34… drh 3061 yymsp[-5].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3062 break;
b62f651… stephan 3063 case 110: /* expr ::= DIST LP position COMMA position RP */
dd20f34… drh 3064 #line 790 "pikchr.y"
dd20f34… drh 3065 {yymsp[-5].minor.yy129 = pik_dist(&yymsp[-3].minor.yy187,&yymsp[-1].minor.yy187);}
dd20f34… drh 3066 #line 3066 "pikchr.c"
b62f651… stephan 3067 break;
b62f651… stephan 3068 case 111: /* expr ::= place2 DOT_XY X */
dd20f34… drh 3069 #line 791 "pikchr.y"
dd20f34… drh 3070 {yylhsminor.yy129 = yymsp[-2].minor.yy187.x;}
dd20f34… drh 3071 #line 3071 "pikchr.c"
dd20f34… drh 3072 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3073 break;
b62f651… stephan 3074 case 112: /* expr ::= place2 DOT_XY Y */
dd20f34… drh 3075 #line 792 "pikchr.y"
dd20f34… drh 3076 {yylhsminor.yy129 = yymsp[-2].minor.yy187.y;}
dd20f34… drh 3077 #line 3077 "pikchr.c"
dd20f34… drh 3078 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3079 break;
b62f651… stephan 3080 case 113: /* expr ::= object DOT_L numproperty */
b62f651… stephan 3081 case 114: /* expr ::= object DOT_L dashproperty */ yytestcase(yyruleno==114);
b62f651… stephan 3082 case 115: /* expr ::= object DOT_L colorproperty */ yytestcase(yyruleno==115);
dd20f34… drh 3083 #line 793 "pikchr.y"
dd20f34… drh 3084 {yylhsminor.yy129=pik_property_of(yymsp[-2].minor.yy54,&yymsp[0].minor.yy0);}
dd20f34… drh 3085 #line 3085 "pikchr.c"
dd20f34… drh 3086 yymsp[-2].minor.yy129 = yylhsminor.yy129;
b62f651… stephan 3087 break;
b62f651… stephan 3088 default:
b62f651… stephan 3089 /* (116) lvalue ::= ID */ yytestcase(yyruleno==116);
b62f651… stephan 3090 /* (117) lvalue ::= FILL */ yytestcase(yyruleno==117);
b62f651… stephan 3091 /* (118) lvalue ::= COLOR */ yytestcase(yyruleno==118);
b62f651… stephan 3092 /* (119) lvalue ::= THICKNESS */ yytestcase(yyruleno==119);
b62f651… stephan 3093 /* (120) rvalue ::= expr */ yytestcase(yyruleno==120);
b62f651… stephan 3094 /* (121) print ::= PRINT */ yytestcase(yyruleno==121);
b62f651… stephan 3095 /* (122) prlist ::= pritem (OPTIMIZED OUT) */ assert(yyruleno!=122);
b62f651… stephan 3096 /* (123) prlist ::= prlist prsep pritem */ yytestcase(yyruleno==123);
b62f651… stephan 3097 /* (124) direction ::= UP */ yytestcase(yyruleno==124);
b62f651… stephan 3098 /* (125) direction ::= DOWN */ yytestcase(yyruleno==125);
b62f651… stephan 3099 /* (126) direction ::= LEFT */ yytestcase(yyruleno==126);
b62f651… stephan 3100 /* (127) direction ::= RIGHT */ yytestcase(yyruleno==127);
b62f651… stephan 3101 /* (128) optrelexpr ::= relexpr (OPTIMIZED OUT) */ assert(yyruleno!=128);
b62f651… stephan 3102 /* (129) attribute_list ::= alist */ yytestcase(yyruleno==129);
b62f651… stephan 3103 /* (130) alist ::= */ yytestcase(yyruleno==130);
b62f651… stephan 3104 /* (131) alist ::= alist attribute */ yytestcase(yyruleno==131);
b62f651… stephan 3105 /* (132) attribute ::= boolproperty (OPTIMIZED OUT) */ assert(yyruleno!=132);
b62f651… stephan 3106 /* (133) attribute ::= WITH withclause */ yytestcase(yyruleno==133);
b62f651… stephan 3107 /* (134) go ::= GO */ yytestcase(yyruleno==134);
b62f651… stephan 3108 /* (135) go ::= */ yytestcase(yyruleno==135);
b62f651… stephan 3109 /* (136) even ::= UNTIL EVEN WITH */ yytestcase(yyruleno==136);
b62f651… stephan 3110 /* (137) even ::= EVEN WITH */ yytestcase(yyruleno==137);
b62f651… stephan 3111 /* (138) dashproperty ::= DOTTED */ yytestcase(yyruleno==138);
b62f651… stephan 3112 /* (139) dashproperty ::= DASHED */ yytestcase(yyruleno==139);
b62f651… stephan 3113 /* (140) colorproperty ::= FILL */ yytestcase(yyruleno==140);
b62f651… stephan 3114 /* (141) colorproperty ::= COLOR */ yytestcase(yyruleno==141);
b62f651… stephan 3115 /* (142) position ::= place */ yytestcase(yyruleno==142);
b62f651… stephan 3116 /* (143) between ::= WAY BETWEEN */ yytestcase(yyruleno==143);
b62f651… stephan 3117 /* (144) between ::= BETWEEN */ yytestcase(yyruleno==144);
b62f651… stephan 3118 /* (145) between ::= OF THE WAY BETWEEN */ yytestcase(yyruleno==145);
b62f651… stephan 3119 /* (146) place ::= place2 */ yytestcase(yyruleno==146);
b62f651… stephan 3120 /* (147) edge ::= CENTER */ yytestcase(yyruleno==147);
b62f651… stephan 3121 /* (148) edge ::= EDGEPT */ yytestcase(yyruleno==148);
b62f651… stephan 3122 /* (149) edge ::= TOP */ yytestcase(yyruleno==149);
b62f651… stephan 3123 /* (150) edge ::= BOTTOM */ yytestcase(yyruleno==150);
b62f651… stephan 3124 /* (151) edge ::= START */ yytestcase(yyruleno==151);
b62f651… stephan 3125 /* (152) edge ::= END */ yytestcase(yyruleno==152);
b62f651… stephan 3126 /* (153) edge ::= RIGHT */ yytestcase(yyruleno==153);
b62f651… stephan 3127 /* (154) edge ::= LEFT */ yytestcase(yyruleno==154);
b62f651… stephan 3128 /* (155) object ::= objectname */ yytestcase(yyruleno==155);
b62f651… stephan 3129 break;
b62f651… stephan 3130 /********** End reduce actions ************************************************/
b62f651… stephan 3131 };
b62f651… stephan 3132 assert( yyruleno<sizeof(yyRuleInfoLhs)/sizeof(yyRuleInfoLhs[0]) );
b62f651… stephan 3133 yygoto = yyRuleInfoLhs[yyruleno];
b62f651… stephan 3134 yysize = yyRuleInfoNRhs[yyruleno];
b62f651… stephan 3135 yyact = yy_find_reduce_action(yymsp[yysize].stateno,(YYCODETYPE)yygoto);
b62f651… stephan 3136
b62f651… stephan 3137 /* There are no SHIFTREDUCE actions on nonterminals because the table
b62f651… stephan 3138 ** generator has simplified them to pure REDUCE actions. */
b62f651… stephan 3139 assert( !(yyact>YY_MAX_SHIFT && yyact<=YY_MAX_SHIFTREDUCE) );
b62f651… stephan 3140
b62f651… stephan 3141 /* It is not possible for a REDUCE to be followed by an error */
b62f651… stephan 3142 assert( yyact!=YY_ERROR_ACTION );
b62f651… stephan 3143
b62f651… stephan 3144 yymsp += yysize+1;
b62f651… stephan 3145 yypParser->yytos = yymsp;
b62f651… stephan 3146 yymsp->stateno = (YYACTIONTYPE)yyact;
b62f651… stephan 3147 yymsp->major = (YYCODETYPE)yygoto;
b62f651… stephan 3148 yyTraceShift(yypParser, yyact, "... then shift");
b62f651… stephan 3149 return yyact;
b62f651… stephan 3150 }
b62f651… stephan 3151
b62f651… stephan 3152 /*
b62f651… stephan 3153 ** The following code executes when the parse fails
b62f651… stephan 3154 */
b62f651… stephan 3155 #ifndef YYNOERRORRECOVERY
b62f651… stephan 3156 static void yy_parse_failed(
b62f651… stephan 3157 yyParser *yypParser /* The parser */
b62f651… stephan 3158 ){
b62f651… stephan 3159 pik_parserARG_FETCH
b62f651… stephan 3160 pik_parserCTX_FETCH
b62f651… stephan 3161 #ifndef NDEBUG
b62f651… stephan 3162 if( yyTraceFILE ){
b62f651… stephan 3163 fprintf(yyTraceFILE,"%sFail!\n",yyTracePrompt);
b62f651… stephan 3164 }
b62f651… stephan 3165 #endif
b62f651… stephan 3166 while( yypParser->yytos>yypParser->yystack ) yy_pop_parser_stack(yypParser);
b62f651… stephan 3167 /* Here code is inserted which will be executed whenever the
b62f651… stephan 3168 ** parser fails */
b62f651… stephan 3169 /************ Begin %parse_failure code ***************************************/
b62f651… stephan 3170 /************ End %parse_failure code *****************************************/
b62f651… stephan 3171 pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
b62f651… stephan 3172 pik_parserCTX_STORE
b62f651… stephan 3173 }
b62f651… stephan 3174 #endif /* YYNOERRORRECOVERY */
b62f651… stephan 3175
b62f651… stephan 3176 /*
b62f651… stephan 3177 ** The following code executes when a syntax error first occurs.
b62f651… stephan 3178 */
b62f651… stephan 3179 static void yy_syntax_error(
b62f651… stephan 3180 yyParser *yypParser, /* The parser */
b62f651… stephan 3181 int yymajor, /* The major type of the error token */
b62f651… stephan 3182 pik_parserTOKENTYPE yyminor /* The minor type of the error token */
b62f651… stephan 3183 ){
b62f651… stephan 3184 pik_parserARG_FETCH
b62f651… stephan 3185 pik_parserCTX_FETCH
b62f651… stephan 3186 #define TOKEN yyminor
b62f651… stephan 3187 /************ Begin %syntax_error code ****************************************/
dd20f34… drh 3188 #line 551 "pikchr.y"
b62f651… stephan 3189
b62f651… stephan 3190 if( TOKEN.z && TOKEN.z[0] ){
b62f651… stephan 3191 pik_error(p, &TOKEN, "syntax error");
b62f651… stephan 3192 }else{
b62f651… stephan 3193 pik_error(p, 0, "syntax error");
b62f651… stephan 3194 }
b62f651… stephan 3195 UNUSED_PARAMETER(yymajor);
dd20f34… drh 3196 #line 3196 "pikchr.c"
b62f651… stephan 3197 /************ End %syntax_error code ******************************************/
b62f651… stephan 3198 pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
b62f651… stephan 3199 pik_parserCTX_STORE
b62f651… stephan 3200 }
b62f651… stephan 3201
b62f651… stephan 3202 /*
b62f651… stephan 3203 ** The following is executed when the parser accepts
b62f651… stephan 3204 */
b62f651… stephan 3205 static void yy_accept(
b62f651… stephan 3206 yyParser *yypParser /* The parser */
b62f651… stephan 3207 ){
b62f651… stephan 3208 pik_parserARG_FETCH
b62f651… stephan 3209 pik_parserCTX_FETCH
b62f651… stephan 3210 #ifndef NDEBUG
b62f651… stephan 3211 if( yyTraceFILE ){
b62f651… stephan 3212 fprintf(yyTraceFILE,"%sAccept!\n",yyTracePrompt);
b62f651… stephan 3213 }
b62f651… stephan 3214 #endif
b62f651… stephan 3215 #ifndef YYNOERRORRECOVERY
b62f651… stephan 3216 yypParser->yyerrcnt = -1;
b62f651… stephan 3217 #endif
b62f651… stephan 3218 assert( yypParser->yytos==yypParser->yystack );
b62f651… stephan 3219 /* Here code is inserted which will be executed whenever the
b62f651… stephan 3220 ** parser accepts */
b62f651… stephan 3221 /*********** Begin %parse_accept code *****************************************/
b62f651… stephan 3222 /*********** End %parse_accept code *******************************************/
b62f651… stephan 3223 pik_parserARG_STORE /* Suppress warning about unused %extra_argument variable */
b62f651… stephan 3224 pik_parserCTX_STORE
b62f651… stephan 3225 }
b62f651… stephan 3226
b62f651… stephan 3227 /* The main parser program.
b62f651… stephan 3228 ** The first argument is a pointer to a structure obtained from
b62f651… stephan 3229 ** "pik_parserAlloc" which describes the current state of the parser.
b62f651… stephan 3230 ** The second argument is the major token number. The third is
b62f651… stephan 3231 ** the minor token. The fourth optional argument is whatever the
b62f651… stephan 3232 ** user wants (and specified in the grammar) and is available for
b62f651… stephan 3233 ** use by the action routines.
b62f651… stephan 3234 **
b62f651… stephan 3235 ** Inputs:
b62f651… stephan 3236 ** <ul>
b62f651… stephan 3237 ** <li> A pointer to the parser (an opaque structure.)
b62f651… stephan 3238 ** <li> The major token number.
b62f651… stephan 3239 ** <li> The minor token number.
b62f651… stephan 3240 ** <li> An option argument of a grammar-specified type.
b62f651… stephan 3241 ** </ul>
b62f651… stephan 3242 **
b62f651… stephan 3243 ** Outputs:
b62f651… stephan 3244 ** None.
b62f651… stephan 3245 */
b62f651… stephan 3246 void pik_parser(
b62f651… stephan 3247 void *yyp, /* The parser */
b62f651… stephan 3248 int yymajor, /* The major token code number */
b62f651… stephan 3249 pik_parserTOKENTYPE yyminor /* The value for the token */
b62f651… stephan 3250 pik_parserARG_PDECL /* Optional %extra_argument parameter */
b62f651… stephan 3251 ){
b62f651… stephan 3252 YYMINORTYPE yyminorunion;
b62f651… stephan 3253 YYACTIONTYPE yyact; /* The parser action. */
b62f651… stephan 3254 #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
b62f651… stephan 3255 int yyendofinput; /* True if we are at the end of input */
b62f651… stephan 3256 #endif
b62f651… stephan 3257 #ifdef YYERRORSYMBOL
b62f651… stephan 3258 int yyerrorhit = 0; /* True if yymajor has invoked an error */
b62f651… stephan 3259 #endif
b62f651… stephan 3260 yyParser *yypParser = (yyParser*)yyp; /* The parser */
b62f651… stephan 3261 pik_parserCTX_FETCH
b62f651… stephan 3262 pik_parserARG_STORE
b62f651… stephan 3263
b62f651… stephan 3264 assert( yypParser->yytos!=0 );
b62f651… stephan 3265 #if !defined(YYERRORSYMBOL) && !defined(YYNOERRORRECOVERY)
b62f651… stephan 3266 yyendofinput = (yymajor==0);
b62f651… stephan 3267 #endif
b62f651… stephan 3268
b62f651… stephan 3269 yyact = yypParser->yytos->stateno;
b62f651… stephan 3270 #ifndef NDEBUG
b62f651… stephan 3271 if( yyTraceFILE ){
b62f651… stephan 3272 if( yyact < YY_MIN_REDUCE ){
b62f651… stephan 3273 fprintf(yyTraceFILE,"%sInput '%s' in state %d\n",
b62f651… stephan 3274 yyTracePrompt,yyTokenName[yymajor],yyact);
b62f651… stephan 3275 }else{
b62f651… stephan 3276 fprintf(yyTraceFILE,"%sInput '%s' with pending reduce %d\n",
b62f651… stephan 3277 yyTracePrompt,yyTokenName[yymajor],yyact-YY_MIN_REDUCE);
b62f651… stephan 3278 }
b62f651… stephan 3279 }
b62f651… stephan 3280 #endif
b62f651… stephan 3281
8f4a32c… drh 3282 while(1){ /* Exit by "break" */
8f4a32c… drh 3283 assert( yypParser->yytos>=yypParser->yystack );
b62f651… stephan 3284 assert( yyact==yypParser->yytos->stateno );
b62f651… stephan 3285 yyact = yy_find_shift_action((YYCODETYPE)yymajor,yyact);
b62f651… stephan 3286 if( yyact >= YY_MIN_REDUCE ){
8f4a32c… drh 3287 unsigned int yyruleno = yyact - YY_MIN_REDUCE; /* Reduce by this rule */
8f4a32c… drh 3288 #ifndef NDEBUG
8f4a32c… drh 3289 assert( yyruleno<(int)(sizeof(yyRuleName)/sizeof(yyRuleName[0])) );
8f4a32c… drh 3290 if( yyTraceFILE ){
8f4a32c… drh 3291 int yysize = yyRuleInfoNRhs[yyruleno];
8f4a32c… drh 3292 if( yysize ){
8f4a32c… drh 3293 fprintf(yyTraceFILE, "%sReduce %d [%s]%s, pop back to state %d.\n",
8f4a32c… drh 3294 yyTracePrompt,
8f4a32c… drh 3295 yyruleno, yyRuleName[yyruleno],
8f4a32c… drh 3296 yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action",
8f4a32c… drh 3297 yypParser->yytos[yysize].stateno);
8f4a32c… drh 3298 }else{
8f4a32c… drh 3299 fprintf(yyTraceFILE, "%sReduce %d [%s]%s.\n",
8f4a32c… drh 3300 yyTracePrompt, yyruleno, yyRuleName[yyruleno],
8f4a32c… drh 3301 yyruleno<YYNRULE_WITH_ACTION ? "" : " without external action");
8f4a32c… drh 3302 }
8f4a32c… drh 3303 }
8f4a32c… drh 3304 #endif /* NDEBUG */
8f4a32c… drh 3305
8f4a32c… drh 3306 /* Check that the stack is large enough to grow by a single entry
8f4a32c… drh 3307 ** if the RHS of the rule is empty. This ensures that there is room
8f4a32c… drh 3308 ** enough on the stack to push the LHS value */
8f4a32c… drh 3309 if( yyRuleInfoNRhs[yyruleno]==0 ){
8f4a32c… drh 3310 #ifdef YYTRACKMAXSTACKDEPTH
8f4a32c… drh 3311 if( (int)(yypParser->yytos - yypParser->yystack)>yypParser->yyhwm ){
8f4a32c… drh 3312 yypParser->yyhwm++;
8f4a32c… drh 3313 assert( yypParser->yyhwm ==
8f4a32c… drh 3314 (int)(yypParser->yytos - yypParser->yystack));
8f4a32c… drh 3315 }
8f4a32c… drh 3316 #endif
8f4a32c… drh 3317 if( yypParser->yytos>=yypParser->yystackEnd ){
8f4a32c… drh 3318 if( yyGrowStack(yypParser) ){
8f4a32c… drh 3319 yyStackOverflow(yypParser);
8f4a32c… drh 3320 break;
8f4a32c… drh 3321 }
8f4a32c… drh 3322 }
8f4a32c… drh 3323 }
8f4a32c… drh 3324 yyact = yy_reduce(yypParser,yyruleno,yymajor,yyminor pik_parserCTX_PARAM);
b62f651… stephan 3325 }else if( yyact <= YY_MAX_SHIFTREDUCE ){
b62f651… stephan 3326 yy_shift(yypParser,yyact,(YYCODETYPE)yymajor,yyminor);
b62f651… stephan 3327 #ifndef YYNOERRORRECOVERY
b62f651… stephan 3328 yypParser->yyerrcnt--;
b62f651… stephan 3329 #endif
b62f651… stephan 3330 break;
b62f651… stephan 3331 }else if( yyact==YY_ACCEPT_ACTION ){
b62f651… stephan 3332 yypParser->yytos--;
b62f651… stephan 3333 yy_accept(yypParser);
b62f651… stephan 3334 return;
b62f651… stephan 3335 }else{
b62f651… stephan 3336 assert( yyact == YY_ERROR_ACTION );
b62f651… stephan 3337 yyminorunion.yy0 = yyminor;
b62f651… stephan 3338 #ifdef YYERRORSYMBOL
b62f651… stephan 3339 int yymx;
b62f651… stephan 3340 #endif
b62f651… stephan 3341 #ifndef NDEBUG
b62f651… stephan 3342 if( yyTraceFILE ){
b62f651… stephan 3343 fprintf(yyTraceFILE,"%sSyntax Error!\n",yyTracePrompt);
b62f651… stephan 3344 }
b62f651… stephan 3345 #endif
b62f651… stephan 3346 #ifdef YYERRORSYMBOL
b62f651… stephan 3347 /* A syntax error has occurred.
b62f651… stephan 3348 ** The response to an error depends upon whether or not the
b62f651… stephan 3349 ** grammar defines an error token "ERROR".
b62f651… stephan 3350 **
b62f651… stephan 3351 ** This is what we do if the grammar does define ERROR:
b62f651… stephan 3352 **
b62f651… stephan 3353 ** * Call the %syntax_error function.
b62f651… stephan 3354 **
b62f651… stephan 3355 ** * Begin popping the stack until we enter a state where
b62f651… stephan 3356 ** it is legal to shift the error symbol, then shift
b62f651… stephan 3357 ** the error symbol.
b62f651… stephan 3358 **
b62f651… stephan 3359 ** * Set the error count to three.
b62f651… stephan 3360 **
b62f651… stephan 3361 ** * Begin accepting and shifting new tokens. No new error
b62f651… stephan 3362 ** processing will occur until three tokens have been
b62f651… stephan 3363 ** shifted successfully.
b62f651… stephan 3364 **
b62f651… stephan 3365 */
b62f651… stephan 3366 if( yypParser->yyerrcnt<0 ){
b62f651… stephan 3367 yy_syntax_error(yypParser,yymajor,yyminor);
b62f651… stephan 3368 }
b62f651… stephan 3369 yymx = yypParser->yytos->major;
b62f651… stephan 3370 if( yymx==YYERRORSYMBOL || yyerrorhit ){
b62f651… stephan 3371 #ifndef NDEBUG
b62f651… stephan 3372 if( yyTraceFILE ){
b62f651… stephan 3373 fprintf(yyTraceFILE,"%sDiscard input token %s\n",
b62f651… stephan 3374 yyTracePrompt,yyTokenName[yymajor]);
b62f651… stephan 3375 }
b62f651… stephan 3376 #endif
b62f651… stephan 3377 yy_destructor(yypParser, (YYCODETYPE)yymajor, &yyminorunion);
b62f651… stephan 3378 yymajor = YYNOCODE;
b62f651… stephan 3379 }else{
8f4a32c… drh 3380 while( yypParser->yytos > yypParser->yystack ){
8f4a32c… drh 3381 yyact = yy_find_reduce_action(yypParser->yytos->stateno,
8f4a32c… drh 3382 YYERRORSYMBOL);
8f4a32c… drh 3383 if( yyact<=YY_MAX_SHIFTREDUCE ) break;
b62f651… stephan 3384 yy_pop_parser_stack(yypParser);
b62f651… stephan 3385 }
8f4a32c… drh 3386 if( yypParser->yytos <= yypParser->yystack || yymajor==0 ){
b62f651… stephan 3387 yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
b62f651… stephan 3388 yy_parse_failed(yypParser);
b62f651… stephan 3389 #ifndef YYNOERRORRECOVERY
b62f651… stephan 3390 yypParser->yyerrcnt = -1;
b62f651… stephan 3391 #endif
b62f651… stephan 3392 yymajor = YYNOCODE;
b62f651… stephan 3393 }else if( yymx!=YYERRORSYMBOL ){
b62f651… stephan 3394 yy_shift(yypParser,yyact,YYERRORSYMBOL,yyminor);
b62f651… stephan 3395 }
b62f651… stephan 3396 }
b62f651… stephan 3397 yypParser->yyerrcnt = 3;
b62f651… stephan 3398 yyerrorhit = 1;
b62f651… stephan 3399 if( yymajor==YYNOCODE ) break;
b62f651… stephan 3400 yyact = yypParser->yytos->stateno;
b62f651… stephan 3401 #elif defined(YYNOERRORRECOVERY)
b62f651… stephan 3402 /* If the YYNOERRORRECOVERY macro is defined, then do not attempt to
b62f651… stephan 3403 ** do any kind of error recovery. Instead, simply invoke the syntax
b62f651… stephan 3404 ** error routine and continue going as if nothing had happened.
b62f651… stephan 3405 **
b62f651… stephan 3406 ** Applications can set this macro (for example inside %include) if
b62f651… stephan 3407 ** they intend to abandon the parse upon the first syntax error seen.
b62f651… stephan 3408 */
b62f651… stephan 3409 yy_syntax_error(yypParser,yymajor, yyminor);
b62f651… stephan 3410 yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
b62f651… stephan 3411 break;
b62f651… stephan 3412 #else /* YYERRORSYMBOL is not defined */
b62f651… stephan 3413 /* This is what we do if the grammar does not define ERROR:
b62f651… stephan 3414 **
b62f651… stephan 3415 ** * Report an error message, and throw away the input token.
b62f651… stephan 3416 **
b62f651… stephan 3417 ** * If the input token is $, then fail the parse.
b62f651… stephan 3418 **
b62f651… stephan 3419 ** As before, subsequent error messages are suppressed until
b62f651… stephan 3420 ** three input tokens have been successfully shifted.
b62f651… stephan 3421 */
b62f651… stephan 3422 if( yypParser->yyerrcnt<=0 ){
b62f651… stephan 3423 yy_syntax_error(yypParser,yymajor, yyminor);
b62f651… stephan 3424 }
b62f651… stephan 3425 yypParser->yyerrcnt = 3;
b62f651… stephan 3426 yy_destructor(yypParser,(YYCODETYPE)yymajor,&yyminorunion);
b62f651… stephan 3427 if( yyendofinput ){
b62f651… stephan 3428 yy_parse_failed(yypParser);
b62f651… stephan 3429 #ifndef YYNOERRORRECOVERY
b62f651… stephan 3430 yypParser->yyerrcnt = -1;
b62f651… stephan 3431 #endif
b62f651… stephan 3432 }
b62f651… stephan 3433 break;
b62f651… stephan 3434 #endif
b62f651… stephan 3435 }
8f4a32c… drh 3436 }
b62f651… stephan 3437 #ifndef NDEBUG
b62f651… stephan 3438 if( yyTraceFILE ){
b62f651… stephan 3439 yyStackEntry *i;
b62f651… stephan 3440 char cDiv = '[';
b62f651… stephan 3441 fprintf(yyTraceFILE,"%sReturn. Stack=",yyTracePrompt);
b62f651… stephan 3442 for(i=&yypParser->yystack[1]; i<=yypParser->yytos; i++){
b62f651… stephan 3443 fprintf(yyTraceFILE,"%c%s", cDiv, yyTokenName[i->major]);
b62f651… stephan 3444 cDiv = ' ';
b62f651… stephan 3445 }
b62f651… stephan 3446 fprintf(yyTraceFILE,"]\n");
b62f651… stephan 3447 }
b62f651… stephan 3448 #endif
b62f651… stephan 3449 return;
b62f651… stephan 3450 }
b62f651… stephan 3451
b62f651… stephan 3452 /*
b62f651… stephan 3453 ** Return the fallback token corresponding to canonical token iToken, or
b62f651… stephan 3454 ** 0 if iToken has no fallback.
b62f651… stephan 3455 */
b62f651… stephan 3456 int pik_parserFallback(int iToken){
b62f651… stephan 3457 #ifdef YYFALLBACK
b62f651… stephan 3458 assert( iToken<(int)(sizeof(yyFallback)/sizeof(yyFallback[0])) );
b62f651… stephan 3459 return yyFallback[iToken];
b62f651… stephan 3460 #else
b62f651… stephan 3461 (void)iToken;
b62f651… stephan 3462 return 0;
b62f651… stephan 3463 #endif
b62f651… stephan 3464 }
dd20f34… drh 3465 #line 798 "pikchr.y"
b62f651… stephan 3466
b62f651… stephan 3467
b62f651… stephan 3468
b62f651… stephan 3469 /* Chart of the 148 official CSS color names with their
b62f651… stephan 3470 ** corresponding RGB values thru Color Module Level 4:
b62f651… stephan 3471 ** https://developer.mozilla.org/en-US/docs/Web/CSS/color_value
b62f651… stephan 3472 **
b62f651… stephan 3473 ** Two new names "None" and "Off" are added with a value
b62f651… stephan 3474 ** of -1.
b62f651… stephan 3475 */
b62f651… stephan 3476 static const struct {
b62f651… stephan 3477 const char *zName; /* Name of the color */
b62f651… stephan 3478 int val; /* RGB value */
b62f651… stephan 3479 } aColor[] = {
b62f651… stephan 3480 { "AliceBlue", 0xf0f8ff },
b62f651… stephan 3481 { "AntiqueWhite", 0xfaebd7 },
b62f651… stephan 3482 { "Aqua", 0x00ffff },
b62f651… stephan 3483 { "Aquamarine", 0x7fffd4 },
b62f651… stephan 3484 { "Azure", 0xf0ffff },
b62f651… stephan 3485 { "Beige", 0xf5f5dc },
b62f651… stephan 3486 { "Bisque", 0xffe4c4 },
b62f651… stephan 3487 { "Black", 0x000000 },
b62f651… stephan 3488 { "BlanchedAlmond", 0xffebcd },
b62f651… stephan 3489 { "Blue", 0x0000ff },
b62f651… stephan 3490 { "BlueViolet", 0x8a2be2 },
b62f651… stephan 3491 { "Brown", 0xa52a2a },
b62f651… stephan 3492 { "BurlyWood", 0xdeb887 },
b62f651… stephan 3493 { "CadetBlue", 0x5f9ea0 },
b62f651… stephan 3494 { "Chartreuse", 0x7fff00 },
b62f651… stephan 3495 { "Chocolate", 0xd2691e },
b62f651… stephan 3496 { "Coral", 0xff7f50 },
b62f651… stephan 3497 { "CornflowerBlue", 0x6495ed },
b62f651… stephan 3498 { "Cornsilk", 0xfff8dc },
b62f651… stephan 3499 { "Crimson", 0xdc143c },
b62f651… stephan 3500 { "Cyan", 0x00ffff },
b62f651… stephan 3501 { "DarkBlue", 0x00008b },
b62f651… stephan 3502 { "DarkCyan", 0x008b8b },
b62f651… stephan 3503 { "DarkGoldenrod", 0xb8860b },
b62f651… stephan 3504 { "DarkGray", 0xa9a9a9 },
b62f651… stephan 3505 { "DarkGreen", 0x006400 },
b62f651… stephan 3506 { "DarkGrey", 0xa9a9a9 },
b62f651… stephan 3507 { "DarkKhaki", 0xbdb76b },
b62f651… stephan 3508 { "DarkMagenta", 0x8b008b },
b62f651… stephan 3509 { "DarkOliveGreen", 0x556b2f },
b62f651… stephan 3510 { "DarkOrange", 0xff8c00 },
b62f651… stephan 3511 { "DarkOrchid", 0x9932cc },
b62f651… stephan 3512 { "DarkRed", 0x8b0000 },
b62f651… stephan 3513 { "DarkSalmon", 0xe9967a },
b62f651… stephan 3514 { "DarkSeaGreen", 0x8fbc8f },
b62f651… stephan 3515 { "DarkSlateBlue", 0x483d8b },
b62f651… stephan 3516 { "DarkSlateGray", 0x2f4f4f },
b62f651… stephan 3517 { "DarkSlateGrey", 0x2f4f4f },
b62f651… stephan 3518 { "DarkTurquoise", 0x00ced1 },
b62f651… stephan 3519 { "DarkViolet", 0x9400d3 },
b62f651… stephan 3520 { "DeepPink", 0xff1493 },
b62f651… stephan 3521 { "DeepSkyBlue", 0x00bfff },
b62f651… stephan 3522 { "DimGray", 0x696969 },
b62f651… stephan 3523 { "DimGrey", 0x696969 },
b62f651… stephan 3524 { "DodgerBlue", 0x1e90ff },
b62f651… stephan 3525 { "Firebrick", 0xb22222 },
b62f651… stephan 3526 { "FloralWhite", 0xfffaf0 },
b62f651… stephan 3527 { "ForestGreen", 0x228b22 },
b62f651… stephan 3528 { "Fuchsia", 0xff00ff },
b62f651… stephan 3529 { "Gainsboro", 0xdcdcdc },
b62f651… stephan 3530 { "GhostWhite", 0xf8f8ff },
b62f651… stephan 3531 { "Gold", 0xffd700 },
b62f651… stephan 3532 { "Goldenrod", 0xdaa520 },
b62f651… stephan 3533 { "Gray", 0x808080 },
b62f651… stephan 3534 { "Green", 0x008000 },
b62f651… stephan 3535 { "GreenYellow", 0xadff2f },
b62f651… stephan 3536 { "Grey", 0x808080 },
b62f651… stephan 3537 { "Honeydew", 0xf0fff0 },
b62f651… stephan 3538 { "HotPink", 0xff69b4 },
b62f651… stephan 3539 { "IndianRed", 0xcd5c5c },
b62f651… stephan 3540 { "Indigo", 0x4b0082 },
b62f651… stephan 3541 { "Ivory", 0xfffff0 },
b62f651… stephan 3542 { "Khaki", 0xf0e68c },
b62f651… stephan 3543 { "Lavender", 0xe6e6fa },
b62f651… stephan 3544 { "LavenderBlush", 0xfff0f5 },
b62f651… stephan 3545 { "LawnGreen", 0x7cfc00 },
b62f651… stephan 3546 { "LemonChiffon", 0xfffacd },
b62f651… stephan 3547 { "LightBlue", 0xadd8e6 },
b62f651… stephan 3548 { "LightCoral", 0xf08080 },
b62f651… stephan 3549 { "LightCyan", 0xe0ffff },
b62f651… stephan 3550 { "LightGoldenrodYellow", 0xfafad2 },
b62f651… stephan 3551 { "LightGray", 0xd3d3d3 },
b62f651… stephan 3552 { "LightGreen", 0x90ee90 },
b62f651… stephan 3553 { "LightGrey", 0xd3d3d3 },
b62f651… stephan 3554 { "LightPink", 0xffb6c1 },
b62f651… stephan 3555 { "LightSalmon", 0xffa07a },
b62f651… stephan 3556 { "LightSeaGreen", 0x20b2aa },
b62f651… stephan 3557 { "LightSkyBlue", 0x87cefa },
b62f651… stephan 3558 { "LightSlateGray", 0x778899 },
b62f651… stephan 3559 { "LightSlateGrey", 0x778899 },
b62f651… stephan 3560 { "LightSteelBlue", 0xb0c4de },
b62f651… stephan 3561 { "LightYellow", 0xffffe0 },
b62f651… stephan 3562 { "Lime", 0x00ff00 },
b62f651… stephan 3563 { "LimeGreen", 0x32cd32 },
b62f651… stephan 3564 { "Linen", 0xfaf0e6 },
b62f651… stephan 3565 { "Magenta", 0xff00ff },
b62f651… stephan 3566 { "Maroon", 0x800000 },
b62f651… stephan 3567 { "MediumAquamarine", 0x66cdaa },
b62f651… stephan 3568 { "MediumBlue", 0x0000cd },
b62f651… stephan 3569 { "MediumOrchid", 0xba55d3 },
b62f651… stephan 3570 { "MediumPurple", 0x9370db },
b62f651… stephan 3571 { "MediumSeaGreen", 0x3cb371 },
b62f651… stephan 3572 { "MediumSlateBlue", 0x7b68ee },
b62f651… stephan 3573 { "MediumSpringGreen", 0x00fa9a },
b62f651… stephan 3574 { "MediumTurquoise", 0x48d1cc },
b62f651… stephan 3575 { "MediumVioletRed", 0xc71585 },
b62f651… stephan 3576 { "MidnightBlue", 0x191970 },
b62f651… stephan 3577 { "MintCream", 0xf5fffa },
b62f651… stephan 3578 { "MistyRose", 0xffe4e1 },
b62f651… stephan 3579 { "Moccasin", 0xffe4b5 },
b62f651… stephan 3580 { "NavajoWhite", 0xffdead },
b62f651… stephan 3581 { "Navy", 0x000080 },
b62f651… stephan 3582 { "None", -1 }, /* Non-standard addition */
b62f651… stephan 3583 { "Off", -1 }, /* Non-standard addition */
b62f651… stephan 3584 { "OldLace", 0xfdf5e6 },
b62f651… stephan 3585 { "Olive", 0x808000 },
b62f651… stephan 3586 { "OliveDrab", 0x6b8e23 },
b62f651… stephan 3587 { "Orange", 0xffa500 },
b62f651… stephan 3588 { "OrangeRed", 0xff4500 },
b62f651… stephan 3589 { "Orchid", 0xda70d6 },
b62f651… stephan 3590 { "PaleGoldenrod", 0xeee8aa },
b62f651… stephan 3591 { "PaleGreen", 0x98fb98 },
b62f651… stephan 3592 { "PaleTurquoise", 0xafeeee },
b62f651… stephan 3593 { "PaleVioletRed", 0xdb7093 },
b62f651… stephan 3594 { "PapayaWhip", 0xffefd5 },
b62f651… stephan 3595 { "PeachPuff", 0xffdab9 },
b62f651… stephan 3596 { "Peru", 0xcd853f },
b62f651… stephan 3597 { "Pink", 0xffc0cb },
b62f651… stephan 3598 { "Plum", 0xdda0dd },
b62f651… stephan 3599 { "PowderBlue", 0xb0e0e6 },
b62f651… stephan 3600 { "Purple", 0x800080 },
b62f651… stephan 3601 { "RebeccaPurple", 0x663399 },
b62f651… stephan 3602 { "Red", 0xff0000 },
b62f651… stephan 3603 { "RosyBrown", 0xbc8f8f },
b62f651… stephan 3604 { "RoyalBlue", 0x4169e1 },
b62f651… stephan 3605 { "SaddleBrown", 0x8b4513 },
b62f651… stephan 3606 { "Salmon", 0xfa8072 },
b62f651… stephan 3607 { "SandyBrown", 0xf4a460 },
b62f651… stephan 3608 { "SeaGreen", 0x2e8b57 },
b62f651… stephan 3609 { "Seashell", 0xfff5ee },
b62f651… stephan 3610 { "Sienna", 0xa0522d },
b62f651… stephan 3611 { "Silver", 0xc0c0c0 },
b62f651… stephan 3612 { "SkyBlue", 0x87ceeb },
b62f651… stephan 3613 { "SlateBlue", 0x6a5acd },
b62f651… stephan 3614 { "SlateGray", 0x708090 },
b62f651… stephan 3615 { "SlateGrey", 0x708090 },
b62f651… stephan 3616 { "Snow", 0xfffafa },
b62f651… stephan 3617 { "SpringGreen", 0x00ff7f },
b62f651… stephan 3618 { "SteelBlue", 0x4682b4 },
b62f651… stephan 3619 { "Tan", 0xd2b48c },
b62f651… stephan 3620 { "Teal", 0x008080 },
b62f651… stephan 3621 { "Thistle", 0xd8bfd8 },
b62f651… stephan 3622 { "Tomato", 0xff6347 },
b62f651… stephan 3623 { "Turquoise", 0x40e0d0 },
b62f651… stephan 3624 { "Violet", 0xee82ee },
b62f651… stephan 3625 { "Wheat", 0xf5deb3 },
b62f651… stephan 3626 { "White", 0xffffff },
b62f651… stephan 3627 { "WhiteSmoke", 0xf5f5f5 },
b62f651… stephan 3628 { "Yellow", 0xffff00 },
b62f651… stephan 3629 { "YellowGreen", 0x9acd32 },
b62f651… stephan 3630 };
b62f651… stephan 3631
b62f651… stephan 3632 /* Built-in variable names.
b62f651… stephan 3633 **
b62f651… stephan 3634 ** This array is constant. When a script changes the value of one of
b62f651… stephan 3635 ** these built-ins, a new PVar record is added at the head of
b62f651… stephan 3636 ** the Pik.pVar list, which is searched first. Thus the new PVar entry
b62f651… stephan 3637 ** will override this default value.
b62f651… stephan 3638 **
b62f651… stephan 3639 ** Units are in inches, except for "color" and "fill" which are
b62f651… stephan 3640 ** interpreted as 24-bit RGB values.
b62f651… stephan 3641 **
b62f651… stephan 3642 ** Binary search used. Must be kept in sorted order.
b62f651… stephan 3643 */
b62f651… stephan 3644 static const struct { const char *zName; PNum val; } aBuiltin[] = {
b62f651… stephan 3645 { "arcrad", 0.25 },
b62f651… stephan 3646 { "arrowhead", 2.0 },
b62f651… stephan 3647 { "arrowht", 0.08 },
b62f651… stephan 3648 { "arrowwid", 0.06 },
b62f651… stephan 3649 { "boxht", 0.5 },
b62f651… stephan 3650 { "boxrad", 0.0 },
b62f651… stephan 3651 { "boxwid", 0.75 },
b62f651… stephan 3652 { "charht", 0.14 },
b62f651… stephan 3653 { "charwid", 0.08 },
b62f651… stephan 3654 { "circlerad", 0.25 },
b62f651… stephan 3655 { "color", 0.0 },
b62f651… stephan 3656 { "cylht", 0.5 },
b62f651… stephan 3657 { "cylrad", 0.075 },
b62f651… stephan 3658 { "cylwid", 0.75 },
b62f651… stephan 3659 { "dashwid", 0.05 },
7573b3f… drh 3660 { "diamondht", 0.75 },
7573b3f… drh 3661 { "diamondwid", 1.0 },
b62f651… stephan 3662 { "dotrad", 0.015 },
b62f651… stephan 3663 { "ellipseht", 0.5 },
b62f651… stephan 3664 { "ellipsewid", 0.75 },
b62f651… stephan 3665 { "fileht", 0.75 },
b62f651… stephan 3666 { "filerad", 0.15 },
b62f651… stephan 3667 { "filewid", 0.5 },
b62f651… stephan 3668 { "fill", -1.0 },
b62f651… stephan 3669 { "lineht", 0.5 },
b62f651… stephan 3670 { "linewid", 0.5 },
b62f651… stephan 3671 { "movewid", 0.5 },
b62f651… stephan 3672 { "ovalht", 0.5 },
b62f651… stephan 3673 { "ovalwid", 1.0 },
b62f651… stephan 3674 { "scale", 1.0 },
b62f651… stephan 3675 { "textht", 0.5 },
b62f651… stephan 3676 { "textwid", 0.75 },
b62f651… stephan 3677 { "thickness", 0.015 },
b62f651… stephan 3678 };
b62f651… stephan 3679
b62f651… stephan 3680
b62f651… stephan 3681 /* Methods for the "arc" class */
b62f651… stephan 3682 static void arcInit(Pik *p, PObj *pObj){
b62f651… stephan 3683 pObj->w = pik_value(p, "arcrad",6,0);
b62f651… stephan 3684 pObj->h = pObj->w;
b62f651… stephan 3685 }
b62f651… stephan 3686 /* Hack: Arcs are here rendered as quadratic Bezier curves rather
b62f651… stephan 3687 ** than true arcs. Multiple reasons: (1) the legacy-PIC parameters
b62f651… stephan 3688 ** that control arcs are obscure and I could not figure out what they
b62f651… stephan 3689 ** mean based on available documentation. (2) Arcs are rarely used,
b62f651… stephan 3690 ** and so do not seem that important.
b62f651… stephan 3691 */
f78e48f… drh 3692 static PPoint arcControlPoint(int cw, PPoint f, PPoint t){
b62f651… stephan 3693 PPoint m;
b62f651… stephan 3694 PNum dx, dy;
f78e48f… drh 3695 m.x = 0.5*(f.x+t.x);
f78e48f… drh 3696 m.y = 0.5*(f.y+t.y);
b62f651… stephan 3697 dx = t.x - f.x;
b62f651… stephan 3698 dy = t.y - f.y;
b62f651… stephan 3699 if( cw ){
f78e48f… drh 3700 m.x -= 0.5*dy;
f78e48f… drh 3701 m.y += 0.5*dx;
b62f651… stephan 3702 }else{
f78e48f… drh 3703 m.x += 0.5*dy;
f78e48f… drh 3704 m.y -= 0.5*dx;
b62f651… stephan 3705 }
b62f651… stephan 3706 return m;
b62f651… stephan 3707 }
b62f651… stephan 3708 static void arcCheck(Pik *p, PObj *pObj){
f78e48f… drh 3709 PPoint f, m, t;
f78e48f… drh 3710 PNum sw;
f78e48f… drh 3711 int i;
b62f651… stephan 3712 if( p->nTPath>2 ){
b62f651… stephan 3713 pik_error(p, &pObj->errTok, "arc geometry error");
b62f651… stephan 3714 return;
b62f651… stephan 3715 }
f78e48f… drh 3716 f = p->aTPath[0];
f78e48f… drh 3717 t = p->aTPath[1];
f78e48f… drh 3718 m = arcControlPoint(pObj->cw, f, t);
f78e48f… drh 3719 sw = pObj->sw;
f78e48f… drh 3720 for(i=1; i<16; i++){
f78e48f… drh 3721 PNum t1, t2, a, b, c, x, y;
f78e48f… drh 3722 t1 = 0.0625*i;
f78e48f… drh 3723 t2 = 1.0 - t1;
f78e48f… drh 3724 a = t2*t2;
f78e48f… drh 3725 b = 2*t1*t2;
f78e48f… drh 3726 c = t1*t1;
f78e48f… drh 3727 x = a*f.x + b*m.x + c*t.x;
f78e48f… drh 3728 y = a*f.y + b*m.y + c*t.y;
f78e48f… drh 3729 pik_bbox_addellipse(&pObj->bbox, x, y, sw, sw);
f78e48f… drh 3730 }
b62f651… stephan 3731 }
b62f651… stephan 3732 static void arcRender(Pik *p, PObj *pObj){
b62f651… stephan 3733 PPoint f, m, t;
b62f651… stephan 3734 if( pObj->nPath<2 ) return;
8ed25a3… drh 3735 if( pObj->sw<0.0 ) return;
b62f651… stephan 3736 f = pObj->aPath[0];
b62f651… stephan 3737 t = pObj->aPath[1];
f78e48f… drh 3738 m = arcControlPoint(pObj->cw,f,t);
b62f651… stephan 3739 if( pObj->larrow ){
b62f651… stephan 3740 pik_draw_arrowhead(p,&m,&f,pObj);
b62f651… stephan 3741 }
b62f651… stephan 3742 if( pObj->rarrow ){
b62f651… stephan 3743 pik_draw_arrowhead(p,&m,&t,pObj);
b62f651… stephan 3744 }
b62f651… stephan 3745 pik_append_xy(p,"<path d=\"M", f.x, f.y);
b62f651… stephan 3746 pik_append_xy(p,"Q", m.x, m.y);
b62f651… stephan 3747 pik_append_xy(p," ", t.x, t.y);
b62f651… stephan 3748 pik_append(p,"\" ",2);
b62f651… stephan 3749 pik_append_style(p,pObj,0);
b62f651… stephan 3750 pik_append(p,"\" />\n", -1);
b62f651… stephan 3751
b62f651… stephan 3752 pik_append_txt(p, pObj, 0);
b62f651… stephan 3753 }
b62f651… stephan 3754
b62f651… stephan 3755
b62f651… stephan 3756 /* Methods for the "arrow" class */
b62f651… stephan 3757 static void arrowInit(Pik *p, PObj *pObj){
b62f651… stephan 3758 pObj->w = pik_value(p, "linewid",7,0);
b62f651… stephan 3759 pObj->h = pik_value(p, "lineht",6,0);
b62f651… stephan 3760 pObj->rad = pik_value(p, "linerad",7,0);
b62f651… stephan 3761 pObj->rarrow = 1;
b62f651… stephan 3762 }
b62f651… stephan 3763
b62f651… stephan 3764 /* Methods for the "box" class */
b62f651… stephan 3765 static void boxInit(Pik *p, PObj *pObj){
b62f651… stephan 3766 pObj->w = pik_value(p, "boxwid",6,0);
b62f651… stephan 3767 pObj->h = pik_value(p, "boxht",5,0);
b62f651… stephan 3768 pObj->rad = pik_value(p, "boxrad",6,0);
b62f651… stephan 3769 }
b62f651… stephan 3770 /* Return offset from the center of the box to the compass point
b62f651… stephan 3771 ** given by parameter cp */
b62f651… stephan 3772 static PPoint boxOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 3773 PPoint pt = cZeroPoint;
b62f651… stephan 3774 PNum w2 = 0.5*pObj->w;
b62f651… stephan 3775 PNum h2 = 0.5*pObj->h;
b62f651… stephan 3776 PNum rad = pObj->rad;
b62f651… stephan 3777 PNum rx;
b62f651… stephan 3778 if( rad<=0.0 ){
b62f651… stephan 3779 rx = 0.0;
b62f651… stephan 3780 }else{
b62f651… stephan 3781 if( rad>w2 ) rad = w2;
b62f651… stephan 3782 if( rad>h2 ) rad = h2;
b62f651… stephan 3783 rx = 0.29289321881345252392*rad;
b62f651… stephan 3784 }
b62f651… stephan 3785 switch( cp ){
b62f651… stephan 3786 case CP_C: break;
b62f651… stephan 3787 case CP_N: pt.x = 0.0; pt.y = h2; break;
b62f651… stephan 3788 case CP_NE: pt.x = w2-rx; pt.y = h2-rx; break;
b62f651… stephan 3789 case CP_E: pt.x = w2; pt.y = 0.0; break;
b62f651… stephan 3790 case CP_SE: pt.x = w2-rx; pt.y = rx-h2; break;
b62f651… stephan 3791 case CP_S: pt.x = 0.0; pt.y = -h2; break;
b62f651… stephan 3792 case CP_SW: pt.x = rx-w2; pt.y = rx-h2; break;
b62f651… stephan 3793 case CP_W: pt.x = -w2; pt.y = 0.0; break;
b62f651… stephan 3794 case CP_NW: pt.x = rx-w2; pt.y = h2-rx; break;
b62f651… stephan 3795 default: assert(0);
b62f651… stephan 3796 }
b62f651… stephan 3797 UNUSED_PARAMETER(p);
b62f651… stephan 3798 return pt;
b62f651… stephan 3799 }
b62f651… stephan 3800 static PPoint boxChop(Pik *p, PObj *pObj, PPoint *pPt){
b62f651… stephan 3801 PNum dx, dy;
b62f651… stephan 3802 int cp = CP_C;
b62f651… stephan 3803 PPoint chop = pObj->ptAt;
b62f651… stephan 3804 if( pObj->w<=0.0 ) return chop;
b62f651… stephan 3805 if( pObj->h<=0.0 ) return chop;
b62f651… stephan 3806 dx = (pPt->x - pObj->ptAt.x)*pObj->h/pObj->w;
b62f651… stephan 3807 dy = (pPt->y - pObj->ptAt.y);
b62f651… stephan 3808 if( dx>0.0 ){
b62f651… stephan 3809 if( dy>=2.414*dx ){
b62f651… stephan 3810 cp = CP_N;
b62f651… stephan 3811 }else if( dy>=0.414*dx ){
b62f651… stephan 3812 cp = CP_NE;
b62f651… stephan 3813 }else if( dy>=-0.414*dx ){
b62f651… stephan 3814 cp = CP_E;
b62f651… stephan 3815 }else if( dy>-2.414*dx ){
b62f651… stephan 3816 cp = CP_SE;
b62f651… stephan 3817 }else{
b62f651… stephan 3818 cp = CP_S;
b62f651… stephan 3819 }
b62f651… stephan 3820 }else{
b62f651… stephan 3821 if( dy>=-2.414*dx ){
b62f651… stephan 3822 cp = CP_N;
b62f651… stephan 3823 }else if( dy>=-0.414*dx ){
b62f651… stephan 3824 cp = CP_NW;
b62f651… stephan 3825 }else if( dy>=0.414*dx ){
b62f651… stephan 3826 cp = CP_W;
b62f651… stephan 3827 }else if( dy>2.414*dx ){
b62f651… stephan 3828 cp = CP_SW;
b62f651… stephan 3829 }else{
b62f651… stephan 3830 cp = CP_S;
b62f651… stephan 3831 }
b62f651… stephan 3832 }
b62f651… stephan 3833 chop = pObj->type->xOffset(p,pObj,cp);
b62f651… stephan 3834 chop.x += pObj->ptAt.x;
b62f651… stephan 3835 chop.y += pObj->ptAt.y;
b62f651… stephan 3836 return chop;
b62f651… stephan 3837 }
b62f651… stephan 3838 static void boxFit(Pik *p, PObj *pObj, PNum w, PNum h){
b62f651… stephan 3839 if( w>0 ) pObj->w = w;
b62f651… stephan 3840 if( h>0 ) pObj->h = h;
b62f651… stephan 3841 UNUSED_PARAMETER(p);
b62f651… stephan 3842 }
b62f651… stephan 3843 static void boxRender(Pik *p, PObj *pObj){
b62f651… stephan 3844 PNum w2 = 0.5*pObj->w;
b62f651… stephan 3845 PNum h2 = 0.5*pObj->h;
b62f651… stephan 3846 PNum rad = pObj->rad;
b62f651… stephan 3847 PPoint pt = pObj->ptAt;
8ed25a3… drh 3848 if( pObj->sw>=0.0 ){
b62f651… stephan 3849 if( rad<=0.0 ){
b62f651… stephan 3850 pik_append_xy(p,"<path d=\"M", pt.x-w2,pt.y-h2);
b62f651… stephan 3851 pik_append_xy(p,"L", pt.x+w2,pt.y-h2);
b62f651… stephan 3852 pik_append_xy(p,"L", pt.x+w2,pt.y+h2);
b62f651… stephan 3853 pik_append_xy(p,"L", pt.x-w2,pt.y+h2);
b62f651… stephan 3854 pik_append(p,"Z\" ",-1);
b62f651… stephan 3855 }else{
b62f651… stephan 3856 /*
b62f651… stephan 3857 ** ---- - y3
b62f651… stephan 3858 ** / \
b62f651… stephan 3859 ** / \ _ y2
b62f651… stephan 3860 ** | |
b62f651… stephan 3861 ** | | _ y1
b62f651… stephan 3862 ** \ /
b62f651… stephan 3863 ** \ /
b62f651… stephan 3864 ** ---- _ y0
b62f651… stephan 3865 **
b62f651… stephan 3866 ** ' ' ' '
b62f651… stephan 3867 ** x0 x1 x2 x3
b62f651… stephan 3868 */
b62f651… stephan 3869 PNum x0,x1,x2,x3,y0,y1,y2,y3;
b62f651… stephan 3870 if( rad>w2 ) rad = w2;
b62f651… stephan 3871 if( rad>h2 ) rad = h2;
b62f651… stephan 3872 x0 = pt.x - w2;
b62f651… stephan 3873 x1 = x0 + rad;
b62f651… stephan 3874 x3 = pt.x + w2;
b62f651… stephan 3875 x2 = x3 - rad;
b62f651… stephan 3876 y0 = pt.y - h2;
b62f651… stephan 3877 y1 = y0 + rad;
b62f651… stephan 3878 y3 = pt.y + h2;
b62f651… stephan 3879 y2 = y3 - rad;
b62f651… stephan 3880 pik_append_xy(p,"<path d=\"M", x1, y0);
b62f651… stephan 3881 if( x2>x1 ) pik_append_xy(p, "L", x2, y0);
b62f651… stephan 3882 pik_append_arc(p, rad, rad, x3, y1);
b62f651… stephan 3883 if( y2>y1 ) pik_append_xy(p, "L", x3, y2);
b62f651… stephan 3884 pik_append_arc(p, rad, rad, x2, y3);
b62f651… stephan 3885 if( x2>x1 ) pik_append_xy(p, "L", x1, y3);
b62f651… stephan 3886 pik_append_arc(p, rad, rad, x0, y2);
b62f651… stephan 3887 if( y2>y1 ) pik_append_xy(p, "L", x0, y1);
b62f651… stephan 3888 pik_append_arc(p, rad, rad, x1, y0);
b62f651… stephan 3889 pik_append(p,"Z\" ",-1);
b62f651… stephan 3890 }
b62f651… stephan 3891 pik_append_style(p,pObj,3);
b62f651… stephan 3892 pik_append(p,"\" />\n", -1);
b62f651… stephan 3893 }
b62f651… stephan 3894 pik_append_txt(p, pObj, 0);
b62f651… stephan 3895 }
b62f651… stephan 3896
b62f651… stephan 3897 /* Methods for the "circle" class */
b62f651… stephan 3898 static void circleInit(Pik *p, PObj *pObj){
b62f651… stephan 3899 pObj->w = pik_value(p, "circlerad",9,0)*2;
b62f651… stephan 3900 pObj->h = pObj->w;
b62f651… stephan 3901 pObj->rad = 0.5*pObj->w;
b62f651… stephan 3902 }
b62f651… stephan 3903 static void circleNumProp(Pik *p, PObj *pObj, PToken *pId){
b62f651… stephan 3904 /* For a circle, the width must equal the height and both must
b62f651… stephan 3905 ** be twice the radius. Enforce those constraints. */
b62f651… stephan 3906 switch( pId->eType ){
287d13f… drh 3907 case T_DIAMETER:
b62f651… stephan 3908 case T_RADIUS:
b62f651… stephan 3909 pObj->w = pObj->h = 2.0*pObj->rad;
b62f651… stephan 3910 break;
b62f651… stephan 3911 case T_WIDTH:
b62f651… stephan 3912 pObj->h = pObj->w;
b62f651… stephan 3913 pObj->rad = 0.5*pObj->w;
b62f651… stephan 3914 break;
b62f651… stephan 3915 case T_HEIGHT:
b62f651… stephan 3916 pObj->w = pObj->h;
b62f651… stephan 3917 pObj->rad = 0.5*pObj->w;
b62f651… stephan 3918 break;
b62f651… stephan 3919 }
b62f651… stephan 3920 UNUSED_PARAMETER(p);
b62f651… stephan 3921 }
b62f651… stephan 3922 static PPoint circleChop(Pik *p, PObj *pObj, PPoint *pPt){
b62f651… stephan 3923 PPoint chop;
b62f651… stephan 3924 PNum dx = pPt->x - pObj->ptAt.x;
b62f651… stephan 3925 PNum dy = pPt->y - pObj->ptAt.y;
b62f651… stephan 3926 PNum dist = hypot(dx,dy);
b62f651… stephan 3927 if( dist<pObj->rad || dist<=0 ) return pObj->ptAt;
b62f651… stephan 3928 chop.x = pObj->ptAt.x + dx*pObj->rad/dist;
b62f651… stephan 3929 chop.y = pObj->ptAt.y + dy*pObj->rad/dist;
b62f651… stephan 3930 UNUSED_PARAMETER(p);
b62f651… stephan 3931 return chop;
b62f651… stephan 3932 }
b62f651… stephan 3933 static void circleFit(Pik *p, PObj *pObj, PNum w, PNum h){
b62f651… stephan 3934 PNum mx = 0.0;
b62f651… stephan 3935 if( w>0 ) mx = w;
b62f651… stephan 3936 if( h>mx ) mx = h;
b62f651… stephan 3937 if( w*h>0 && (w*w + h*h) > mx*mx ){
b62f651… stephan 3938 mx = hypot(w,h);
b62f651… stephan 3939 }
b62f651… stephan 3940 if( mx>0.0 ){
b62f651… stephan 3941 pObj->rad = 0.5*mx;
b62f651… stephan 3942 pObj->w = pObj->h = mx;
b62f651… stephan 3943 }
b62f651… stephan 3944 UNUSED_PARAMETER(p);
b62f651… stephan 3945 }
b62f651… stephan 3946
b62f651… stephan 3947 static void circleRender(Pik *p, PObj *pObj){
b62f651… stephan 3948 PNum r = pObj->rad;
b62f651… stephan 3949 PPoint pt = pObj->ptAt;
8ed25a3… drh 3950 if( pObj->sw>=0.0 ){
b62f651… stephan 3951 pik_append_x(p,"<circle cx=\"", pt.x, "\"");
b62f651… stephan 3952 pik_append_y(p," cy=\"", pt.y, "\"");
b62f651… stephan 3953 pik_append_dis(p," r=\"", r, "\" ");
b62f651… stephan 3954 pik_append_style(p,pObj,3);
b62f651… stephan 3955 pik_append(p,"\" />\n", -1);
b62f651… stephan 3956 }
b62f651… stephan 3957 pik_append_txt(p, pObj, 0);
b62f651… stephan 3958 }
b62f651… stephan 3959
b62f651… stephan 3960 /* Methods for the "cylinder" class */
b62f651… stephan 3961 static void cylinderInit(Pik *p, PObj *pObj){
b62f651… stephan 3962 pObj->w = pik_value(p, "cylwid",6,0);
b62f651… stephan 3963 pObj->h = pik_value(p, "cylht",5,0);
b62f651… stephan 3964 pObj->rad = pik_value(p, "cylrad",6,0); /* Minor radius of ellipses */
b62f651… stephan 3965 }
b62f651… stephan 3966 static void cylinderFit(Pik *p, PObj *pObj, PNum w, PNum h){
b62f651… stephan 3967 if( w>0 ) pObj->w = w;
b62f651… stephan 3968 if( h>0 ) pObj->h = h + 0.25*pObj->rad + pObj->sw;
b62f651… stephan 3969 UNUSED_PARAMETER(p);
b62f651… stephan 3970 }
b62f651… stephan 3971 static void cylinderRender(Pik *p, PObj *pObj){
b62f651… stephan 3972 PNum w2 = 0.5*pObj->w;
b62f651… stephan 3973 PNum h2 = 0.5*pObj->h;
b62f651… stephan 3974 PNum rad = pObj->rad;
b62f651… stephan 3975 PPoint pt = pObj->ptAt;
8ed25a3… drh 3976 if( pObj->sw>=0.0 ){
b62f651… stephan 3977 if( rad>h2 ){
b62f651… stephan 3978 rad = h2;
b62f651… stephan 3979 }else if( rad<0 ){
b62f651… stephan 3980 rad = 0;
b62f651… stephan 3981 }
b62f651… stephan 3982 pik_append_xy(p,"<path d=\"M", pt.x-w2,pt.y+h2-rad);
b62f651… stephan 3983 pik_append_xy(p,"L", pt.x-w2,pt.y-h2+rad);
b62f651… stephan 3984 pik_append_arc(p,w2,rad,pt.x+w2,pt.y-h2+rad);
b62f651… stephan 3985 pik_append_xy(p,"L", pt.x+w2,pt.y+h2-rad);
b62f651… stephan 3986 pik_append_arc(p,w2,rad,pt.x-w2,pt.y+h2-rad);
b62f651… stephan 3987 pik_append_arc(p,w2,rad,pt.x+w2,pt.y+h2-rad);
b62f651… stephan 3988 pik_append(p,"\" ",-1);
b62f651… stephan 3989 pik_append_style(p,pObj,3);
b62f651… stephan 3990 pik_append(p,"\" />\n", -1);
b62f651… stephan 3991 }
b62f651… stephan 3992 pik_append_txt(p, pObj, 0);
b62f651… stephan 3993 }
b62f651… stephan 3994 static PPoint cylinderOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 3995 PPoint pt = cZeroPoint;
b62f651… stephan 3996 PNum w2 = pObj->w*0.5;
b62f651… stephan 3997 PNum h1 = pObj->h*0.5;
b62f651… stephan 3998 PNum h2 = h1 - pObj->rad;
b62f651… stephan 3999 switch( cp ){
b62f651… stephan 4000 case CP_C: break;
b62f651… stephan 4001 case CP_N: pt.x = 0.0; pt.y = h1; break;
b62f651… stephan 4002 case CP_NE: pt.x = w2; pt.y = h2; break;
b62f651… stephan 4003 case CP_E: pt.x = w2; pt.y = 0.0; break;
b62f651… stephan 4004 case CP_SE: pt.x = w2; pt.y = -h2; break;
b62f651… stephan 4005 case CP_S: pt.x = 0.0; pt.y = -h1; break;
b62f651… stephan 4006 case CP_SW: pt.x = -w2; pt.y = -h2; break;
b62f651… stephan 4007 case CP_W: pt.x = -w2; pt.y = 0.0; break;
b62f651… stephan 4008 case CP_NW: pt.x = -w2; pt.y = h2; break;
b62f651… stephan 4009 default: assert(0);
b62f651… stephan 4010 }
b62f651… stephan 4011 UNUSED_PARAMETER(p);
b62f651… stephan 4012 return pt;
b62f651… stephan 4013 }
b62f651… stephan 4014
b62f651… stephan 4015 /* Methods for the "dot" class */
b62f651… stephan 4016 static void dotInit(Pik *p, PObj *pObj){
b62f651… stephan 4017 pObj->rad = pik_value(p, "dotrad",6,0);
b62f651… stephan 4018 pObj->h = pObj->w = pObj->rad*6;
b62f651… stephan 4019 pObj->fill = pObj->color;
b62f651… stephan 4020 }
b62f651… stephan 4021 static void dotNumProp(Pik *p, PObj *pObj, PToken *pId){
b62f651… stephan 4022 switch( pId->eType ){
b62f651… stephan 4023 case T_COLOR:
b62f651… stephan 4024 pObj->fill = pObj->color;
b62f651… stephan 4025 break;
b62f651… stephan 4026 case T_FILL:
b62f651… stephan 4027 pObj->color = pObj->fill;
b62f651… stephan 4028 break;
b62f651… stephan 4029 }
b62f651… stephan 4030 UNUSED_PARAMETER(p);
b62f651… stephan 4031 }
b62f651… stephan 4032 static void dotCheck(Pik *p, PObj *pObj){
b62f651… stephan 4033 pObj->w = pObj->h = 0;
b62f651… stephan 4034 pik_bbox_addellipse(&pObj->bbox, pObj->ptAt.x, pObj->ptAt.y,
b62f651… stephan 4035 pObj->rad, pObj->rad);
b62f651… stephan 4036 UNUSED_PARAMETER(p);
b62f651… stephan 4037 }
b62f651… stephan 4038 static PPoint dotOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4039 UNUSED_PARAMETER(p);
b62f651… stephan 4040 UNUSED_PARAMETER(pObj);
b62f651… stephan 4041 UNUSED_PARAMETER(cp);
b62f651… stephan 4042 return cZeroPoint;
b62f651… stephan 4043 }
b62f651… stephan 4044 static void dotRender(Pik *p, PObj *pObj){
b62f651… stephan 4045 PNum r = pObj->rad;
b62f651… stephan 4046 PPoint pt = pObj->ptAt;
8ed25a3… drh 4047 if( pObj->sw>=0.0 ){
b62f651… stephan 4048 pik_append_x(p,"<circle cx=\"", pt.x, "\"");
b62f651… stephan 4049 pik_append_y(p," cy=\"", pt.y, "\"");
b62f651… stephan 4050 pik_append_dis(p," r=\"", r, "\"");
b62f651… stephan 4051 pik_append_style(p,pObj,2);
b62f651… stephan 4052 pik_append(p,"\" />\n", -1);
b62f651… stephan 4053 }
b62f651… stephan 4054 pik_append_txt(p, pObj, 0);
b62f651… stephan 4055 }
b62f651… stephan 4056
7573b3f… drh 4057 /* Methods for the "diamond" class */
7573b3f… drh 4058 static void diamondInit(Pik *p, PObj *pObj){
7573b3f… drh 4059 pObj->w = pik_value(p, "diamondwid",10,0);
7573b3f… drh 4060 pObj->h = pik_value(p, "diamondht",9,0);
f4ec8e0… drh 4061 pObj->bAltAutoFit = 1;
7573b3f… drh 4062 }
7573b3f… drh 4063 /* Return offset from the center of the box to the compass point
7573b3f… drh 4064 ** given by parameter cp */
7573b3f… drh 4065 static PPoint diamondOffset(Pik *p, PObj *pObj, int cp){
7573b3f… drh 4066 PPoint pt = cZeroPoint;
7573b3f… drh 4067 PNum w2 = 0.5*pObj->w;
7573b3f… drh 4068 PNum w4 = 0.25*pObj->w;
7573b3f… drh 4069 PNum h2 = 0.5*pObj->h;
7573b3f… drh 4070 PNum h4 = 0.25*pObj->h;
7573b3f… drh 4071 switch( cp ){
7573b3f… drh 4072 case CP_C: break;
7573b3f… drh 4073 case CP_N: pt.x = 0.0; pt.y = h2; break;
7573b3f… drh 4074 case CP_NE: pt.x = w4; pt.y = h4; break;
7573b3f… drh 4075 case CP_E: pt.x = w2; pt.y = 0.0; break;
7573b3f… drh 4076 case CP_SE: pt.x = w4; pt.y = -h4; break;
7573b3f… drh 4077 case CP_S: pt.x = 0.0; pt.y = -h2; break;
7573b3f… drh 4078 case CP_SW: pt.x = -w4; pt.y = -h4; break;
7573b3f… drh 4079 case CP_W: pt.x = -w2; pt.y = 0.0; break;
7573b3f… drh 4080 case CP_NW: pt.x = -w4; pt.y = h4; break;
7573b3f… drh 4081 default: assert(0);
7573b3f… drh 4082 }
7573b3f… drh 4083 UNUSED_PARAMETER(p);
7573b3f… drh 4084 return pt;
7573b3f… drh 4085 }
7573b3f… drh 4086 static void diamondFit(Pik *p, PObj *pObj, PNum w, PNum h){
f4ec8e0… drh 4087 if( pObj->w<=0 ) pObj->w = w*1.5;
f4ec8e0… drh 4088 if( pObj->h<=0 ) pObj->h = h*1.5;
7573b3f… drh 4089 if( pObj->w>0 && pObj->h>0 ){
7573b3f… drh 4090 PNum x = pObj->w*h/pObj->h + w;
7573b3f… drh 4091 PNum y = pObj->h*x/pObj->w;
7573b3f… drh 4092 pObj->w = x;
7573b3f… drh 4093 pObj->h = y;
7573b3f… drh 4094 }
7573b3f… drh 4095 UNUSED_PARAMETER(p);
7573b3f… drh 4096 }
7573b3f… drh 4097 static void diamondRender(Pik *p, PObj *pObj){
7573b3f… drh 4098 PNum w2 = 0.5*pObj->w;
7573b3f… drh 4099 PNum h2 = 0.5*pObj->h;
7573b3f… drh 4100 PPoint pt = pObj->ptAt;
7573b3f… drh 4101 if( pObj->sw>=0.0 ){
7573b3f… drh 4102 pik_append_xy(p,"<path d=\"M", pt.x-w2,pt.y);
7573b3f… drh 4103 pik_append_xy(p,"L", pt.x,pt.y-h2);
7573b3f… drh 4104 pik_append_xy(p,"L", pt.x+w2,pt.y);
7573b3f… drh 4105 pik_append_xy(p,"L", pt.x,pt.y+h2);
7573b3f… drh 4106 pik_append(p,"Z\" ",-1);
7573b3f… drh 4107 pik_append_style(p,pObj,3);
7573b3f… drh 4108 pik_append(p,"\" />\n", -1);
7573b3f… drh 4109 }
7573b3f… drh 4110 pik_append_txt(p, pObj, 0);
7573b3f… drh 4111 }
b62f651… stephan 4112
b62f651… stephan 4113
b62f651… stephan 4114 /* Methods for the "ellipse" class */
b62f651… stephan 4115 static void ellipseInit(Pik *p, PObj *pObj){
b62f651… stephan 4116 pObj->w = pik_value(p, "ellipsewid",10,0);
b62f651… stephan 4117 pObj->h = pik_value(p, "ellipseht",9,0);
b62f651… stephan 4118 }
b62f651… stephan 4119 static PPoint ellipseChop(Pik *p, PObj *pObj, PPoint *pPt){
b62f651… stephan 4120 PPoint chop;
b62f651… stephan 4121 PNum s, dq, dist;
b62f651… stephan 4122 PNum dx = pPt->x - pObj->ptAt.x;
b62f651… stephan 4123 PNum dy = pPt->y - pObj->ptAt.y;
b62f651… stephan 4124 if( pObj->w<=0.0 ) return pObj->ptAt;
b62f651… stephan 4125 if( pObj->h<=0.0 ) return pObj->ptAt;
b62f651… stephan 4126 s = pObj->h/pObj->w;
b62f651… stephan 4127 dq = dx*s;
b62f651… stephan 4128 dist = hypot(dq,dy);
b62f651… stephan 4129 if( dist<pObj->h ) return pObj->ptAt;
b62f651… stephan 4130 chop.x = pObj->ptAt.x + 0.5*dq*pObj->h/(dist*s);
b62f651… stephan 4131 chop.y = pObj->ptAt.y + 0.5*dy*pObj->h/dist;
b62f651… stephan 4132 UNUSED_PARAMETER(p);
b62f651… stephan 4133 return chop;
b62f651… stephan 4134 }
b62f651… stephan 4135 static PPoint ellipseOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4136 PPoint pt = cZeroPoint;
b62f651… stephan 4137 PNum w = pObj->w*0.5;
b62f651… stephan 4138 PNum w2 = w*0.70710678118654747608;
b62f651… stephan 4139 PNum h = pObj->h*0.5;
b62f651… stephan 4140 PNum h2 = h*0.70710678118654747608;
b62f651… stephan 4141 switch( cp ){
b62f651… stephan 4142 case CP_C: break;
b62f651… stephan 4143 case CP_N: pt.x = 0.0; pt.y = h; break;
b62f651… stephan 4144 case CP_NE: pt.x = w2; pt.y = h2; break;
b62f651… stephan 4145 case CP_E: pt.x = w; pt.y = 0.0; break;
b62f651… stephan 4146 case CP_SE: pt.x = w2; pt.y = -h2; break;
b62f651… stephan 4147 case CP_S: pt.x = 0.0; pt.y = -h; break;
b62f651… stephan 4148 case CP_SW: pt.x = -w2; pt.y = -h2; break;
b62f651… stephan 4149 case CP_W: pt.x = -w; pt.y = 0.0; break;
b62f651… stephan 4150 case CP_NW: pt.x = -w2; pt.y = h2; break;
b62f651… stephan 4151 default: assert(0);
b62f651… stephan 4152 }
b62f651… stephan 4153 UNUSED_PARAMETER(p);
b62f651… stephan 4154 return pt;
b62f651… stephan 4155 }
b62f651… stephan 4156 static void ellipseRender(Pik *p, PObj *pObj){
b62f651… stephan 4157 PNum w = pObj->w;
b62f651… stephan 4158 PNum h = pObj->h;
b62f651… stephan 4159 PPoint pt = pObj->ptAt;
8ed25a3… drh 4160 if( pObj->sw>=0.0 ){
b62f651… stephan 4161 pik_append_x(p,"<ellipse cx=\"", pt.x, "\"");
b62f651… stephan 4162 pik_append_y(p," cy=\"", pt.y, "\"");
b62f651… stephan 4163 pik_append_dis(p," rx=\"", w/2.0, "\"");
b62f651… stephan 4164 pik_append_dis(p," ry=\"", h/2.0, "\" ");
b62f651… stephan 4165 pik_append_style(p,pObj,3);
b62f651… stephan 4166 pik_append(p,"\" />\n", -1);
b62f651… stephan 4167 }
b62f651… stephan 4168 pik_append_txt(p, pObj, 0);
b62f651… stephan 4169 }
b62f651… stephan 4170
b62f651… stephan 4171 /* Methods for the "file" object */
b62f651… stephan 4172 static void fileInit(Pik *p, PObj *pObj){
b62f651… stephan 4173 pObj->w = pik_value(p, "filewid",7,0);
b62f651… stephan 4174 pObj->h = pik_value(p, "fileht",6,0);
b62f651… stephan 4175 pObj->rad = pik_value(p, "filerad",7,0);
b62f651… stephan 4176 }
b62f651… stephan 4177 /* Return offset from the center of the file to the compass point
b62f651… stephan 4178 ** given by parameter cp */
b62f651… stephan 4179 static PPoint fileOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4180 PPoint pt = cZeroPoint;
b62f651… stephan 4181 PNum w2 = 0.5*pObj->w;
b62f651… stephan 4182 PNum h2 = 0.5*pObj->h;
b62f651… stephan 4183 PNum rx = pObj->rad;
b62f651… stephan 4184 PNum mn = w2<h2 ? w2 : h2;
b62f651… stephan 4185 if( rx>mn ) rx = mn;
b62f651… stephan 4186 if( rx<mn*0.25 ) rx = mn*0.25;
b62f651… stephan 4187 pt.x = pt.y = 0.0;
b62f651… stephan 4188 rx *= 0.5;
b62f651… stephan 4189 switch( cp ){
b62f651… stephan 4190 case CP_C: break;
b62f651… stephan 4191 case CP_N: pt.x = 0.0; pt.y = h2; break;
b62f651… stephan 4192 case CP_NE: pt.x = w2-rx; pt.y = h2-rx; break;
b62f651… stephan 4193 case CP_E: pt.x = w2; pt.y = 0.0; break;
b62f651… stephan 4194 case CP_SE: pt.x = w2; pt.y = -h2; break;
b62f651… stephan 4195 case CP_S: pt.x = 0.0; pt.y = -h2; break;
b62f651… stephan 4196 case CP_SW: pt.x = -w2; pt.y = -h2; break;
b62f651… stephan 4197 case CP_W: pt.x = -w2; pt.y = 0.0; break;
b62f651… stephan 4198 case CP_NW: pt.x = -w2; pt.y = h2; break;
b62f651… stephan 4199 default: assert(0);
b62f651… stephan 4200 }
b62f651… stephan 4201 UNUSED_PARAMETER(p);
b62f651… stephan 4202 return pt;
b62f651… stephan 4203 }
b62f651… stephan 4204 static void fileFit(Pik *p, PObj *pObj, PNum w, PNum h){
b62f651… stephan 4205 if( w>0 ) pObj->w = w;
b62f651… stephan 4206 if( h>0 ) pObj->h = h + 2*pObj->rad;
b62f651… stephan 4207 UNUSED_PARAMETER(p);
b62f651… stephan 4208 }
b62f651… stephan 4209 static void fileRender(Pik *p, PObj *pObj){
b62f651… stephan 4210 PNum w2 = 0.5*pObj->w;
b62f651… stephan 4211 PNum h2 = 0.5*pObj->h;
b62f651… stephan 4212 PNum rad = pObj->rad;
b62f651… stephan 4213 PPoint pt = pObj->ptAt;
b62f651… stephan 4214 PNum mn = w2<h2 ? w2 : h2;
b62f651… stephan 4215 if( rad>mn ) rad = mn;
b62f651… stephan 4216 if( rad<mn*0.25 ) rad = mn*0.25;
8ed25a3… drh 4217 if( pObj->sw>=0.0 ){
b62f651… stephan 4218 pik_append_xy(p,"<path d=\"M", pt.x-w2,pt.y-h2);
b62f651… stephan 4219 pik_append_xy(p,"L", pt.x+w2,pt.y-h2);
b62f651… stephan 4220 pik_append_xy(p,"L", pt.x+w2,pt.y+(h2-rad));
b62f651… stephan 4221 pik_append_xy(p,"L", pt.x+(w2-rad),pt.y+h2);
b62f651… stephan 4222 pik_append_xy(p,"L", pt.x-w2,pt.y+h2);
b62f651… stephan 4223 pik_append(p,"Z\" ",-1);
b62f651… stephan 4224 pik_append_style(p,pObj,1);
b62f651… stephan 4225 pik_append(p,"\" />\n",-1);
b62f651… stephan 4226 pik_append_xy(p,"<path d=\"M", pt.x+(w2-rad), pt.y+h2);
b62f651… stephan 4227 pik_append_xy(p,"L", pt.x+(w2-rad),pt.y+(h2-rad));
b62f651… stephan 4228 pik_append_xy(p,"L", pt.x+w2, pt.y+(h2-rad));
b62f651… stephan 4229 pik_append(p,"\" ",-1);
b62f651… stephan 4230 pik_append_style(p,pObj,0);
b62f651… stephan 4231 pik_append(p,"\" />\n",-1);
b62f651… stephan 4232 }
b62f651… stephan 4233 pik_append_txt(p, pObj, 0);
b62f651… stephan 4234 }
b62f651… stephan 4235
b62f651… stephan 4236
b62f651… stephan 4237 /* Methods for the "line" class */
b62f651… stephan 4238 static void lineInit(Pik *p, PObj *pObj){
b62f651… stephan 4239 pObj->w = pik_value(p, "linewid",7,0);
b62f651… stephan 4240 pObj->h = pik_value(p, "lineht",6,0);
b62f651… stephan 4241 pObj->rad = pik_value(p, "linerad",7,0);
b62f651… stephan 4242 }
b62f651… stephan 4243 static PPoint lineOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4244 #if 0
b62f651… stephan 4245 /* In legacy PIC, the .center of an unclosed line is half way between
b62f651… stephan 4246 ** its .start and .end. */
b62f651… stephan 4247 if( cp==CP_C && !pObj->bClose ){
b62f651… stephan 4248 PPoint out;
b62f651… stephan 4249 out.x = 0.5*(pObj->ptEnter.x + pObj->ptExit.x) - pObj->ptAt.x;
b62f651… stephan 4250 out.y = 0.5*(pObj->ptEnter.x + pObj->ptExit.y) - pObj->ptAt.y;
b62f651… stephan 4251 return out;
b62f651… stephan 4252 }
b62f651… stephan 4253 #endif
b62f651… stephan 4254 return boxOffset(p,pObj,cp);
b62f651… stephan 4255 }
b62f651… stephan 4256 static void lineRender(Pik *p, PObj *pObj){
b62f651… stephan 4257 int i;
b62f651… stephan 4258 if( pObj->sw>0.0 ){
b62f651… stephan 4259 const char *z = "<path d=\"M";
b62f651… stephan 4260 int n = pObj->nPath;
b62f651… stephan 4261 if( pObj->larrow ){
b62f651… stephan 4262 pik_draw_arrowhead(p,&pObj->aPath[1],&pObj->aPath[0],pObj);
b62f651… stephan 4263 }
b62f651… stephan 4264 if( pObj->rarrow ){
b62f651… stephan 4265 pik_draw_arrowhead(p,&pObj->aPath[n-2],&pObj->aPath[n-1],pObj);
b62f651… stephan 4266 }
b62f651… stephan 4267 for(i=0; i<pObj->nPath; i++){
b62f651… stephan 4268 pik_append_xy(p,z,pObj->aPath[i].x,pObj->aPath[i].y);
b62f651… stephan 4269 z = "L";
b62f651… stephan 4270 }
b62f651… stephan 4271 if( pObj->bClose ){
b62f651… stephan 4272 pik_append(p,"Z",1);
b62f651… stephan 4273 }else{
b62f651… stephan 4274 pObj->fill = -1.0;
b62f651… stephan 4275 }
b62f651… stephan 4276 pik_append(p,"\" ",-1);
b62f651… stephan 4277 pik_append_style(p,pObj,pObj->bClose?3:0);
b62f651… stephan 4278 pik_append(p,"\" />\n", -1);
b62f651… stephan 4279 }
b62f651… stephan 4280 pik_append_txt(p, pObj, 0);
b62f651… stephan 4281 }
b62f651… stephan 4282
b62f651… stephan 4283 /* Methods for the "move" class */
b62f651… stephan 4284 static void moveInit(Pik *p, PObj *pObj){
b62f651… stephan 4285 pObj->w = pik_value(p, "movewid",7,0);
b62f651… stephan 4286 pObj->h = pObj->w;
b62f651… stephan 4287 pObj->fill = -1.0;
b62f651… stephan 4288 pObj->color = -1.0;
b62f651… stephan 4289 pObj->sw = -1.0;
b62f651… stephan 4290 }
b62f651… stephan 4291 static void moveRender(Pik *p, PObj *pObj){
b62f651… stephan 4292 /* No-op */
b62f651… stephan 4293 UNUSED_PARAMETER(p);
b62f651… stephan 4294 UNUSED_PARAMETER(pObj);
b62f651… stephan 4295 }
b62f651… stephan 4296
b62f651… stephan 4297 /* Methods for the "oval" class */
b62f651… stephan 4298 static void ovalInit(Pik *p, PObj *pObj){
b62f651… stephan 4299 pObj->h = pik_value(p, "ovalht",6,0);
b62f651… stephan 4300 pObj->w = pik_value(p, "ovalwid",7,0);
b62f651… stephan 4301 pObj->rad = 0.5*(pObj->h<pObj->w?pObj->h:pObj->w);
b62f651… stephan 4302 }
b62f651… stephan 4303 static void ovalNumProp(Pik *p, PObj *pObj, PToken *pId){
b62f651… stephan 4304 UNUSED_PARAMETER(p);
b62f651… stephan 4305 UNUSED_PARAMETER(pId);
b62f651… stephan 4306 /* Always adjust the radius to be half of the smaller of
b62f651… stephan 4307 ** the width and height. */
b62f651… stephan 4308 pObj->rad = 0.5*(pObj->h<pObj->w?pObj->h:pObj->w);
b62f651… stephan 4309 }
b62f651… stephan 4310 static void ovalFit(Pik *p, PObj *pObj, PNum w, PNum h){
b62f651… stephan 4311 UNUSED_PARAMETER(p);
b62f651… stephan 4312 if( w>0 ) pObj->w = w;
b62f651… stephan 4313 if( h>0 ) pObj->h = h;
b62f651… stephan 4314 if( pObj->w<pObj->h ) pObj->w = pObj->h;
b62f651… stephan 4315 pObj->rad = 0.5*(pObj->h<pObj->w?pObj->h:pObj->w);
b62f651… stephan 4316 }
b62f651… stephan 4317
b62f651… stephan 4318
b62f651… stephan 4319
b62f651… stephan 4320 /* Methods for the "spline" class */
b62f651… stephan 4321 static void splineInit(Pik *p, PObj *pObj){
b62f651… stephan 4322 pObj->w = pik_value(p, "linewid",7,0);
b62f651… stephan 4323 pObj->h = pik_value(p, "lineht",6,0);
b62f651… stephan 4324 pObj->rad = 1000;
b62f651… stephan 4325 }
b62f651… stephan 4326 /* Return a point along the path from "f" to "t" that is r units
b62f651… stephan 4327 ** prior to reaching "t", except if the path is less than 2*r total,
b62f651… stephan 4328 ** return the midpoint.
b62f651… stephan 4329 */
b62f651… stephan 4330 static PPoint radiusMidpoint(PPoint f, PPoint t, PNum r, int *pbMid){
b62f651… stephan 4331 PNum dx = t.x - f.x;
b62f651… stephan 4332 PNum dy = t.y - f.y;
b62f651… stephan 4333 PNum dist = hypot(dx,dy);
b62f651… stephan 4334 PPoint m;
b62f651… stephan 4335 if( dist<=0.0 ) return t;
b62f651… stephan 4336 dx /= dist;
b62f651… stephan 4337 dy /= dist;
b62f651… stephan 4338 if( r > 0.5*dist ){
b62f651… stephan 4339 r = 0.5*dist;
b62f651… stephan 4340 *pbMid = 1;
b62f651… stephan 4341 }else{
b62f651… stephan 4342 *pbMid = 0;
b62f651… stephan 4343 }
b62f651… stephan 4344 m.x = t.x - r*dx;
b62f651… stephan 4345 m.y = t.y - r*dy;
b62f651… stephan 4346 return m;
b62f651… stephan 4347 }
b62f651… stephan 4348 static void radiusPath(Pik *p, PObj *pObj, PNum r){
b62f651… stephan 4349 int i;
b62f651… stephan 4350 int n = pObj->nPath;
b62f651… stephan 4351 const PPoint *a = pObj->aPath;
b62f651… stephan 4352 PPoint m;
b62f651… stephan 4353 PPoint an = a[n-1];
b62f651… stephan 4354 int isMid = 0;
b62f651… stephan 4355 int iLast = pObj->bClose ? n : n-1;
b62f651… stephan 4356
b62f651… stephan 4357 pik_append_xy(p,"<path d=\"M", a[0].x, a[0].y);
b62f651… stephan 4358 m = radiusMidpoint(a[0], a[1], r, &isMid);
b62f651… stephan 4359 pik_append_xy(p," L ",m.x,m.y);
b62f651… stephan 4360 for(i=1; i<iLast; i++){
b62f651… stephan 4361 an = i<n-1 ? a[i+1] : a[0];
b62f651… stephan 4362 m = radiusMidpoint(an,a[i],r, &isMid);
b62f651… stephan 4363 pik_append_xy(p," Q ",a[i].x,a[i].y);
b62f651… stephan 4364 pik_append_xy(p," ",m.x,m.y);
b62f651… stephan 4365 if( !isMid ){
b62f651… stephan 4366 m = radiusMidpoint(a[i],an,r, &isMid);
b62f651… stephan 4367 pik_append_xy(p," L ",m.x,m.y);
b62f651… stephan 4368 }
b62f651… stephan 4369 }
b62f651… stephan 4370 pik_append_xy(p," L ",an.x,an.y);
b62f651… stephan 4371 if( pObj->bClose ){
b62f651… stephan 4372 pik_append(p,"Z",1);
b62f651… stephan 4373 }else{
b62f651… stephan 4374 pObj->fill = -1.0;
b62f651… stephan 4375 }
b62f651… stephan 4376 pik_append(p,"\" ",-1);
b62f651… stephan 4377 pik_append_style(p,pObj,pObj->bClose?3:0);
b62f651… stephan 4378 pik_append(p,"\" />\n", -1);
b62f651… stephan 4379 }
b62f651… stephan 4380 static void splineRender(Pik *p, PObj *pObj){
b62f651… stephan 4381 if( pObj->sw>0.0 ){
b62f651… stephan 4382 int n = pObj->nPath;
b62f651… stephan 4383 PNum r = pObj->rad;
b62f651… stephan 4384 if( n<3 || r<=0.0 ){
b62f651… stephan 4385 lineRender(p,pObj);
b62f651… stephan 4386 return;
b62f651… stephan 4387 }
b62f651… stephan 4388 if( pObj->larrow ){
b62f651… stephan 4389 pik_draw_arrowhead(p,&pObj->aPath[1],&pObj->aPath[0],pObj);
b62f651… stephan 4390 }
b62f651… stephan 4391 if( pObj->rarrow ){
b62f651… stephan 4392 pik_draw_arrowhead(p,&pObj->aPath[n-2],&pObj->aPath[n-1],pObj);
b62f651… stephan 4393 }
b62f651… stephan 4394 radiusPath(p,pObj,pObj->rad);
b62f651… stephan 4395 }
b62f651… stephan 4396 pik_append_txt(p, pObj, 0);
b62f651… stephan 4397 }
b62f651… stephan 4398
b62f651… stephan 4399
b62f651… stephan 4400 /* Methods for the "text" class */
b62f651… stephan 4401 static void textInit(Pik *p, PObj *pObj){
b62f651… stephan 4402 pik_value(p, "textwid",7,0);
b62f651… stephan 4403 pik_value(p, "textht",6,0);
b62f651… stephan 4404 pObj->sw = 0.0;
b62f651… stephan 4405 }
b62f651… stephan 4406 static PPoint textOffset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4407 /* Automatically slim-down the width and height of text
b62f651… stephan 4408 ** statements so that the bounding box tightly encloses the text,
b62f651… stephan 4409 ** then get boxOffset() to do the offset computation.
b62f651… stephan 4410 */
c32f97e… drh 4411 pik_size_to_fit(p, pObj, &pObj->errTok,3);
b62f651… stephan 4412 return boxOffset(p, pObj, cp);
b62f651… stephan 4413 }
8ed25a3… drh 4414 static void textRender(Pik *p, PObj *pObj){
8ed25a3… drh 4415 pik_append_txt(p, pObj, 0);
8ed25a3… drh 4416 }
8ed25a3… drh 4417
b62f651… stephan 4418
b62f651… stephan 4419 /* Methods for the "sublist" class */
b62f651… stephan 4420 static void sublistInit(Pik *p, PObj *pObj){
b62f651… stephan 4421 PList *pList = pObj->pSublist;
b62f651… stephan 4422 int i;
b62f651… stephan 4423 UNUSED_PARAMETER(p);
b62f651… stephan 4424 pik_bbox_init(&pObj->bbox);
b62f651… stephan 4425 for(i=0; i<pList->n; i++){
b62f651… stephan 4426 pik_bbox_addbox(&pObj->bbox, &pList->a[i]->bbox);
b62f651… stephan 4427 }
b62f651… stephan 4428 pObj->w = pObj->bbox.ne.x - pObj->bbox.sw.x;
b62f651… stephan 4429 pObj->h = pObj->bbox.ne.y - pObj->bbox.sw.y;
b62f651… stephan 4430 pObj->ptAt.x = 0.5*(pObj->bbox.ne.x + pObj->bbox.sw.x);
b62f651… stephan 4431 pObj->ptAt.y = 0.5*(pObj->bbox.ne.y + pObj->bbox.sw.y);
b62f651… stephan 4432 pObj->mCalc |= A_WIDTH|A_HEIGHT|A_RADIUS;
b62f651… stephan 4433 }
b62f651… stephan 4434
b62f651… stephan 4435
b62f651… stephan 4436 /*
b62f651… stephan 4437 ** The following array holds all the different kinds of objects.
b62f651… stephan 4438 ** The special [] object is separate.
b62f651… stephan 4439 */
b62f651… stephan 4440 static const PClass aClass[] = {
b62f651… stephan 4441 { /* name */ "arc",
b62f651… stephan 4442 /* isline */ 1,
b62f651… stephan 4443 /* eJust */ 0,
b62f651… stephan 4444 /* xInit */ arcInit,
b62f651… stephan 4445 /* xNumProp */ 0,
b62f651… stephan 4446 /* xCheck */ arcCheck,
b62f651… stephan 4447 /* xChop */ 0,
b62f651… stephan 4448 /* xOffset */ boxOffset,
b62f651… stephan 4449 /* xFit */ 0,
b62f651… stephan 4450 /* xRender */ arcRender
b62f651… stephan 4451 },
b62f651… stephan 4452 { /* name */ "arrow",
b62f651… stephan 4453 /* isline */ 1,
b62f651… stephan 4454 /* eJust */ 0,
b62f651… stephan 4455 /* xInit */ arrowInit,
b62f651… stephan 4456 /* xNumProp */ 0,
b62f651… stephan 4457 /* xCheck */ 0,
b62f651… stephan 4458 /* xChop */ 0,
b62f651… stephan 4459 /* xOffset */ lineOffset,
b62f651… stephan 4460 /* xFit */ 0,
b62f651… stephan 4461 /* xRender */ splineRender
b62f651… stephan 4462 },
b62f651… stephan 4463 { /* name */ "box",
b62f651… stephan 4464 /* isline */ 0,
b62f651… stephan 4465 /* eJust */ 1,
b62f651… stephan 4466 /* xInit */ boxInit,
b62f651… stephan 4467 /* xNumProp */ 0,
b62f651… stephan 4468 /* xCheck */ 0,
b62f651… stephan 4469 /* xChop */ boxChop,
b62f651… stephan 4470 /* xOffset */ boxOffset,
b62f651… stephan 4471 /* xFit */ boxFit,
b62f651… stephan 4472 /* xRender */ boxRender
b62f651… stephan 4473 },
b62f651… stephan 4474 { /* name */ "circle",
b62f651… stephan 4475 /* isline */ 0,
b62f651… stephan 4476 /* eJust */ 0,
b62f651… stephan 4477 /* xInit */ circleInit,
b62f651… stephan 4478 /* xNumProp */ circleNumProp,
b62f651… stephan 4479 /* xCheck */ 0,
b62f651… stephan 4480 /* xChop */ circleChop,
b62f651… stephan 4481 /* xOffset */ ellipseOffset,
b62f651… stephan 4482 /* xFit */ circleFit,
b62f651… stephan 4483 /* xRender */ circleRender
b62f651… stephan 4484 },
b62f651… stephan 4485 { /* name */ "cylinder",
b62f651… stephan 4486 /* isline */ 0,
b62f651… stephan 4487 /* eJust */ 1,
b62f651… stephan 4488 /* xInit */ cylinderInit,
b62f651… stephan 4489 /* xNumProp */ 0,
b62f651… stephan 4490 /* xCheck */ 0,
b62f651… stephan 4491 /* xChop */ boxChop,
b62f651… stephan 4492 /* xOffset */ cylinderOffset,
b62f651… stephan 4493 /* xFit */ cylinderFit,
b62f651… stephan 4494 /* xRender */ cylinderRender
7573b3f… drh 4495 },
7573b3f… drh 4496 { /* name */ "diamond",
7573b3f… drh 4497 /* isline */ 0,
7573b3f… drh 4498 /* eJust */ 0,
7573b3f… drh 4499 /* xInit */ diamondInit,
7573b3f… drh 4500 /* xNumProp */ 0,
7573b3f… drh 4501 /* xCheck */ 0,
7573b3f… drh 4502 /* xChop */ boxChop,
7573b3f… drh 4503 /* xOffset */ diamondOffset,
7573b3f… drh 4504 /* xFit */ diamondFit,
7573b3f… drh 4505 /* xRender */ diamondRender
b62f651… stephan 4506 },
b62f651… stephan 4507 { /* name */ "dot",
b62f651… stephan 4508 /* isline */ 0,
b62f651… stephan 4509 /* eJust */ 0,
b62f651… stephan 4510 /* xInit */ dotInit,
b62f651… stephan 4511 /* xNumProp */ dotNumProp,
b62f651… stephan 4512 /* xCheck */ dotCheck,
b62f651… stephan 4513 /* xChop */ circleChop,
b62f651… stephan 4514 /* xOffset */ dotOffset,
b62f651… stephan 4515 /* xFit */ 0,
b62f651… stephan 4516 /* xRender */ dotRender
b62f651… stephan 4517 },
b62f651… stephan 4518 { /* name */ "ellipse",
b62f651… stephan 4519 /* isline */ 0,
b62f651… stephan 4520 /* eJust */ 0,
b62f651… stephan 4521 /* xInit */ ellipseInit,
b62f651… stephan 4522 /* xNumProp */ 0,
b62f651… stephan 4523 /* xCheck */ 0,
b62f651… stephan 4524 /* xChop */ ellipseChop,
b62f651… stephan 4525 /* xOffset */ ellipseOffset,
b62f651… stephan 4526 /* xFit */ boxFit,
b62f651… stephan 4527 /* xRender */ ellipseRender
b62f651… stephan 4528 },
b62f651… stephan 4529 { /* name */ "file",
b62f651… stephan 4530 /* isline */ 0,
b62f651… stephan 4531 /* eJust */ 1,
b62f651… stephan 4532 /* xInit */ fileInit,
b62f651… stephan 4533 /* xNumProp */ 0,
b62f651… stephan 4534 /* xCheck */ 0,
b62f651… stephan 4535 /* xChop */ boxChop,
b62f651… stephan 4536 /* xOffset */ fileOffset,
b62f651… stephan 4537 /* xFit */ fileFit,
b62f651… stephan 4538 /* xRender */ fileRender
b62f651… stephan 4539 },
b62f651… stephan 4540 { /* name */ "line",
b62f651… stephan 4541 /* isline */ 1,
b62f651… stephan 4542 /* eJust */ 0,
b62f651… stephan 4543 /* xInit */ lineInit,
b62f651… stephan 4544 /* xNumProp */ 0,
b62f651… stephan 4545 /* xCheck */ 0,
b62f651… stephan 4546 /* xChop */ 0,
b62f651… stephan 4547 /* xOffset */ lineOffset,
b62f651… stephan 4548 /* xFit */ 0,
b62f651… stephan 4549 /* xRender */ splineRender
b62f651… stephan 4550 },
b62f651… stephan 4551 { /* name */ "move",
b62f651… stephan 4552 /* isline */ 1,
b62f651… stephan 4553 /* eJust */ 0,
b62f651… stephan 4554 /* xInit */ moveInit,
b62f651… stephan 4555 /* xNumProp */ 0,
b62f651… stephan 4556 /* xCheck */ 0,
b62f651… stephan 4557 /* xChop */ 0,
b62f651… stephan 4558 /* xOffset */ boxOffset,
b62f651… stephan 4559 /* xFit */ 0,
b62f651… stephan 4560 /* xRender */ moveRender
b62f651… stephan 4561 },
b62f651… stephan 4562 { /* name */ "oval",
b62f651… stephan 4563 /* isline */ 0,
b62f651… stephan 4564 /* eJust */ 1,
b62f651… stephan 4565 /* xInit */ ovalInit,
b62f651… stephan 4566 /* xNumProp */ ovalNumProp,
b62f651… stephan 4567 /* xCheck */ 0,
b62f651… stephan 4568 /* xChop */ boxChop,
b62f651… stephan 4569 /* xOffset */ boxOffset,
b62f651… stephan 4570 /* xFit */ ovalFit,
b62f651… stephan 4571 /* xRender */ boxRender
b62f651… stephan 4572 },
b62f651… stephan 4573 { /* name */ "spline",
b62f651… stephan 4574 /* isline */ 1,
b62f651… stephan 4575 /* eJust */ 0,
b62f651… stephan 4576 /* xInit */ splineInit,
b62f651… stephan 4577 /* xNumProp */ 0,
b62f651… stephan 4578 /* xCheck */ 0,
b62f651… stephan 4579 /* xChop */ 0,
b62f651… stephan 4580 /* xOffset */ lineOffset,
b62f651… stephan 4581 /* xFit */ 0,
b62f651… stephan 4582 /* xRender */ splineRender
b62f651… stephan 4583 },
b62f651… stephan 4584 { /* name */ "text",
b62f651… stephan 4585 /* isline */ 0,
b62f651… stephan 4586 /* eJust */ 0,
b62f651… stephan 4587 /* xInit */ textInit,
b62f651… stephan 4588 /* xNumProp */ 0,
b62f651… stephan 4589 /* xCheck */ 0,
b62f651… stephan 4590 /* xChop */ boxChop,
b62f651… stephan 4591 /* xOffset */ textOffset,
b62f651… stephan 4592 /* xFit */ boxFit,
8ed25a3… drh 4593 /* xRender */ textRender
b62f651… stephan 4594 },
b62f651… stephan 4595 };
b62f651… stephan 4596 static const PClass sublistClass =
b62f651… stephan 4597 { /* name */ "[]",
b62f651… stephan 4598 /* isline */ 0,
b62f651… stephan 4599 /* eJust */ 0,
b62f651… stephan 4600 /* xInit */ sublistInit,
b62f651… stephan 4601 /* xNumProp */ 0,
b62f651… stephan 4602 /* xCheck */ 0,
b62f651… stephan 4603 /* xChop */ 0,
b62f651… stephan 4604 /* xOffset */ boxOffset,
b62f651… stephan 4605 /* xFit */ 0,
b62f651… stephan 4606 /* xRender */ 0
b62f651… stephan 4607 };
b62f651… stephan 4608 static const PClass noopClass =
b62f651… stephan 4609 { /* name */ "noop",
b62f651… stephan 4610 /* isline */ 0,
b62f651… stephan 4611 /* eJust */ 0,
b62f651… stephan 4612 /* xInit */ 0,
b62f651… stephan 4613 /* xNumProp */ 0,
b62f651… stephan 4614 /* xCheck */ 0,
b62f651… stephan 4615 /* xChop */ 0,
b62f651… stephan 4616 /* xOffset */ boxOffset,
b62f651… stephan 4617 /* xFit */ 0,
b62f651… stephan 4618 /* xRender */ 0
b62f651… stephan 4619 };
b62f651… stephan 4620
b62f651… stephan 4621
b62f651… stephan 4622 /*
b62f651… stephan 4623 ** Reduce the length of the line segment by amt (if possible) by
b62f651… stephan 4624 ** modifying the location of *t.
b62f651… stephan 4625 */
b62f651… stephan 4626 static void pik_chop(PPoint *f, PPoint *t, PNum amt){
b62f651… stephan 4627 PNum dx = t->x - f->x;
b62f651… stephan 4628 PNum dy = t->y - f->y;
b62f651… stephan 4629 PNum dist = hypot(dx,dy);
b62f651… stephan 4630 PNum r;
b62f651… stephan 4631 if( dist<=amt ){
b62f651… stephan 4632 *t = *f;
b62f651… stephan 4633 return;
b62f651… stephan 4634 }
b62f651… stephan 4635 r = 1.0 - amt/dist;
b62f651… stephan 4636 t->x = f->x + r*dx;
b62f651… stephan 4637 t->y = f->y + r*dy;
b62f651… stephan 4638 }
b62f651… stephan 4639
b62f651… stephan 4640 /*
b62f651… stephan 4641 ** Draw an arrowhead on the end of the line segment from pFrom to pTo.
b62f651… stephan 4642 ** Also, shorten the line segment (by changing the value of pTo) so that
b62f651… stephan 4643 ** the shaft of the arrow does not extend into the arrowhead.
b62f651… stephan 4644 */
b62f651… stephan 4645 static void pik_draw_arrowhead(Pik *p, PPoint *f, PPoint *t, PObj *pObj){
b62f651… stephan 4646 PNum dx = t->x - f->x;
b62f651… stephan 4647 PNum dy = t->y - f->y;
b62f651… stephan 4648 PNum dist = hypot(dx,dy);
b62f651… stephan 4649 PNum h = p->hArrow * pObj->sw;
b62f651… stephan 4650 PNum w = p->wArrow * pObj->sw;
b62f651… stephan 4651 PNum e1, ddx, ddy;
b62f651… stephan 4652 PNum bx, by;
b62f651… stephan 4653 if( pObj->color<0.0 ) return;
b62f651… stephan 4654 if( pObj->sw<=0.0 ) return;
b62f651… stephan 4655 if( dist<=0.0 ) return; /* Unable */
b62f651… stephan 4656 dx /= dist;
b62f651… stephan 4657 dy /= dist;
b62f651… stephan 4658 e1 = dist - h;
b62f651… stephan 4659 if( e1<0.0 ){
b62f651… stephan 4660 e1 = 0.0;
b62f651… stephan 4661 h = dist;
b62f651… stephan 4662 }
b62f651… stephan 4663 ddx = -w*dy;
b62f651… stephan 4664 ddy = w*dx;
b62f651… stephan 4665 bx = f->x + e1*dx;
b62f651… stephan 4666 by = f->y + e1*dy;
b62f651… stephan 4667 pik_append_xy(p,"<polygon points=\"", t->x, t->y);
b62f651… stephan 4668 pik_append_xy(p," ",bx-ddx, by-ddy);
b62f651… stephan 4669 pik_append_xy(p," ",bx+ddx, by+ddy);
b62f651… stephan 4670 pik_append_clr(p,"\" style=\"fill:",pObj->color,"\"/>\n",0);
b62f651… stephan 4671 pik_chop(f,t,h/2);
b62f651… stephan 4672 }
b62f651… stephan 4673
b62f651… stephan 4674 /*
b62f651… stephan 4675 ** Compute the relative offset to an edge location from the reference for a
b62f651… stephan 4676 ** an statement.
b62f651… stephan 4677 */
b62f651… stephan 4678 static PPoint pik_elem_offset(Pik *p, PObj *pObj, int cp){
b62f651… stephan 4679 return pObj->type->xOffset(p, pObj, cp);
b62f651… stephan 4680 }
b62f651… stephan 4681
b62f651… stephan 4682
b62f651… stephan 4683 /*
b62f651… stephan 4684 ** Append raw text to zOut
b62f651… stephan 4685 */
b62f651… stephan 4686 static void pik_append(Pik *p, const char *zText, int n){
b62f651… stephan 4687 if( n<0 ) n = (int)strlen(zText);
b62f651… stephan 4688 if( p->nOut+n>=p->nOutAlloc ){
b62f651… stephan 4689 int nNew = (p->nOut+n)*2 + 1;
b62f651… stephan 4690 char *z = realloc(p->zOut, nNew);
b62f651… stephan 4691 if( z==0 ){
b62f651… stephan 4692 pik_error(p, 0, 0);
b62f651… stephan 4693 return;
b62f651… stephan 4694 }
b62f651… stephan 4695 p->zOut = z;
b62f651… stephan 4696 p->nOutAlloc = nNew;
b62f651… stephan 4697 }
b62f651… stephan 4698 memcpy(p->zOut+p->nOut, zText, n);
b62f651… stephan 4699 p->nOut += n;
b62f651… stephan 4700 p->zOut[p->nOut] = 0;
b62f651… stephan 4701 }
b62f651… stephan 4702
b62f651… stephan 4703 /*
b3a0a4c… stephan 4704 ** Given a string and its length, returns true if the string begins
b3a0a4c… stephan 4705 ** with a construct which syntactically matches an HTML entity escape
b3a0a4c… stephan 4706 ** sequence (without checking for whether it's a known entity). Always
b3a0a4c… stephan 4707 ** returns false if zText[0] is false or n<4. Entities match the
b1ffe20… stephan 4708 ** equivalent of the regexes `&#[0-9]{2,};` and
b1ffe20… stephan 4709 ** `&[a-zA-Z][a-zA-Z0-9]+;`.
b3a0a4c… stephan 4710 */
b3a0a4c… stephan 4711 static int pik_isentity(char const * zText, int n){
b3a0a4c… stephan 4712 int i = 0;
b3a0a4c… stephan 4713 if( n<4 || '&'!=zText[0] ) return 0;
b3a0a4c… stephan 4714 n--;
b3a0a4c… stephan 4715 zText++;
b3a0a4c… stephan 4716 if( '#'==zText[0] ){
b3a0a4c… stephan 4717 zText++;
b3a0a4c… stephan 4718 n--;
b3a0a4c… stephan 4719 for(i=0; i<n; i++){
b3a0a4c… stephan 4720 if( i>1 && ';'==zText[i] ) return 1;
b3a0a4c… stephan 4721 else if( zText[i]<'0' || zText[i]>'9' ) return 0;
b1ffe20… stephan 4722 /* Note that &#nn; values nn<32d are not legal entities. */
b3a0a4c… stephan 4723 }
b3a0a4c… stephan 4724 }else{
b1ffe20… stephan 4725 for(i=0; i<n; i++){
b3a0a4c… stephan 4726 if( i>1 && ';'==zText[i] ) return 1;
b1ffe20… stephan 4727 else if( i>0 && zText[i]>='0' && zText[i]<='9' ){
b1ffe20… stephan 4728 continue;
b1ffe20… stephan 4729 }else if( zText[i]<'A' || zText[i]>'z'
b3a0a4c… stephan 4730 || (zText[i]>'Z' && zText[i]<'a') ) return 0;
b3a0a4c… stephan 4731 }
b3a0a4c… stephan 4732 }
b3a0a4c… stephan 4733 return 0;
b3a0a4c… stephan 4734 }
b3a0a4c… stephan 4735
b3a0a4c… stephan 4736 /*
b62f651… stephan 4737 ** Append text to zOut with HTML characters escaped.
b62f651… stephan 4738 **
b62f651… stephan 4739 ** * The space character is changed into non-breaking space (U+00a0)
b62f651… stephan 4740 ** if mFlags has the 0x01 bit set. This is needed when outputting
b62f651… stephan 4741 ** text to preserve leading and trailing whitespace. Turns out we
b62f651… stephan 4742 ** cannot use &nbsp; as that is an HTML-ism and is not valid in XML.
b62f651… stephan 4743 **
b62f651… stephan 4744 ** * The "&" character is changed into "&amp;" if mFlags has the
b62f651… stephan 4745 ** 0x02 bit set. This is needed when generating error message text.
b62f651… stephan 4746 **
b62f651… stephan 4747 ** * Except for the above, only "<" and ">" are escaped.
b62f651… stephan 4748 */
b62f651… stephan 4749 static void pik_append_text(Pik *p, const char *zText, int n, int mFlags){
b62f651… stephan 4750 int i;
b62f651… stephan 4751 char c = 0;
b62f651… stephan 4752 int bQSpace = mFlags & 1;
b62f651… stephan 4753 int bQAmp = mFlags & 2;
b62f651… stephan 4754 if( n<0 ) n = (int)strlen(zText);
b62f651… stephan 4755 while( n>0 ){
b62f651… stephan 4756 for(i=0; i<n; i++){
b62f651… stephan 4757 c = zText[i];
b62f651… stephan 4758 if( c=='<' || c=='>' ) break;
b62f651… stephan 4759 if( c==' ' && bQSpace ) break;
b62f651… stephan 4760 if( c=='&' && bQAmp ) break;
b62f651… stephan 4761 }
b62f651… stephan 4762 if( i ) pik_append(p, zText, i);
b62f651… stephan 4763 if( i==n ) break;
b62f651… stephan 4764 switch( c ){
b62f651… stephan 4765 case '<': { pik_append(p, "&lt;", 4); break; }
b62f651… stephan 4766 case '>': { pik_append(p, "&gt;", 4); break; }
b62f651… stephan 4767 case ' ': { pik_append(p, "\302\240;", 2); break; }
b3a0a4c… stephan 4768 case '&':
b3a0a4c… stephan 4769 if( pik_isentity(zText+i, n-i) ){ pik_append(p, "&", 1); }
b3a0a4c… stephan 4770 else { pik_append(p, "&amp;", 5); }
b62f651… stephan 4771 }
b62f651… stephan 4772 i++;
b62f651… stephan 4773 n -= i;
b62f651… stephan 4774 zText += i;
b62f651… stephan 4775 i = 0;
b62f651… stephan 4776 }
b62f651… stephan 4777 }
b62f651… stephan 4778
b62f651… stephan 4779 /*
b62f651… stephan 4780 ** Append error message text. This is either a raw append, or an append
b62f651… stephan 4781 ** with HTML escapes, depending on whether the PIKCHR_PLAINTEXT_ERRORS flag
b62f651… stephan 4782 ** is set.
b62f651… stephan 4783 */
b62f651… stephan 4784 static void pik_append_errtxt(Pik *p, const char *zText, int n){
b62f651… stephan 4785 if( p->mFlags & PIKCHR_PLAINTEXT_ERRORS ){
b62f651… stephan 4786 pik_append(p, zText, n);
b62f651… stephan 4787 }else{
b62f651… stephan 4788 pik_append_text(p, zText, n, 0);
b62f651… stephan 4789 }
b62f651… stephan 4790 }
b62f651… stephan 4791
b62f651… stephan 4792 /* Append a PNum value
b62f651… stephan 4793 */
b62f651… stephan 4794 static void pik_append_num(Pik *p, const char *z,PNum v){
b62f651… stephan 4795 char buf[100];
b62f651… stephan 4796 snprintf(buf, sizeof(buf)-1, "%.10g", (double)v);
b62f651… stephan 4797 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4798 pik_append(p, z, -1);
b62f651… stephan 4799 pik_append(p, buf, -1);
b62f651… stephan 4800 }
b62f651… stephan 4801
b62f651… stephan 4802 /* Append a PPoint value (Used for debugging only)
b62f651… stephan 4803 */
b62f651… stephan 4804 static void pik_append_point(Pik *p, const char *z, PPoint *pPt){
b62f651… stephan 4805 char buf[100];
b62f651… stephan 4806 snprintf(buf, sizeof(buf)-1, "%.10g,%.10g",
b62f651… stephan 4807 (double)pPt->x, (double)pPt->y);
b62f651… stephan 4808 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4809 pik_append(p, z, -1);
b62f651… stephan 4810 pik_append(p, buf, -1);
b62f651… stephan 4811 }
b62f651… stephan 4812
b62f651… stephan 4813 /*
b62f651… stephan 4814 ** Invert the RGB color so that it is appropriate for dark mode.
b62f651… stephan 4815 ** Variable x hold the initial color. The color is intended for use
b62f651… stephan 4816 ** as a background color if isBg is true, and as a foreground color
b62f651… stephan 4817 ** if isBg is false.
b62f651… stephan 4818 */
b62f651… stephan 4819 static int pik_color_to_dark_mode(int x, int isBg){
b62f651… stephan 4820 int r, g, b;
b62f651… stephan 4821 int mn, mx;
b62f651… stephan 4822 x = 0xffffff - x;
b62f651… stephan 4823 r = (x>>16) & 0xff;
b62f651… stephan 4824 g = (x>>8) & 0xff;
b62f651… stephan 4825 b = x & 0xff;
b62f651… stephan 4826 mx = r;
b62f651… stephan 4827 if( g>mx ) mx = g;
b62f651… stephan 4828 if( b>mx ) mx = b;
b62f651… stephan 4829 mn = r;
b62f651… stephan 4830 if( g<mn ) mn = g;
b62f651… stephan 4831 if( b<mn ) mn = b;
b62f651… stephan 4832 r = mn + (mx-r);
b62f651… stephan 4833 g = mn + (mx-g);
b62f651… stephan 4834 b = mn + (mx-b);
b62f651… stephan 4835 if( isBg ){
b62f651… stephan 4836 if( mx>127 ){
b62f651… stephan 4837 r = (127*r)/mx;
b62f651… stephan 4838 g = (127*g)/mx;
b62f651… stephan 4839 b = (127*b)/mx;
b62f651… stephan 4840 }
b62f651… stephan 4841 }else{
b62f651… stephan 4842 if( mn<128 && mx>mn ){
b62f651… stephan 4843 r = 127 + ((r-mn)*128)/(mx-mn);
b62f651… stephan 4844 g = 127 + ((g-mn)*128)/(mx-mn);
b62f651… stephan 4845 b = 127 + ((b-mn)*128)/(mx-mn);
b62f651… stephan 4846 }
b62f651… stephan 4847 }
b62f651… stephan 4848 return r*0x10000 + g*0x100 + b;
b62f651… stephan 4849 }
b62f651… stephan 4850
b62f651… stephan 4851 /* Append a PNum value surrounded by text. Do coordinate transformations
b62f651… stephan 4852 ** on the value.
b62f651… stephan 4853 */
b62f651… stephan 4854 static void pik_append_x(Pik *p, const char *z1, PNum v, const char *z2){
b62f651… stephan 4855 char buf[200];
b62f651… stephan 4856 v -= p->bbox.sw.x;
544eefd… drh 4857 snprintf(buf, sizeof(buf)-1, "%s%g%s", z1, p->rScale*v, z2);
b62f651… stephan 4858 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4859 pik_append(p, buf, -1);
b62f651… stephan 4860 }
b62f651… stephan 4861 static void pik_append_y(Pik *p, const char *z1, PNum v, const char *z2){
b62f651… stephan 4862 char buf[200];
b62f651… stephan 4863 v = p->bbox.ne.y - v;
544eefd… drh 4864 snprintf(buf, sizeof(buf)-1, "%s%g%s", z1, p->rScale*v, z2);
b62f651… stephan 4865 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4866 pik_append(p, buf, -1);
b62f651… stephan 4867 }
b62f651… stephan 4868 static void pik_append_xy(Pik *p, const char *z1, PNum x, PNum y){
b62f651… stephan 4869 char buf[200];
b62f651… stephan 4870 x = x - p->bbox.sw.x;
b62f651… stephan 4871 y = p->bbox.ne.y - y;
544eefd… drh 4872 snprintf(buf, sizeof(buf)-1, "%s%g,%g", z1, p->rScale*x, p->rScale*y);
b62f651… stephan 4873 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4874 pik_append(p, buf, -1);
b62f651… stephan 4875 }
b62f651… stephan 4876 static void pik_append_dis(Pik *p, const char *z1, PNum v, const char *z2){
b62f651… stephan 4877 char buf[200];
b62f651… stephan 4878 snprintf(buf, sizeof(buf)-1, "%s%g%s", z1, p->rScale*v, z2);
b62f651… stephan 4879 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4880 pik_append(p, buf, -1);
b62f651… stephan 4881 }
b62f651… stephan 4882
b62f651… stephan 4883 /* Append a color specification to the output.
b62f651… stephan 4884 **
b62f651… stephan 4885 ** In PIKCHR_DARK_MODE, the color is inverted. The "bg" flags indicates that
b62f651… stephan 4886 ** the color is intended for use as a background color if true, or as a
b62f651… stephan 4887 ** foreground color if false. The distinction only matters for color
b62f651… stephan 4888 ** inversions in PIKCHR_DARK_MODE.
b62f651… stephan 4889 */
b62f651… stephan 4890 static void pik_append_clr(Pik *p,const char *z1,PNum v,const char *z2,int bg){
b62f651… stephan 4891 char buf[200];
b62f651… stephan 4892 int x = pik_round(v);
b62f651… stephan 4893 int r, g, b;
b62f651… stephan 4894 if( x==0 && p->fgcolor>0 && !bg ){
b62f651… stephan 4895 x = p->fgcolor;
b62f651… stephan 4896 }else if( bg && x>=0xffffff && p->bgcolor>0 ){
b62f651… stephan 4897 x = p->bgcolor;
b62f651… stephan 4898 }else if( p->mFlags & PIKCHR_DARK_MODE ){
b62f651… stephan 4899 x = pik_color_to_dark_mode(x,bg);
b62f651… stephan 4900 }
b62f651… stephan 4901 r = (x>>16) & 0xff;
b62f651… stephan 4902 g = (x>>8) & 0xff;
b62f651… stephan 4903 b = x & 0xff;
b62f651… stephan 4904 snprintf(buf, sizeof(buf)-1, "%srgb(%d,%d,%d)%s", z1, r, g, b, z2);
b62f651… stephan 4905 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4906 pik_append(p, buf, -1);
b62f651… stephan 4907 }
b62f651… stephan 4908
b62f651… stephan 4909 /* Append an SVG path A record:
b62f651… stephan 4910 **
b62f651… stephan 4911 ** A r1 r2 0 0 0 x y
b62f651… stephan 4912 */
b62f651… stephan 4913 static void pik_append_arc(Pik *p, PNum r1, PNum r2, PNum x, PNum y){
b62f651… stephan 4914 char buf[200];
b62f651… stephan 4915 x = x - p->bbox.sw.x;
b62f651… stephan 4916 y = p->bbox.ne.y - y;
544eefd… drh 4917 snprintf(buf, sizeof(buf)-1, "A%g %g 0 0 0 %g %g",
544eefd… drh 4918 p->rScale*r1, p->rScale*r2,
544eefd… drh 4919 p->rScale*x, p->rScale*y);
b62f651… stephan 4920 buf[sizeof(buf)-1] = 0;
b62f651… stephan 4921 pik_append(p, buf, -1);
b62f651… stephan 4922 }
b62f651… stephan 4923
b62f651… stephan 4924 /* Append a style="..." text. But, leave the quote unterminated, in case
b62f651… stephan 4925 ** the caller wants to add some more.
b62f651… stephan 4926 **
b62f651… stephan 4927 ** eFill is non-zero to fill in the background, or 0 if no fill should
b62f651… stephan 4928 ** occur. Non-zero values of eFill determine the "bg" flag to pik_append_clr()
b62f651… stephan 4929 ** for cases when pObj->fill==pObj->color
b62f651… stephan 4930 **
b62f651… stephan 4931 ** 1 fill is background, and color is foreground.
b62f651… stephan 4932 ** 2 fill and color are both foreground. (Used by "dot" objects)
b62f651… stephan 4933 ** 3 fill and color are both background. (Used by most other objs)
b62f651… stephan 4934 */
b62f651… stephan 4935 static void pik_append_style(Pik *p, PObj *pObj, int eFill){
b62f651… stephan 4936 int clrIsBg = 0;
b62f651… stephan 4937 pik_append(p, " style=\"", -1);
b62f651… stephan 4938 if( pObj->fill>=0 && eFill ){
b62f651… stephan 4939 int fillIsBg = 1;
b62f651… stephan 4940 if( pObj->fill==pObj->color ){
b62f651… stephan 4941 if( eFill==2 ) fillIsBg = 0;
b62f651… stephan 4942 if( eFill==3 ) clrIsBg = 1;
b62f651… stephan 4943 }
b62f651… stephan 4944 pik_append_clr(p, "fill:", pObj->fill, ";", fillIsBg);
b62f651… stephan 4945 }else{
b62f651… stephan 4946 pik_append(p,"fill:none;",-1);
b62f651… stephan 4947 }
8ed25a3… drh 4948 if( pObj->sw>=0.0 && pObj->color>=0.0 ){
b62f651… stephan 4949 PNum sw = pObj->sw;
b62f651… stephan 4950 pik_append_dis(p, "stroke-width:", sw, ";");
b62f651… stephan 4951 if( pObj->nPath>2 && pObj->rad<=pObj->sw ){
b62f651… stephan 4952 pik_append(p, "stroke-linejoin:round;", -1);
b62f651… stephan 4953 }
b62f651… stephan 4954 pik_append_clr(p, "stroke:",pObj->color,";",clrIsBg);
b62f651… stephan 4955 if( pObj->dotted>0.0 ){
b62f651… stephan 4956 PNum v = pObj->dotted;
b62f651… stephan 4957 if( sw<2.1/p->rScale ) sw = 2.1/p->rScale;
b62f651… stephan 4958 pik_append_dis(p,"stroke-dasharray:",sw,"");
b62f651… stephan 4959 pik_append_dis(p,",",v,";");
b62f651… stephan 4960 }else if( pObj->dashed>0.0 ){
b62f651… stephan 4961 PNum v = pObj->dashed;
b62f651… stephan 4962 pik_append_dis(p,"stroke-dasharray:",v,"");
b62f651… stephan 4963 pik_append_dis(p,",",v,";");
b62f651… stephan 4964 }
b62f651… stephan 4965 }
b62f651… stephan 4966 }
b62f651… stephan 4967
b62f651… stephan 4968 /*
b62f651… stephan 4969 ** Compute the vertical locations for all text items in the
b62f651… stephan 4970 ** object pObj. In other words, set every pObj->aTxt[*].eCode
b62f651… stephan 4971 ** value to contain exactly one of: TP_ABOVE2, TP_ABOVE, TP_CENTER,
b62f651… stephan 4972 ** TP_BELOW, or TP_BELOW2 is set.
b62f651… stephan 4973 */
b62f651… stephan 4974 static void pik_txt_vertical_layout(PObj *pObj){
b62f651… stephan 4975 int n, i;
b62f651… stephan 4976 PToken *aTxt;
b62f651… stephan 4977 n = pObj->nTxt;
b62f651… stephan 4978 if( n==0 ) return;
b62f651… stephan 4979 aTxt = pObj->aTxt;
b62f651… stephan 4980 if( n==1 ){
b62f651… stephan 4981 if( (aTxt[0].eCode & TP_VMASK)==0 ){
b62f651… stephan 4982 aTxt[0].eCode |= TP_CENTER;
b62f651… stephan 4983 }
b62f651… stephan 4984 }else{
b62f651… stephan 4985 int allSlots = 0;
b62f651… stephan 4986 int aFree[5];
b62f651… stephan 4987 int iSlot;
b62f651… stephan 4988 int j, mJust;
b62f651… stephan 4989 /* If there is more than one TP_ABOVE, change the first to TP_ABOVE2. */
b62f651… stephan 4990 for(j=mJust=0, i=n-1; i>=0; i--){
b62f651… stephan 4991 if( aTxt[i].eCode & TP_ABOVE ){
b62f651… stephan 4992 if( j==0 ){
b62f651… stephan 4993 j++;
b62f651… stephan 4994 mJust = aTxt[i].eCode & TP_JMASK;
b62f651… stephan 4995 }else if( j==1 && mJust!=0 && (aTxt[i].eCode & mJust)==0 ){
b62f651… stephan 4996 j++;
b62f651… stephan 4997 }else{
b62f651… stephan 4998 aTxt[i].eCode = (aTxt[i].eCode & ~TP_VMASK) | TP_ABOVE2;
b62f651… stephan 4999 break;
b62f651… stephan 5000 }
b62f651… stephan 5001 }
b62f651… stephan 5002 }
b62f651… stephan 5003 /* If there is more than one TP_BELOW, change the last to TP_BELOW2 */
b62f651… stephan 5004 for(j=mJust=0, i=0; i<n; i++){
b62f651… stephan 5005 if( aTxt[i].eCode & TP_BELOW ){
b62f651… stephan 5006 if( j==0 ){
b62f651… stephan 5007 j++;
b62f651… stephan 5008 mJust = aTxt[i].eCode & TP_JMASK;
b62f651… stephan 5009 }else if( j==1 && mJust!=0 && (aTxt[i].eCode & mJust)==0 ){
b62f651… stephan 5010 j++;
b62f651… stephan 5011 }else{
b62f651… stephan 5012 aTxt[i].eCode = (aTxt[i].eCode & ~TP_VMASK) | TP_BELOW2;
b62f651… stephan 5013 break;
b62f651… stephan 5014 }
b62f651… stephan 5015 }
b62f651… stephan 5016 }
b62f651… stephan 5017 /* Compute a mask of all slots used */
b62f651… stephan 5018 for(i=0; i<n; i++) allSlots |= aTxt[i].eCode & TP_VMASK;
b62f651… stephan 5019 /* Set of an array of available slots */
b62f651… stephan 5020 if( n==2
b62f651… stephan 5021 && ((aTxt[0].eCode|aTxt[1].eCode)&TP_JMASK)==(TP_LJUST|TP_RJUST)
b62f651… stephan 5022 ){
b62f651… stephan 5023 /* Special case of two texts that have opposite justification:
b62f651… stephan 5024 ** Allow them both to float to center. */
b62f651… stephan 5025 iSlot = 2;
b62f651… stephan 5026 aFree[0] = aFree[1] = TP_CENTER;
b62f651… stephan 5027 }else{
b62f651… stephan 5028 /* Set up the arrow so that available slots are filled from top to
b62f651… stephan 5029 ** bottom */
b62f651… stephan 5030 iSlot = 0;
b62f651… stephan 5031 if( n>=4 && (allSlots & TP_ABOVE2)==0 ) aFree[iSlot++] = TP_ABOVE2;
b62f651… stephan 5032 if( (allSlots & TP_ABOVE)==0 ) aFree[iSlot++] = TP_ABOVE;
b62f651… stephan 5033 if( (n&1)!=0 ) aFree[iSlot++] = TP_CENTER;
b62f651… stephan 5034 if( (allSlots & TP_BELOW)==0 ) aFree[iSlot++] = TP_BELOW;
b62f651… stephan 5035 if( n>=4 && (allSlots & TP_BELOW2)==0 ) aFree[iSlot++] = TP_BELOW2;
b62f651… stephan 5036 }
b62f651… stephan 5037 /* Set the VMASK for all unassigned texts */
b62f651… stephan 5038 for(i=iSlot=0; i<n; i++){
b62f651… stephan 5039 if( (aTxt[i].eCode & TP_VMASK)==0 ){
b62f651… stephan 5040 aTxt[i].eCode |= aFree[iSlot++];
b62f651… stephan 5041 }
b62f651… stephan 5042 }
b62f651… stephan 5043 }
b62f651… stephan 5044 }
b62f651… stephan 5045
b62f651… stephan 5046 /* Return the font scaling factor associated with the input text attribute.
b62f651… stephan 5047 */
b62f651… stephan 5048 static PNum pik_font_scale(PToken *t){
b62f651… stephan 5049 PNum scale = 1.0;
b62f651… stephan 5050 if( t->eCode & TP_BIG ) scale *= 1.25;
b62f651… stephan 5051 if( t->eCode & TP_SMALL ) scale *= 0.8;
b62f651… stephan 5052 if( t->eCode & TP_XTRA ) scale *= scale;
b62f651… stephan 5053 return scale;
b62f651… stephan 5054 }
b62f651… stephan 5055
b62f651… stephan 5056 /* Append multiple <text> SVG elements for the text fields of the PObj.
b62f651… stephan 5057 ** Parameters:
b62f651… stephan 5058 **
b62f651… stephan 5059 ** p The Pik object into which we are rendering
b62f651… stephan 5060 **
b62f651… stephan 5061 ** pObj Object containing the text to be rendered
b62f651… stephan 5062 **
b62f651… stephan 5063 ** pBox If not NULL, do no rendering at all. Instead
b62f651… stephan 5064 ** expand the box object so that it will include all
b62f651… stephan 5065 ** of the text.
b62f651… stephan 5066 */
b62f651… stephan 5067 static void pik_append_txt(Pik *p, PObj *pObj, PBox *pBox){
b62f651… stephan 5068 PNum jw; /* Justification margin relative to center */
b62f651… stephan 5069 PNum ha2 = 0.0; /* Height of the top row of text */
b62f651… stephan 5070 PNum ha1 = 0.0; /* Height of the second "above" row */
b62f651… stephan 5071 PNum hc = 0.0; /* Height of the center row */
b62f651… stephan 5072 PNum hb1 = 0.0; /* Height of the first "below" row of text */
b62f651… stephan 5073 PNum hb2 = 0.0; /* Height of the second "below" row */
b62f651… stephan 5074 PNum yBase = 0.0;
2bdd36e… drh 5075 PNum sw = pObj->sw>=0.0 ? pObj->sw : 0;
b62f651… stephan 5076 int n, i, nz;
b62f651… stephan 5077 PNum x, y, orig_y, s;
b62f651… stephan 5078 const char *z;
b62f651… stephan 5079 PToken *aTxt;
b62f651… stephan 5080 unsigned allMask = 0;
b62f651… stephan 5081
b62f651… stephan 5082 if( p->nErr ) return;
b62f651… stephan 5083 if( pObj->nTxt==0 ) return;
b62f651… stephan 5084 aTxt = pObj->aTxt;
b62f651… stephan 5085 n = pObj->nTxt;
b62f651… stephan 5086 pik_txt_vertical_layout(pObj);
b62f651… stephan 5087 x = pObj->ptAt.x;
b62f651… stephan 5088 for(i=0; i<n; i++) allMask |= pObj->aTxt[i].eCode;
b62f651… stephan 5089 if( pObj->type->isLine ){
2bdd36e… drh 5090 hc = sw*1.5;
b62f651… stephan 5091 }else if( pObj->rad>0.0 && pObj->type->xInit==cylinderInit ){
b62f651… stephan 5092 yBase = -0.75*pObj->rad;
b62f651… stephan 5093 }
b62f651… stephan 5094 if( allMask & TP_CENTER ){
b62f651… stephan 5095 for(i=0; i<n; i++){
b62f651… stephan 5096 if( pObj->aTxt[i].eCode & TP_CENTER ){
b62f651… stephan 5097 s = pik_font_scale(pObj->aTxt+i);
b62f651… stephan 5098 if( hc<s*p->charHeight ) hc = s*p->charHeight;
b62f651… stephan 5099 }
b62f651… stephan 5100 }
b62f651… stephan 5101 }
b62f651… stephan 5102 if( allMask & TP_ABOVE ){
b62f651… stephan 5103 for(i=0; i<n; i++){
b62f651… stephan 5104 if( pObj->aTxt[i].eCode & TP_ABOVE ){
b62f651… stephan 5105 s = pik_font_scale(pObj->aTxt+i)*p->charHeight;
b62f651… stephan 5106 if( ha1<s ) ha1 = s;
b62f651… stephan 5107 }
b62f651… stephan 5108 }
b62f651… stephan 5109 if( allMask & TP_ABOVE2 ){
b62f651… stephan 5110 for(i=0; i<n; i++){
b62f651… stephan 5111 if( pObj->aTxt[i].eCode & TP_ABOVE2 ){
b62f651… stephan 5112 s = pik_font_scale(pObj->aTxt+i)*p->charHeight;
b62f651… stephan 5113 if( ha2<s ) ha2 = s;
b62f651… stephan 5114 }
b62f651… stephan 5115 }
b62f651… stephan 5116 }
b62f651… stephan 5117 }
b62f651… stephan 5118 if( allMask & TP_BELOW ){
b62f651… stephan 5119 for(i=0; i<n; i++){
b62f651… stephan 5120 if( pObj->aTxt[i].eCode & TP_BELOW ){
b62f651… stephan 5121 s = pik_font_scale(pObj->aTxt+i)*p->charHeight;
b62f651… stephan 5122 if( hb1<s ) hb1 = s;
b62f651… stephan 5123 }
b62f651… stephan 5124 }
b62f651… stephan 5125 if( allMask & TP_BELOW2 ){
b62f651… stephan 5126 for(i=0; i<n; i++){
b62f651… stephan 5127 if( pObj->aTxt[i].eCode & TP_BELOW2 ){
b62f651… stephan 5128 s = pik_font_scale(pObj->aTxt+i)*p->charHeight;
b62f651… stephan 5129 if( hb2<s ) hb2 = s;
b62f651… stephan 5130 }
b62f651… stephan 5131 }
b62f651… stephan 5132 }
b62f651… stephan 5133 }
b62f651… stephan 5134 if( pObj->type->eJust==1 ){
2bdd36e… drh 5135 jw = 0.5*(pObj->w - 0.5*(p->charWidth + sw));
b62f651… stephan 5136 }else{
b62f651… stephan 5137 jw = 0.0;
b62f651… stephan 5138 }
b62f651… stephan 5139 for(i=0; i<n; i++){
b62f651… stephan 5140 PToken *t = &aTxt[i];
b62f651… stephan 5141 PNum xtraFontScale = pik_font_scale(t);
b62f651… stephan 5142 PNum nx = 0;
b62f651… stephan 5143 orig_y = pObj->ptAt.y;
b62f651… stephan 5144 y = yBase;
b62f651… stephan 5145 if( t->eCode & TP_ABOVE2 ) y += 0.5*hc + ha1 + 0.5*ha2;
b62f651… stephan 5146 if( t->eCode & TP_ABOVE ) y += 0.5*hc + 0.5*ha1;
b62f651… stephan 5147 if( t->eCode & TP_BELOW ) y -= 0.5*hc + 0.5*hb1;
b62f651… stephan 5148 if( t->eCode & TP_BELOW2 ) y -= 0.5*hc + hb1 + 0.5*hb2;
b62f651… stephan 5149 if( t->eCode & TP_LJUST ) nx -= jw;
b62f651… stephan 5150 if( t->eCode & TP_RJUST ) nx += jw;
b62f651… stephan 5151
b62f651… stephan 5152 if( pBox!=0 ){
b62f651… stephan 5153 /* If pBox is not NULL, do not draw any <text>. Instead, just expand
b62f651… stephan 5154 ** pBox to include the text */
43eefe6… drh 5155 PNum cw = pik_text_length(t, t->eCode & TP_MONO)*p->charWidth*xtraFontScale*0.01;
b62f651… stephan 5156 PNum ch = p->charHeight*0.5*xtraFontScale;
b62f651… stephan 5157 PNum x0, y0, x1, y1; /* Boundary of text relative to pObj->ptAt */
43eefe6… drh 5158 if( (t->eCode & (TP_BOLD|TP_MONO))==TP_BOLD ){
43eefe6… drh 5159 cw *= 1.1;
43eefe6… drh 5160 }
b62f651… stephan 5161 if( t->eCode & TP_RJUST ){
b62f651… stephan 5162 x0 = nx;
b62f651… stephan 5163 y0 = y-ch;
b62f651… stephan 5164 x1 = nx-cw;
b62f651… stephan 5165 y1 = y+ch;
b62f651… stephan 5166 }else if( t->eCode & TP_LJUST ){
b62f651… stephan 5167 x0 = nx;
b62f651… stephan 5168 y0 = y-ch;
b62f651… stephan 5169 x1 = nx+cw;
b62f651… stephan 5170 y1 = y+ch;
b62f651… stephan 5171 }else{
b62f651… stephan 5172 x0 = nx+cw/2;
b62f651… stephan 5173 y0 = y+ch;
b62f651… stephan 5174 x1 = nx-cw/2;
b62f651… stephan 5175 y1 = y-ch;
b62f651… stephan 5176 }
b62f651… stephan 5177 if( (t->eCode & TP_ALIGN)!=0 && pObj->nPath>=2 ){
b62f651… stephan 5178 int nn = pObj->nPath;
b62f651… stephan 5179 PNum dx = pObj->aPath[nn-1].x - pObj->aPath[0].x;
b62f651… stephan 5180 PNum dy = pObj->aPath[nn-1].y - pObj->aPath[0].y;
b62f651… stephan 5181 if( dx!=0 || dy!=0 ){
b62f651… stephan 5182 PNum dist = hypot(dx,dy);
b62f651… stephan 5183 PNum tt;
b62f651… stephan 5184 dx /= dist;
b62f651… stephan 5185 dy /= dist;
b62f651… stephan 5186 tt = dx*x0 - dy*y0;
b62f651… stephan 5187 y0 = dy*x0 - dx*y0;
b62f651… stephan 5188 x0 = tt;
b62f651… stephan 5189 tt = dx*x1 - dy*y1;
b62f651… stephan 5190 y1 = dy*x1 - dx*y1;
b62f651… stephan 5191 x1 = tt;
b62f651… stephan 5192 }
b62f651… stephan 5193 }
b62f651… stephan 5194 pik_bbox_add_xy(pBox, x+x0, orig_y+y0);
b62f651… stephan 5195 pik_bbox_add_xy(pBox, x+x1, orig_y+y1);
b62f651… stephan 5196 continue;
b62f651… stephan 5197 }
b62f651… stephan 5198 nx += x;
b62f651… stephan 5199 y += orig_y;
b62f651… stephan 5200
b62f651… stephan 5201 pik_append_x(p, "<text x=\"", nx, "\"");
b62f651… stephan 5202 pik_append_y(p, " y=\"", y, "\"");
b62f651… stephan 5203 if( t->eCode & TP_RJUST ){
b62f651… stephan 5204 pik_append(p, " text-anchor=\"end\"", -1);
b62f651… stephan 5205 }else if( t->eCode & TP_LJUST ){
b62f651… stephan 5206 pik_append(p, " text-anchor=\"start\"", -1);
b62f651… stephan 5207 }else{
b62f651… stephan 5208 pik_append(p, " text-anchor=\"middle\"", -1);
b62f651… stephan 5209 }
b62f651… stephan 5210 if( t->eCode & TP_ITALIC ){
b62f651… stephan 5211 pik_append(p, " font-style=\"italic\"", -1);
b62f651… stephan 5212 }
b62f651… stephan 5213 if( t->eCode & TP_BOLD ){
b62f651… stephan 5214 pik_append(p, " font-weight=\"bold\"", -1);
43eefe6… drh 5215 }
43eefe6… drh 5216 if( t->eCode & TP_MONO ){
43eefe6… drh 5217 pik_append(p, " font-family=\"monospace\"", -1);
b62f651… stephan 5218 }
b62f651… stephan 5219 if( pObj->color>=0.0 ){
b62f651… stephan 5220 pik_append_clr(p, " fill=\"", pObj->color, "\"",0);
b62f651… stephan 5221 }
b62f651… stephan 5222 xtraFontScale *= p->fontScale;
b62f651… stephan 5223 if( xtraFontScale<=0.99 || xtraFontScale>=1.01 ){
b62f651… stephan 5224 pik_append_num(p, " font-size=\"", xtraFontScale*100.0);
b62f651… stephan 5225 pik_append(p, "%\"", 2);
b62f651… stephan 5226 }
b62f651… stephan 5227 if( (t->eCode & TP_ALIGN)!=0 && pObj->nPath>=2 ){
b62f651… stephan 5228 int nn = pObj->nPath;
b62f651… stephan 5229 PNum dx = pObj->aPath[nn-1].x - pObj->aPath[0].x;
b62f651… stephan 5230 PNum dy = pObj->aPath[nn-1].y - pObj->aPath[0].y;
b62f651… stephan 5231 if( dx!=0 || dy!=0 ){
b62f651… stephan 5232 PNum ang = atan2(dy,dx)*-180/M_PI;
b62f651… stephan 5233 pik_append_num(p, " transform=\"rotate(", ang);
b62f651… stephan 5234 pik_append_xy(p, " ", x, orig_y);
b62f651… stephan 5235 pik_append(p,")\"",2);
b62f651… stephan 5236 }
b62f651… stephan 5237 }
b62f651… stephan 5238 pik_append(p," dominant-baseline=\"central\">",-1);
b62f651… stephan 5239 if( t->n>=2 && t->z[0]=='"' ){
b62f651… stephan 5240 z = t->z+1;
b62f651… stephan 5241 nz = t->n-2;
b62f651… stephan 5242 }else{
b62f651… stephan 5243 z = t->z;
b62f651… stephan 5244 nz = t->n;
b62f651… stephan 5245 }
b62f651… stephan 5246 while( nz>0 ){
b62f651… stephan 5247 int j;
b62f651… stephan 5248 for(j=0; j<nz && z[j]!='\\'; j++){}
b62f651… stephan 5249 if( j ) pik_append_text(p, z, j, 0x3);
b62f651… stephan 5250 if( j<nz && (j+1==nz || z[j+1]=='\\') ){
b62f651… stephan 5251 pik_append(p, "&#92;", -1);
b62f651… stephan 5252 j++;
b62f651… stephan 5253 }
b62f651… stephan 5254 nz -= j+1;
b62f651… stephan 5255 z += j+1;
b62f651… stephan 5256 }
b62f651… stephan 5257 pik_append(p, "</text>\n", -1);
b62f651… stephan 5258 }
b62f651… stephan 5259 }
b62f651… stephan 5260
b62f651… stephan 5261 /*
b62f651… stephan 5262 ** Append text (that will go inside of a <pre>...</pre>) that
b62f651… stephan 5263 ** shows the context of an error token.
b62f651… stephan 5264 */
b62f651… stephan 5265 static void pik_error_context(Pik *p, PToken *pErr, int nContext){
b62f651… stephan 5266 int iErrPt; /* Index of first byte of error from start of input */
b62f651… stephan 5267 int iErrCol; /* Column of the error token on its line */
b62f651… stephan 5268 int iStart; /* Start position of the error context */
b62f651… stephan 5269 int iEnd; /* End position of the error context */
b62f651… stephan 5270 int iLineno; /* Line number of the error */
b62f651… stephan 5271 int iFirstLineno; /* Line number of start of error context */
b62f651… stephan 5272 int i; /* Loop counter */
b62f651… stephan 5273 int iBump = 0; /* Bump the location of the error cursor */
315aa26… stephan 5274 char zLineno[24]; /* Buffer in which to generate line numbers */
b62f651… stephan 5275
b62f651… stephan 5276 iErrPt = (int)(pErr->z - p->sIn.z);
b62f651… stephan 5277 if( iErrPt>=(int)p->sIn.n ){
b62f651… stephan 5278 iErrPt = p->sIn.n-1;
b62f651… stephan 5279 iBump = 1;
b62f651… stephan 5280 }else{
b62f651… stephan 5281 while( iErrPt>0 && (p->sIn.z[iErrPt]=='\n' || p->sIn.z[iErrPt]=='\r') ){
b62f651… stephan 5282 iErrPt--;
b62f651… stephan 5283 iBump = 1;
b62f651… stephan 5284 }
b62f651… stephan 5285 }
b62f651… stephan 5286 iLineno = 1;
b62f651… stephan 5287 for(i=0; i<iErrPt; i++){
b62f651… stephan 5288 if( p->sIn.z[i]=='\n' ){
b62f651… stephan 5289 iLineno++;
b62f651… stephan 5290 }
b62f651… stephan 5291 }
b62f651… stephan 5292 iStart = 0;
b62f651… stephan 5293 iFirstLineno = 1;
b62f651… stephan 5294 while( iFirstLineno+nContext<iLineno ){
b62f651… stephan 5295 while( p->sIn.z[iStart]!='\n' ){ iStart++; }
b62f651… stephan 5296 iStart++;
b62f651… stephan 5297 iFirstLineno++;
b62f651… stephan 5298 }
b62f651… stephan 5299 for(iEnd=iErrPt; p->sIn.z[iEnd]!=0 && p->sIn.z[iEnd]!='\n'; iEnd++){}
b62f651… stephan 5300 i = iStart;
b62f651… stephan 5301 while( iFirstLineno<=iLineno ){
b62f651… stephan 5302 snprintf(zLineno,sizeof(zLineno)-1,"/* %4d */ ", iFirstLineno++);
b62f651… stephan 5303 zLineno[sizeof(zLineno)-1] = 0;
b62f651… stephan 5304 pik_append(p, zLineno, -1);
b62f651… stephan 5305 for(i=iStart; p->sIn.z[i]!=0 && p->sIn.z[i]!='\n'; i++){}
b62f651… stephan 5306 pik_append_errtxt(p, p->sIn.z+iStart, i-iStart);
b62f651… stephan 5307 iStart = i+1;
b62f651… stephan 5308 pik_append(p, "\n", 1);
b62f651… stephan 5309 }
b62f651… stephan 5310 for(iErrCol=0, i=iErrPt; i>0 && p->sIn.z[i]!='\n'; iErrCol++, i--){}
b62f651… stephan 5311 for(i=0; i<iErrCol+11+iBump; i++){ pik_append(p, " ", 1); }
b62f651… stephan 5312 for(i=0; i<(int)pErr->n; i++) pik_append(p, "^", 1);
b62f651… stephan 5313 pik_append(p, "\n", 1);
b62f651… stephan 5314 }
b62f651… stephan 5315
b62f651… stephan 5316
b62f651… stephan 5317 /*
b62f651… stephan 5318 ** Generate an error message for the output. pErr is the token at which
b62f651… stephan 5319 ** the error should point. zMsg is the text of the error message. If
b62f651… stephan 5320 ** either pErr or zMsg is NULL, generate an out-of-memory error message.
b62f651… stephan 5321 **
b62f651… stephan 5322 ** This routine is a no-op if there has already been an error reported.
b62f651… stephan 5323 */
b62f651… stephan 5324 static void pik_error(Pik *p, PToken *pErr, const char *zMsg){
b62f651… stephan 5325 int i;
b62f651… stephan 5326 if( p==0 ) return;
b62f651… stephan 5327 if( p->nErr ) return;
b62f651… stephan 5328 p->nErr++;
b62f651… stephan 5329 if( zMsg==0 ){
b62f651… stephan 5330 if( p->mFlags & PIKCHR_PLAINTEXT_ERRORS ){
b62f651… stephan 5331 pik_append(p, "\nOut of memory\n", -1);
b62f651… stephan 5332 }else{
b62f651… stephan 5333 pik_append(p, "\n<div><p>Out of memory</p></div>\n", -1);
b62f651… stephan 5334 }
b62f651… stephan 5335 return;
b62f651… stephan 5336 }
b62f651… stephan 5337 if( pErr==0 ){
b62f651… stephan 5338 pik_append(p, "\n", 1);
b62f651… stephan 5339 pik_append_errtxt(p, zMsg, -1);
b62f651… stephan 5340 return;
b62f651… stephan 5341 }
b62f651… stephan 5342 if( (p->mFlags & PIKCHR_PLAINTEXT_ERRORS)==0 ){
b62f651… stephan 5343 pik_append(p, "<div><pre>\n", -1);
b62f651… stephan 5344 }
b62f651… stephan 5345 pik_error_context(p, pErr, 5);
b62f651… stephan 5346 pik_append(p, "ERROR: ", -1);
b62f651… stephan 5347 pik_append_errtxt(p, zMsg, -1);
b62f651… stephan 5348 pik_append(p, "\n", 1);
b62f651… stephan 5349 for(i=p->nCtx-1; i>=0; i--){
b62f651… stephan 5350 pik_append(p, "Called from:\n", -1);
b62f651… stephan 5351 pik_error_context(p, &p->aCtx[i], 0);
b62f651… stephan 5352 }
b62f651… stephan 5353 if( (p->mFlags & PIKCHR_PLAINTEXT_ERRORS)==0 ){
b62f651… stephan 5354 pik_append(p, "</pre></div>\n", -1);
b62f651… stephan 5355 }
b62f651… stephan 5356 }
b62f651… stephan 5357
b62f651… stephan 5358 /*
b62f651… stephan 5359 ** Process an "assert( e1 == e2 )" statement. Always return NULL.
b62f651… stephan 5360 */
b62f651… stephan 5361 static PObj *pik_assert(Pik *p, PNum e1, PToken *pEq, PNum e2){
b62f651… stephan 5362 char zE1[100], zE2[100], zMsg[300];
b62f651… stephan 5363
b62f651… stephan 5364 /* Convert the numbers to strings using %g for comparison. This
b62f651… stephan 5365 ** limits the precision of the comparison to account for rounding error. */
b62f651… stephan 5366 snprintf(zE1, sizeof(zE1), "%g", e1); zE1[sizeof(zE1)-1] = 0;
b62f651… stephan 5367 snprintf(zE2, sizeof(zE2), "%g", e2); zE1[sizeof(zE2)-1] = 0;
b62f651… stephan 5368 if( strcmp(zE1,zE2)!=0 ){
b62f651… stephan 5369 snprintf(zMsg, sizeof(zMsg), "%.50s != %.50s", zE1, zE2);
b62f651… stephan 5370 pik_error(p, pEq, zMsg);
b62f651… stephan 5371 }
b62f651… stephan 5372 return 0;
b62f651… stephan 5373 }
b62f651… stephan 5374
b62f651… stephan 5375 /*
b62f651… stephan 5376 ** Process an "assert( place1 == place2 )" statement. Always return NULL.
b62f651… stephan 5377 */
b62f651… stephan 5378 static PObj *pik_position_assert(Pik *p, PPoint *e1, PToken *pEq, PPoint *e2){
b62f651… stephan 5379 char zE1[100], zE2[100], zMsg[210];
b62f651… stephan 5380
b62f651… stephan 5381 /* Convert the numbers to strings using %g for comparison. This
b62f651… stephan 5382 ** limits the precision of the comparison to account for rounding error. */
b62f651… stephan 5383 snprintf(zE1, sizeof(zE1), "(%g,%g)", e1->x, e1->y); zE1[sizeof(zE1)-1] = 0;
b62f651… stephan 5384 snprintf(zE2, sizeof(zE2), "(%g,%g)", e2->x, e2->y); zE1[sizeof(zE2)-1] = 0;
b62f651… stephan 5385 if( strcmp(zE1,zE2)!=0 ){
b62f651… stephan 5386 snprintf(zMsg, sizeof(zMsg), "%s != %s", zE1, zE2);
b62f651… stephan 5387 pik_error(p, pEq, zMsg);
b62f651… stephan 5388 }
b62f651… stephan 5389 return 0;
b62f651… stephan 5390 }
b62f651… stephan 5391
b62f651… stephan 5392 /* Free a complete list of objects */
b62f651… stephan 5393 static void pik_elist_free(Pik *p, PList *pList){
b62f651… stephan 5394 int i;
b62f651… stephan 5395 if( pList==0 ) return;
b62f651… stephan 5396 for(i=0; i<pList->n; i++){
b62f651… stephan 5397 pik_elem_free(p, pList->a[i]);
b62f651… stephan 5398 }
b62f651… stephan 5399 free(pList->a);
b62f651… stephan 5400 free(pList);
b62f651… stephan 5401 return;
b62f651… stephan 5402 }
b62f651… stephan 5403
b62f651… stephan 5404 /* Free a single object, and its substructure */
b62f651… stephan 5405 static void pik_elem_free(Pik *p, PObj *pObj){
b62f651… stephan 5406 if( pObj==0 ) return;
b62f651… stephan 5407 free(pObj->zName);
b62f651… stephan 5408 pik_elist_free(p, pObj->pSublist);
b62f651… stephan 5409 free(pObj->aPath);
b62f651… stephan 5410 free(pObj);
b62f651… stephan 5411 }
b62f651… stephan 5412
b62f651… stephan 5413 /* Convert a numeric literal into a number. Return that number.
b62f651… stephan 5414 ** There is no error handling because the tokenizer has already
b62f651… stephan 5415 ** assured us that the numeric literal is valid.
b62f651… stephan 5416 **
b62f651… stephan 5417 ** Allowed number forms:
b62f651… stephan 5418 **
b62f651… stephan 5419 ** (1) Floating point literal
b62f651… stephan 5420 ** (2) Same as (1) but followed by a unit: "cm", "mm", "in",
b62f651… stephan 5421 ** "px", "pt", or "pc".
b62f651… stephan 5422 ** (3) Hex integers: 0x000000
b62f651… stephan 5423 **
b62f651… stephan 5424 ** This routine returns the result in inches. If a different unit
b62f651… stephan 5425 ** is specified, the conversion happens automatically.
b62f651… stephan 5426 */
b62f651… stephan 5427 PNum pik_atof(PToken *num){
b62f651… stephan 5428 char *endptr;
b62f651… stephan 5429 PNum ans;
b62f651… stephan 5430 if( num->n>=3 && num->z[0]=='0' && (num->z[1]=='x'||num->z[1]=='X') ){
b62f651… stephan 5431 return (PNum)strtol(num->z+2, 0, 16);
b62f651… stephan 5432 }
b62f651… stephan 5433 ans = strtod(num->z, &endptr);
b62f651… stephan 5434 if( (int)(endptr - num->z)==(int)num->n-2 ){
b62f651… stephan 5435 char c1 = endptr[0];
b62f651… stephan 5436 char c2 = endptr[1];
b62f651… stephan 5437 if( c1=='c' && c2=='m' ){
b62f651… stephan 5438 ans /= 2.54;
b62f651… stephan 5439 }else if( c1=='m' && c2=='m' ){
b62f651… stephan 5440 ans /= 25.4;
b62f651… stephan 5441 }else if( c1=='p' && c2=='x' ){
b62f651… stephan 5442 ans /= 96;
b62f651… stephan 5443 }else if( c1=='p' && c2=='t' ){
b62f651… stephan 5444 ans /= 72;
b62f651… stephan 5445 }else if( c1=='p' && c2=='c' ){
b62f651… stephan 5446 ans /= 6;
b62f651… stephan 5447 }
b62f651… stephan 5448 }
b62f651… stephan 5449 return ans;
b62f651… stephan 5450 }
b62f651… stephan 5451
b62f651… stephan 5452 /*
b62f651… stephan 5453 ** Compute the distance between two points
b62f651… stephan 5454 */
b62f651… stephan 5455 static PNum pik_dist(PPoint *pA, PPoint *pB){
b62f651… stephan 5456 PNum dx, dy;
b62f651… stephan 5457 dx = pB->x - pA->x;
b62f651… stephan 5458 dy = pB->y - pA->y;
b62f651… stephan 5459 return hypot(dx,dy);
b62f651… stephan 5460 }
b62f651… stephan 5461
b62f651… stephan 5462 /* Return true if a bounding box is empty.
b62f651… stephan 5463 */
b62f651… stephan 5464 static int pik_bbox_isempty(PBox *p){
b62f651… stephan 5465 return p->sw.x>p->ne.x;
b62f651… stephan 5466 }
b62f651… stephan 5467
b62f651… stephan 5468 /* Return true if point pPt is contained within the bounding box pBox
b62f651… stephan 5469 */
b62f651… stephan 5470 static int pik_bbox_contains_point(PBox *pBox, PPoint *pPt){
b62f651… stephan 5471 if( pik_bbox_isempty(pBox) ) return 0;
b62f651… stephan 5472 if( pPt->x < pBox->sw.x ) return 0;
b62f651… stephan 5473 if( pPt->x > pBox->ne.x ) return 0;
b62f651… stephan 5474 if( pPt->y < pBox->sw.y ) return 0;
b62f651… stephan 5475 if( pPt->y > pBox->ne.y ) return 0;
b62f651… stephan 5476 return 1;
b62f651… stephan 5477 }
b62f651… stephan 5478
b62f651… stephan 5479 /* Initialize a bounding box to an empty container
b62f651… stephan 5480 */
b62f651… stephan 5481 static void pik_bbox_init(PBox *p){
b62f651… stephan 5482 p->sw.x = 1.0;
b62f651… stephan 5483 p->sw.y = 1.0;
b62f651… stephan 5484 p->ne.x = 0.0;
b62f651… stephan 5485 p->ne.y = 0.0;
b62f651… stephan 5486 }
b62f651… stephan 5487
b62f651… stephan 5488 /* Enlarge the PBox of the first argument so that it fully
b62f651… stephan 5489 ** covers the second PBox
b62f651… stephan 5490 */
b62f651… stephan 5491 static void pik_bbox_addbox(PBox *pA, PBox *pB){
b62f651… stephan 5492 if( pik_bbox_isempty(pA) ){
b62f651… stephan 5493 *pA = *pB;
b62f651… stephan 5494 }
b62f651… stephan 5495 if( pik_bbox_isempty(pB) ) return;
b62f651… stephan 5496 if( pA->sw.x>pB->sw.x ) pA->sw.x = pB->sw.x;
b62f651… stephan 5497 if( pA->sw.y>pB->sw.y ) pA->sw.y = pB->sw.y;
b62f651… stephan 5498 if( pA->ne.x<pB->ne.x ) pA->ne.x = pB->ne.x;
b62f651… stephan 5499 if( pA->ne.y<pB->ne.y ) pA->ne.y = pB->ne.y;
b62f651… stephan 5500 }
b62f651… stephan 5501
b62f651… stephan 5502 /* Enlarge the PBox of the first argument, if necessary, so that
b62f651… stephan 5503 ** it contains the point described by the 2nd and 3rd arguments.
b62f651… stephan 5504 */
b62f651… stephan 5505 static void pik_bbox_add_xy(PBox *pA, PNum x, PNum y){
b62f651… stephan 5506 if( pik_bbox_isempty(pA) ){
b62f651… stephan 5507 pA->ne.x = x;
b62f651… stephan 5508 pA->ne.y = y;
b62f651… stephan 5509 pA->sw.x = x;
b62f651… stephan 5510 pA->sw.y = y;
b62f651… stephan 5511 return;
b62f651… stephan 5512 }
b62f651… stephan 5513 if( pA->sw.x>x ) pA->sw.x = x;
b62f651… stephan 5514 if( pA->sw.y>y ) pA->sw.y = y;
b62f651… stephan 5515 if( pA->ne.x<x ) pA->ne.x = x;
b62f651… stephan 5516 if( pA->ne.y<y ) pA->ne.y = y;
b62f651… stephan 5517 }
b62f651… stephan 5518
b62f651… stephan 5519 /* Enlarge the PBox so that it is able to contain an ellipse
b62f651… stephan 5520 ** centered at x,y and with radiuses rx and ry.
b62f651… stephan 5521 */
b62f651… stephan 5522 static void pik_bbox_addellipse(PBox *pA, PNum x, PNum y, PNum rx, PNum ry){
b62f651… stephan 5523 if( pik_bbox_isempty(pA) ){
b62f651… stephan 5524 pA->ne.x = x+rx;
b62f651… stephan 5525 pA->ne.y = y+ry;
b62f651… stephan 5526 pA->sw.x = x-rx;
b62f651… stephan 5527 pA->sw.y = y-ry;
b62f651… stephan 5528 return;
b62f651… stephan 5529 }
b62f651… stephan 5530 if( pA->sw.x>x-rx ) pA->sw.x = x-rx;
b62f651… stephan 5531 if( pA->sw.y>y-ry ) pA->sw.y = y-ry;
b62f651… stephan 5532 if( pA->ne.x<x+rx ) pA->ne.x = x+rx;
b62f651… stephan 5533 if( pA->ne.y<y+ry ) pA->ne.y = y+ry;
b62f651… stephan 5534 }
b62f651… stephan 5535
b62f651… stephan 5536
b62f651… stephan 5537
b62f651… stephan 5538 /* Append a new object onto the end of an object list. The
b62f651… stephan 5539 ** object list is created if it does not already exist. Return
b62f651… stephan 5540 ** the new object list.
b62f651… stephan 5541 */
b62f651… stephan 5542 static PList *pik_elist_append(Pik *p, PList *pList, PObj *pObj){
b62f651… stephan 5543 if( pObj==0 ) return pList;
b62f651… stephan 5544 if( pList==0 ){
b62f651… stephan 5545 pList = malloc(sizeof(*pList));
b62f651… stephan 5546 if( pList==0 ){
b62f651… stephan 5547 pik_error(p, 0, 0);
b62f651… stephan 5548 pik_elem_free(p, pObj);
b62f651… stephan 5549 return 0;
b62f651… stephan 5550 }
b62f651… stephan 5551 memset(pList, 0, sizeof(*pList));
b62f651… stephan 5552 }
b62f651… stephan 5553 if( pList->n>=pList->nAlloc ){
b62f651… stephan 5554 int nNew = (pList->n+5)*2;
b62f651… stephan 5555 PObj **pNew = realloc(pList->a, sizeof(PObj*)*nNew);
b62f651… stephan 5556 if( pNew==0 ){
b62f651… stephan 5557 pik_error(p, 0, 0);
b62f651… stephan 5558 pik_elem_free(p, pObj);
b62f651… stephan 5559 return pList;
b62f651… stephan 5560 }
b62f651… stephan 5561 pList->nAlloc = nNew;
b62f651… stephan 5562 pList->a = pNew;
b62f651… stephan 5563 }
b62f651… stephan 5564 pList->a[pList->n++] = pObj;
b62f651… stephan 5565 p->list = pList;
b62f651… stephan 5566 return pList;
b62f651… stephan 5567 }
b62f651… stephan 5568
b62f651… stephan 5569 /* Convert an object class name into a PClass pointer
b62f651… stephan 5570 */
b62f651… stephan 5571 static const PClass *pik_find_class(PToken *pId){
b62f651… stephan 5572 int first = 0;
b62f651… stephan 5573 int last = count(aClass) - 1;
b62f651… stephan 5574 do{
b62f651… stephan 5575 int mid = (first+last)/2;
b62f651… stephan 5576 int c = strncmp(aClass[mid].zName, pId->z, pId->n);
b62f651… stephan 5577 if( c==0 ){
b62f651… stephan 5578 c = aClass[mid].zName[pId->n]!=0;
b62f651… stephan 5579 if( c==0 ) return &aClass[mid];
b62f651… stephan 5580 }
b62f651… stephan 5581 if( c<0 ){
b62f651… stephan 5582 first = mid + 1;
b62f651… stephan 5583 }else{
b62f651… stephan 5584 last = mid - 1;
b62f651… stephan 5585 }
b62f651… stephan 5586 }while( first<=last );
b62f651… stephan 5587 return 0;
b62f651… stephan 5588 }
b62f651… stephan 5589
b62f651… stephan 5590 /* Allocate and return a new PObj object.
b62f651… stephan 5591 **
b62f651… stephan 5592 ** If pId!=0 then pId is an identifier that defines the object class.
b62f651… stephan 5593 ** If pStr!=0 then it is a STRING literal that defines a text object.
b62f651… stephan 5594 ** If pSublist!=0 then this is a [...] object. If all three parameters
b62f651… stephan 5595 ** are NULL then this is a no-op object used to define a PLACENAME.
b62f651… stephan 5596 */
b62f651… stephan 5597 static PObj *pik_elem_new(Pik *p, PToken *pId, PToken *pStr,PList *pSublist){
b62f651… stephan 5598 PObj *pNew;
b62f651… stephan 5599 int miss = 0;
b62f651… stephan 5600
b62f651… stephan 5601 if( p->nErr ) return 0;
b62f651… stephan 5602 pNew = malloc( sizeof(*pNew) );
b62f651… stephan 5603 if( pNew==0 ){
b62f651… stephan 5604 pik_error(p,0,0);
b62f651… stephan 5605 pik_elist_free(p, pSublist);
b62f651… stephan 5606 return 0;
b62f651… stephan 5607 }
b62f651… stephan 5608 memset(pNew, 0, sizeof(*pNew));
b62f651… stephan 5609 p->cur = pNew;
b62f651… stephan 5610 p->nTPath = 1;
b62f651… stephan 5611 p->thenFlag = 0;
b62f651… stephan 5612 if( p->list==0 || p->list->n==0 ){
b62f651… stephan 5613 pNew->ptAt.x = pNew->ptAt.y = 0.0;
b62f651… stephan 5614 pNew->eWith = CP_C;
b62f651… stephan 5615 }else{
b62f651… stephan 5616 PObj *pPrior = p->list->a[p->list->n-1];
b62f651… stephan 5617 pNew->ptAt = pPrior->ptExit;
b62f651… stephan 5618 switch( p->eDir ){
b62f651… stephan 5619 default: pNew->eWith = CP_W; break;
b62f651… stephan 5620 case DIR_LEFT: pNew->eWith = CP_E; break;
b62f651… stephan 5621 case DIR_UP: pNew->eWith = CP_S; break;
b62f651… stephan 5622 case DIR_DOWN: pNew->eWith = CP_N; break;
b62f651… stephan 5623 }
b62f651… stephan 5624 }
b62f651… stephan 5625 p->aTPath[0] = pNew->ptAt;
b62f651… stephan 5626 pNew->with = pNew->ptAt;
b62f651… stephan 5627 pNew->outDir = pNew->inDir = p->eDir;
b62f651… stephan 5628 pNew->iLayer = pik_value_int(p, "layer", 5, &miss);
b62f651… stephan 5629 if( miss ) pNew->iLayer = 1000;
b62f651… stephan 5630 if( pNew->iLayer<0 ) pNew->iLayer = 0;
b62f651… stephan 5631 if( pSublist ){
b62f651… stephan 5632 pNew->type = &sublistClass;
b62f651… stephan 5633 pNew->pSublist = pSublist;
b62f651… stephan 5634 sublistClass.xInit(p,pNew);
b62f651… stephan 5635 return pNew;
b62f651… stephan 5636 }
b62f651… stephan 5637 if( pStr ){
b62f651… stephan 5638 PToken n;
b62f651… stephan 5639 n.z = "text";
b62f651… stephan 5640 n.n = 4;
b62f651… stephan 5641 pNew->type = pik_find_class(&n);
b62f651… stephan 5642 assert( pNew->type!=0 );
b62f651… stephan 5643 pNew->errTok = *pStr;
b62f651… stephan 5644 pNew->type->xInit(p, pNew);
b62f651… stephan 5645 pik_add_txt(p, pStr, pStr->eCode);
b62f651… stephan 5646 return pNew;
b62f651… stephan 5647 }
b62f651… stephan 5648 if( pId ){
b62f651… stephan 5649 const PClass *pClass;
b62f651… stephan 5650 pNew->errTok = *pId;
b62f651… stephan 5651 pClass = pik_find_class(pId);
b62f651… stephan 5652 if( pClass ){
b62f651… stephan 5653 pNew->type = pClass;
b62f651… stephan 5654 pNew->sw = pik_value(p, "thickness",9,0);
b62f651… stephan 5655 pNew->fill = pik_value(p, "fill",4,0);
b62f651… stephan 5656 pNew->color = pik_value(p, "color",5,0);
b62f651… stephan 5657 pClass->xInit(p, pNew);
b62f651… stephan 5658 return pNew;
b62f651… stephan 5659 }
b62f651… stephan 5660 pik_error(p, pId, "unknown object type");
b62f651… stephan 5661 pik_elem_free(p, pNew);
b62f651… stephan 5662 return 0;
b62f651… stephan 5663 }
b62f651… stephan 5664 pNew->type = &noopClass;
b62f651… stephan 5665 pNew->ptExit = pNew->ptEnter = pNew->ptAt;
b62f651… stephan 5666 return pNew;
b62f651… stephan 5667 }
b62f651… stephan 5668
b62f651… stephan 5669 /*
b62f651… stephan 5670 ** If the ID token in the argument is the name of a macro, return
b62f651… stephan 5671 ** the PMacro object for that macro
b62f651… stephan 5672 */
b62f651… stephan 5673 static PMacro *pik_find_macro(Pik *p, PToken *pId){
b62f651… stephan 5674 PMacro *pMac;
b62f651… stephan 5675 for(pMac = p->pMacros; pMac; pMac=pMac->pNext){
b62f651… stephan 5676 if( pMac->macroName.n==pId->n
b62f651… stephan 5677 && strncmp(pMac->macroName.z,pId->z,pId->n)==0
b62f651… stephan 5678 ){
b62f651… stephan 5679 return pMac;
b62f651… stephan 5680 }
b62f651… stephan 5681 }
b62f651… stephan 5682 return 0;
b62f651… stephan 5683 }
b62f651… stephan 5684
b62f651… stephan 5685 /* Add a new macro
b62f651… stephan 5686 */
b62f651… stephan 5687 static void pik_add_macro(
b62f651… stephan 5688 Pik *p, /* Current Pikchr diagram */
b62f651… stephan 5689 PToken *pId, /* The ID token that defines the macro name */
b62f651… stephan 5690 PToken *pCode /* Macro body inside of {...} */
b62f651… stephan 5691 ){
b62f651… stephan 5692 PMacro *pNew = pik_find_macro(p, pId);
b62f651… stephan 5693 if( pNew==0 ){
b62f651… stephan 5694 pNew = malloc( sizeof(*pNew) );
b62f651… stephan 5695 if( pNew==0 ){
b62f651… stephan 5696 pik_error(p, 0, 0);
b62f651… stephan 5697 return;
b62f651… stephan 5698 }
b62f651… stephan 5699 pNew->pNext = p->pMacros;
b62f651… stephan 5700 p->pMacros = pNew;
b62f651… stephan 5701 pNew->macroName = *pId;
b62f651… stephan 5702 }
b62f651… stephan 5703 pNew->macroBody.z = pCode->z+1;
b62f651… stephan 5704 pNew->macroBody.n = pCode->n-2;
b62f651… stephan 5705 pNew->inUse = 0;
b62f651… stephan 5706 }
b62f651… stephan 5707
b62f651… stephan 5708
b62f651… stephan 5709 /*
b62f651… stephan 5710 ** Set the output direction and exit point for an object
b62f651… stephan 5711 */
b62f651… stephan 5712 static void pik_elem_set_exit(PObj *pObj, int eDir){
b62f651… stephan 5713 assert( ValidDir(eDir) );
b62f651… stephan 5714 pObj->outDir = eDir;
b62f651… stephan 5715 if( !pObj->type->isLine || pObj->bClose ){
b62f651… stephan 5716 pObj->ptExit = pObj->ptAt;
b62f651… stephan 5717 switch( pObj->outDir ){
b62f651… stephan 5718 default: pObj->ptExit.x += pObj->w*0.5; break;
b62f651… stephan 5719 case DIR_LEFT: pObj->ptExit.x -= pObj->w*0.5; break;
b62f651… stephan 5720 case DIR_UP: pObj->ptExit.y += pObj->h*0.5; break;
b62f651… stephan 5721 case DIR_DOWN: pObj->ptExit.y -= pObj->h*0.5; break;
b62f651… stephan 5722 }
b62f651… stephan 5723 }
b62f651… stephan 5724 }
b62f651… stephan 5725
b62f651… stephan 5726 /* Change the layout direction.
b62f651… stephan 5727 */
b62f651… stephan 5728 static void pik_set_direction(Pik *p, int eDir){
b62f651… stephan 5729 assert( ValidDir(eDir) );
b62f651… stephan 5730 p->eDir = (unsigned char)eDir;
b62f651… stephan 5731
b62f651… stephan 5732 /* It seems to make sense to reach back into the last object and
b62f651… stephan 5733 ** change its exit point (its ".end") to correspond to the new
b62f651… stephan 5734 ** direction. Things just seem to work better this way. However,
b62f651… stephan 5735 ** legacy PIC does *not* do this.
b62f651… stephan 5736 **
b62f651… stephan 5737 ** The difference can be seen in a script like this:
b62f651… stephan 5738 **
b62f651… stephan 5739 ** arrow; circle; down; arrow
b62f651… stephan 5740 **
b62f651… stephan 5741 ** You can make pikchr render the above exactly like PIC
b62f651… stephan 5742 ** by deleting the following three lines. But I (drh) think
b62f651… stephan 5743 ** it works better with those lines in place.
b62f651… stephan 5744 */
b62f651… stephan 5745 if( p->list && p->list->n ){
b62f651… stephan 5746 pik_elem_set_exit(p->list->a[p->list->n-1], eDir);
b62f651… stephan 5747 }
b62f651… stephan 5748 }
b62f651… stephan 5749
b62f651… stephan 5750 /* Move all coordinates contained within an object (and within its
b62f651… stephan 5751 ** substructure) by dx, dy
b62f651… stephan 5752 */
b62f651… stephan 5753 static void pik_elem_move(PObj *pObj, PNum dx, PNum dy){
b62f651… stephan 5754 int i;
b62f651… stephan 5755 pObj->ptAt.x += dx;
b62f651… stephan 5756 pObj->ptAt.y += dy;
b62f651… stephan 5757 pObj->ptEnter.x += dx;
b62f651… stephan 5758 pObj->ptEnter.y += dy;
b62f651… stephan 5759 pObj->ptExit.x += dx;
b62f651… stephan 5760 pObj->ptExit.y += dy;
b62f651… stephan 5761 pObj->bbox.ne.x += dx;
b62f651… stephan 5762 pObj->bbox.ne.y += dy;
b62f651… stephan 5763 pObj->bbox.sw.x += dx;
b62f651… stephan 5764 pObj->bbox.sw.y += dy;
b62f651… stephan 5765 for(i=0; i<pObj->nPath; i++){
b62f651… stephan 5766 pObj->aPath[i].x += dx;
b62f651… stephan 5767 pObj->aPath[i].y += dy;
b62f651… stephan 5768 }
b62f651… stephan 5769 if( pObj->pSublist ){
b62f651… stephan 5770 pik_elist_move(pObj->pSublist, dx, dy);
b62f651… stephan 5771 }
b62f651… stephan 5772 }
b62f651… stephan 5773 static void pik_elist_move(PList *pList, PNum dx, PNum dy){
b62f651… stephan 5774 int i;
b62f651… stephan 5775 for(i=0; i<pList->n; i++){
b62f651… stephan 5776 pik_elem_move(pList->a[i], dx, dy);
b62f651… stephan 5777 }
b62f651… stephan 5778 }
b62f651… stephan 5779
b62f651… stephan 5780 /*
b62f651… stephan 5781 ** Check to see if it is ok to set the value of paraemeter mThis.
b62f651… stephan 5782 ** Return 0 if it is ok. If it not ok, generate an appropriate
b62f651… stephan 5783 ** error message and return non-zero.
b62f651… stephan 5784 **
b62f651… stephan 5785 ** Flags are set in pObj so that the same object or conflicting
b62f651… stephan 5786 ** objects may not be set again.
b62f651… stephan 5787 **
b62f651… stephan 5788 ** To be ok, bit mThis must be clear and no more than one of
b62f651… stephan 5789 ** the bits identified by mBlockers may be set.
b62f651… stephan 5790 */
b62f651… stephan 5791 static int pik_param_ok(
b62f651… stephan 5792 Pik *p, /* For storing the error message (if any) */
b62f651… stephan 5793 PObj *pObj, /* The object under construction */
b62f651… stephan 5794 PToken *pId, /* Make the error point to this token */
b62f651… stephan 5795 int mThis /* Value we are trying to set */
b62f651… stephan 5796 ){
b62f651… stephan 5797 if( pObj->mProp & mThis ){
b62f651… stephan 5798 pik_error(p, pId, "value is already set");
b62f651… stephan 5799 return 1;
b62f651… stephan 5800 }
b62f651… stephan 5801 if( pObj->mCalc & mThis ){
b62f651… stephan 5802 pik_error(p, pId, "value already fixed by prior constraints");
b62f651… stephan 5803 return 1;
b62f651… stephan 5804 }
b62f651… stephan 5805 pObj->mProp |= mThis;
b62f651… stephan 5806 return 0;
b62f651… stephan 5807 }
b62f651… stephan 5808
b62f651… stephan 5809
b62f651… stephan 5810 /*
b62f651… stephan 5811 ** Set a numeric property like "width 7" or "radius 200%".
b62f651… stephan 5812 **
b62f651… stephan 5813 ** The rAbs term is an absolute value to add in. rRel is
b62f651… stephan 5814 ** a relative value by which to change the current value.
b62f651… stephan 5815 */
b62f651… stephan 5816 void pik_set_numprop(Pik *p, PToken *pId, PRel *pVal){
b62f651… stephan 5817 PObj *pObj = p->cur;
b62f651… stephan 5818 switch( pId->eType ){
b62f651… stephan 5819 case T_HEIGHT:
b62f651… stephan 5820 if( pik_param_ok(p, pObj, pId, A_HEIGHT) ) return;
b62f651… stephan 5821 pObj->h = pObj->h*pVal->rRel + pVal->rAbs;
b62f651… stephan 5822 break;
b62f651… stephan 5823 case T_WIDTH:
b62f651… stephan 5824 if( pik_param_ok(p, pObj, pId, A_WIDTH) ) return;
b62f651… stephan 5825 pObj->w = pObj->w*pVal->rRel + pVal->rAbs;
b62f651… stephan 5826 break;
b62f651… stephan 5827 case T_RADIUS:
b62f651… stephan 5828 if( pik_param_ok(p, pObj, pId, A_RADIUS) ) return;
b62f651… stephan 5829 pObj->rad = pObj->rad*pVal->rRel + pVal->rAbs;
b62f651… stephan 5830 break;
b62f651… stephan 5831 case T_DIAMETER:
b62f651… stephan 5832 if( pik_param_ok(p, pObj, pId, A_RADIUS) ) return;
b62f651… stephan 5833 pObj->rad = pObj->rad*pVal->rRel + 0.5*pVal->rAbs; /* diam it 2x rad */
b62f651… stephan 5834 break;
b62f651… stephan 5835 case T_THICKNESS:
b62f651… stephan 5836 if( pik_param_ok(p, pObj, pId, A_THICKNESS) ) return;
b62f651… stephan 5837 pObj->sw = pObj->sw*pVal->rRel + pVal->rAbs;
b62f651… stephan 5838 break;
b62f651… stephan 5839 }
b62f651… stephan 5840 if( pObj->type->xNumProp ){
b62f651… stephan 5841 pObj->type->xNumProp(p, pObj, pId);
b62f651… stephan 5842 }
b62f651… stephan 5843 return;
b62f651… stephan 5844 }
b62f651… stephan 5845
b62f651… stephan 5846 /*
b62f651… stephan 5847 ** Set a color property. The argument is an RGB value.
b62f651… stephan 5848 */
b62f651… stephan 5849 void pik_set_clrprop(Pik *p, PToken *pId, PNum rClr){
b62f651… stephan 5850 PObj *pObj = p->cur;
b62f651… stephan 5851 switch( pId->eType ){
b62f651… stephan 5852 case T_FILL:
b62f651… stephan 5853 if( pik_param_ok(p, pObj, pId, A_FILL) ) return;
b62f651… stephan 5854 pObj->fill = rClr;
b62f651… stephan 5855 break;
b62f651… stephan 5856 case T_COLOR:
b62f651… stephan 5857 if( pik_param_ok(p, pObj, pId, A_COLOR) ) return;
b62f651… stephan 5858 pObj->color = rClr;
b62f651… stephan 5859 break;
b62f651… stephan 5860 }
b62f651… stephan 5861 if( pObj->type->xNumProp ){
b62f651… stephan 5862 pObj->type->xNumProp(p, pObj, pId);
b62f651… stephan 5863 }
b62f651… stephan 5864 return;
b62f651… stephan 5865 }
b62f651… stephan 5866
b62f651… stephan 5867 /*
b62f651… stephan 5868 ** Set a "dashed" property like "dash 0.05"
b62f651… stephan 5869 **
b62f651… stephan 5870 ** Use the value supplied by pVal if available. If pVal==0, use
b62f651… stephan 5871 ** a default.
b62f651… stephan 5872 */
b62f651… stephan 5873 void pik_set_dashed(Pik *p, PToken *pId, PNum *pVal){
b62f651… stephan 5874 PObj *pObj = p->cur;
b62f651… stephan 5875 PNum v;
b62f651… stephan 5876 switch( pId->eType ){
b62f651… stephan 5877 case T_DOTTED: {
b62f651… stephan 5878 v = pVal==0 ? pik_value(p,"dashwid",7,0) : *pVal;
b62f651… stephan 5879 pObj->dotted = v;
b62f651… stephan 5880 pObj->dashed = 0.0;
b62f651… stephan 5881 break;
b62f651… stephan 5882 }
b62f651… stephan 5883 case T_DASHED: {
b62f651… stephan 5884 v = pVal==0 ? pik_value(p,"dashwid",7,0) : *pVal;
b62f651… stephan 5885 pObj->dashed = v;
b62f651… stephan 5886 pObj->dotted = 0.0;
b62f651… stephan 5887 break;
b62f651… stephan 5888 }
b62f651… stephan 5889 }
b62f651… stephan 5890 }
b62f651… stephan 5891
b62f651… stephan 5892 /*
b62f651… stephan 5893 ** If the current path information came from a "same" or "same as"
b62f651… stephan 5894 ** reset it.
b62f651… stephan 5895 */
b62f651… stephan 5896 static void pik_reset_samepath(Pik *p){
b62f651… stephan 5897 if( p->samePath ){
b62f651… stephan 5898 p->samePath = 0;
b62f651… stephan 5899 p->nTPath = 1;
b62f651… stephan 5900 }
b62f651… stephan 5901 }
b62f651… stephan 5902
b62f651… stephan 5903
b62f651… stephan 5904 /* Add a new term to the path for a line-oriented object by transferring
b62f651… stephan 5905 ** the information in the ptTo field over onto the path and into ptFrom
b62f651… stephan 5906 ** resetting the ptTo.
b62f651… stephan 5907 */
b62f651… stephan 5908 static void pik_then(Pik *p, PToken *pToken, PObj *pObj){
b62f651… stephan 5909 int n;
b62f651… stephan 5910 if( !pObj->type->isLine ){
b62f651… stephan 5911 pik_error(p, pToken, "use with line-oriented objects only");
b62f651… stephan 5912 return;
b62f651… stephan 5913 }
b62f651… stephan 5914 n = p->nTPath - 1;
b62f651… stephan 5915 if( n<1 && (pObj->mProp & A_FROM)==0 ){
b62f651… stephan 5916 pik_error(p, pToken, "no prior path points");
b62f651… stephan 5917 return;
b62f651… stephan 5918 }
b62f651… stephan 5919 p->thenFlag = 1;
b62f651… stephan 5920 }
b62f651… stephan 5921
b62f651… stephan 5922 /* Advance to the next entry in p->aTPath. Return its index.
b62f651… stephan 5923 */
b62f651… stephan 5924 static int pik_next_rpath(Pik *p, PToken *pErr){
b62f651… stephan 5925 int n = p->nTPath - 1;
b62f651… stephan 5926 if( n+1>=(int)count(p->aTPath) ){
b62f651… stephan 5927 pik_error(0, pErr, "too many path elements");
b62f651… stephan 5928 return n;
b62f651… stephan 5929 }
b62f651… stephan 5930 n++;
b62f651… stephan 5931 p->nTPath++;
b62f651… stephan 5932 p->aTPath[n] = p->aTPath[n-1];
b62f651… stephan 5933 p->mTPath = 0;
b62f651… stephan 5934 return n;
b62f651… stephan 5935 }
b62f651… stephan 5936
b62f651… stephan 5937 /* Add a direction term to an object. "up 0.5", or "left 3", or "down"
b62f651… stephan 5938 ** or "down 50%".
b62f651… stephan 5939 */
b62f651… stephan 5940 static void pik_add_direction(Pik *p, PToken *pDir, PRel *pVal){
b62f651… stephan 5941 PObj *pObj = p->cur;
b62f651… stephan 5942 int n;
b62f651… stephan 5943 int dir;
b62f651… stephan 5944 if( !pObj->type->isLine ){
b62f651… stephan 5945 if( pDir ){
b62f651… stephan 5946 pik_error(p, pDir, "use with line-oriented objects only");
b62f651… stephan 5947 }else{
b62f651… stephan 5948 PToken x = pik_next_semantic_token(&pObj->errTok);
b62f651… stephan 5949 pik_error(p, &x, "syntax error");
b62f651… stephan 5950 }
b62f651… stephan 5951 return;
b62f651… stephan 5952 }
b62f651… stephan 5953 pik_reset_samepath(p);
b62f651… stephan 5954 n = p->nTPath - 1;
b62f651… stephan 5955 if( p->thenFlag || p->mTPath==3 || n==0 ){
b62f651… stephan 5956 n = pik_next_rpath(p, pDir);
b62f651… stephan 5957 p->thenFlag = 0;
b62f651… stephan 5958 }
b62f651… stephan 5959 dir = pDir ? pDir->eCode : p->eDir;
b62f651… stephan 5960 switch( dir ){
b62f651… stephan 5961 case DIR_UP:
b62f651… stephan 5962 if( p->mTPath & 2 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 5963 p->aTPath[n].y += pVal->rAbs + pObj->h*pVal->rRel;
b62f651… stephan 5964 p->mTPath |= 2;
b62f651… stephan 5965 break;
b62f651… stephan 5966 case DIR_DOWN:
b62f651… stephan 5967 if( p->mTPath & 2 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 5968 p->aTPath[n].y -= pVal->rAbs + pObj->h*pVal->rRel;
b62f651… stephan 5969 p->mTPath |= 2;
b62f651… stephan 5970 break;
b62f651… stephan 5971 case DIR_RIGHT:
b62f651… stephan 5972 if( p->mTPath & 1 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 5973 p->aTPath[n].x += pVal->rAbs + pObj->w*pVal->rRel;
b62f651… stephan 5974 p->mTPath |= 1;
b62f651… stephan 5975 break;
b62f651… stephan 5976 case DIR_LEFT:
b62f651… stephan 5977 if( p->mTPath & 1 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 5978 p->aTPath[n].x -= pVal->rAbs + pObj->w*pVal->rRel;
b62f651… stephan 5979 p->mTPath |= 1;
b62f651… stephan 5980 break;
b62f651… stephan 5981 }
b62f651… stephan 5982 pObj->outDir = dir;
b62f651… stephan 5983 }
b62f651… stephan 5984
b62f651… stephan 5985 /* Process a movement attribute of one of these forms:
b62f651… stephan 5986 **
b62f651… stephan 5987 ** pDist pHdgKW rHdg pEdgept
b62f651… stephan 5988 ** GO distance HEADING angle
b62f651… stephan 5989 ** GO distance compasspoint
b62f651… stephan 5990 */
b62f651… stephan 5991 static void pik_move_hdg(
b62f651… stephan 5992 Pik *p, /* The Pikchr context */
b62f651… stephan 5993 PRel *pDist, /* Distance to move */
b62f651… stephan 5994 PToken *pHeading, /* "heading" keyword if present */
b62f651… stephan 5995 PNum rHdg, /* Angle argument to "heading" keyword */
b62f651… stephan 5996 PToken *pEdgept, /* EDGEPT keyword "ne", "sw", etc... */
b62f651… stephan 5997 PToken *pErr /* Token to use for error messages */
b62f651… stephan 5998 ){
b62f651… stephan 5999 PObj *pObj = p->cur;
b62f651… stephan 6000 int n;
b62f651… stephan 6001 PNum rDist = pDist->rAbs + pik_value(p,"linewid",7,0)*pDist->rRel;
b62f651… stephan 6002 if( !pObj->type->isLine ){
b62f651… stephan 6003 pik_error(p, pErr, "use with line-oriented objects only");
b62f651… stephan 6004 return;
b62f651… stephan 6005 }
b62f651… stephan 6006 pik_reset_samepath(p);
b62f651… stephan 6007 do{
b62f651… stephan 6008 n = pik_next_rpath(p, pErr);
b62f651… stephan 6009 }while( n<1 );
b62f651… stephan 6010 if( pHeading ){
d5ec362… stephan 6011 rHdg = fmod(rHdg,360.0);
b62f651… stephan 6012 }else if( pEdgept->eEdge==CP_C ){
b62f651… stephan 6013 pik_error(p, pEdgept, "syntax error");
b62f651… stephan 6014 return;
b62f651… stephan 6015 }else{
b62f651… stephan 6016 rHdg = pik_hdg_angle[pEdgept->eEdge];
b62f651… stephan 6017 }
b62f651… stephan 6018 if( rHdg<=45.0 ){
b62f651… stephan 6019 pObj->outDir = DIR_UP;
b62f651… stephan 6020 }else if( rHdg<=135.0 ){
b62f651… stephan 6021 pObj->outDir = DIR_RIGHT;
b62f651… stephan 6022 }else if( rHdg<=225.0 ){
b62f651… stephan 6023 pObj->outDir = DIR_DOWN;
b62f651… stephan 6024 }else if( rHdg<=315.0 ){
b62f651… stephan 6025 pObj->outDir = DIR_LEFT;
b62f651… stephan 6026 }else{
b62f651… stephan 6027 pObj->outDir = DIR_UP;
b62f651… stephan 6028 }
b62f651… stephan 6029 rHdg *= 0.017453292519943295769; /* degrees to radians */
b62f651… stephan 6030 p->aTPath[n].x += rDist*sin(rHdg);
b62f651… stephan 6031 p->aTPath[n].y += rDist*cos(rHdg);
b62f651… stephan 6032 p->mTPath = 2;
b62f651… stephan 6033 }
b62f651… stephan 6034
b62f651… stephan 6035
b62f651… stephan 6036 /* Process a movement attribute of the form "right until even with ..."
b62f651… stephan 6037 **
b62f651… stephan 6038 ** pDir is the first keyword, "right" or "left" or "up" or "down".
b62f651… stephan 6039 ** The movement is in that direction until its closest approach to
b62f651… stephan 6040 ** the point specified by pPoint.
b62f651… stephan 6041 */
b62f651… stephan 6042 static void pik_evenwith(Pik *p, PToken *pDir, PPoint *pPlace){
b62f651… stephan 6043 PObj *pObj = p->cur;
b62f651… stephan 6044 int n;
b62f651… stephan 6045 if( !pObj->type->isLine ){
b62f651… stephan 6046 pik_error(p, pDir, "use with line-oriented objects only");
b62f651… stephan 6047 return;
b62f651… stephan 6048 }
b62f651… stephan 6049 pik_reset_samepath(p);
b62f651… stephan 6050 n = p->nTPath - 1;
b62f651… stephan 6051 if( p->thenFlag || p->mTPath==3 || n==0 ){
b62f651… stephan 6052 n = pik_next_rpath(p, pDir);
b62f651… stephan 6053 p->thenFlag = 0;
b62f651… stephan 6054 }
b62f651… stephan 6055 switch( pDir->eCode ){
b62f651… stephan 6056 case DIR_DOWN:
b62f651… stephan 6057 case DIR_UP:
b62f651… stephan 6058 if( p->mTPath & 2 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 6059 p->aTPath[n].y = pPlace->y;
b62f651… stephan 6060 p->mTPath |= 2;
b62f651… stephan 6061 break;
b62f651… stephan 6062 case DIR_RIGHT:
b62f651… stephan 6063 case DIR_LEFT:
b62f651… stephan 6064 if( p->mTPath & 1 ) n = pik_next_rpath(p, pDir);
b62f651… stephan 6065 p->aTPath[n].x = pPlace->x;
b62f651… stephan 6066 p->mTPath |= 1;
b62f651… stephan 6067 break;
b62f651… stephan 6068 }
b62f651… stephan 6069 pObj->outDir = pDir->eCode;
b62f651… stephan 6070 }
b62f651… stephan 6071
b62f651… stephan 6072 /* If the last referenced object is centered at point pPt then return
b62f651… stephan 6073 ** a pointer to that object. If there is no prior object reference,
b62f651… stephan 6074 ** or if the points are not the same, return NULL.
b62f651… stephan 6075 **
b62f651… stephan 6076 ** This is a side-channel hack used to find the objects at which a
b62f651… stephan 6077 ** line begins and ends. For example, in
b62f651… stephan 6078 **
b62f651… stephan 6079 ** arrow from OBJ1 to OBJ2 chop
b62f651… stephan 6080 **
b62f651… stephan 6081 ** The arrow object is normally just handed the coordinates of the
b62f651… stephan 6082 ** centers for OBJ1 and OBJ2. But we also want to know the specific
b62f651… stephan 6083 ** object named in case there are multiple objects centered at the
b62f651… stephan 6084 ** same point.
b62f651… stephan 6085 **
b62f651… stephan 6086 ** See forum post 1d46e3a0bc
b62f651… stephan 6087 */
b62f651… stephan 6088 static PObj *pik_last_ref_object(Pik *p, PPoint *pPt){
b62f651… stephan 6089 PObj *pRes = 0;
b62f651… stephan 6090 if( p->lastRef==0 ) return 0;
b62f651… stephan 6091 if( p->lastRef->ptAt.x==pPt->x
b62f651… stephan 6092 && p->lastRef->ptAt.y==pPt->y
b62f651… stephan 6093 ){
b62f651… stephan 6094 pRes = p->lastRef;
b62f651… stephan 6095 }
b62f651… stephan 6096 p->lastRef = 0;
b62f651… stephan 6097 return pRes;
b62f651… stephan 6098 }
b62f651… stephan 6099
b62f651… stephan 6100 /* Set the "from" of an object
b62f651… stephan 6101 */
b62f651… stephan 6102 static void pik_set_from(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
b62f651… stephan 6103 if( !pObj->type->isLine ){
b62f651… stephan 6104 pik_error(p, pTk, "use \"at\" to position this object");
b62f651… stephan 6105 return;
b62f651… stephan 6106 }
b62f651… stephan 6107 if( pObj->mProp & A_FROM ){
b62f651… stephan 6108 pik_error(p, pTk, "line start location already fixed");
b62f651… stephan 6109 return;
b62f651… stephan 6110 }
b62f651… stephan 6111 if( pObj->bClose ){
b62f651… stephan 6112 pik_error(p, pTk, "polygon is closed");
b62f651… stephan 6113 return;
b62f651… stephan 6114 }
b62f651… stephan 6115 if( p->nTPath>1 ){
b62f651… stephan 6116 PNum dx = pPt->x - p->aTPath[0].x;
b62f651… stephan 6117 PNum dy = pPt->y - p->aTPath[0].y;
b62f651… stephan 6118 int i;
b62f651… stephan 6119 for(i=1; i<p->nTPath; i++){
b62f651… stephan 6120 p->aTPath[i].x += dx;
b62f651… stephan 6121 p->aTPath[i].y += dy;
b62f651… stephan 6122 }
b62f651… stephan 6123 }
b62f651… stephan 6124 p->aTPath[0] = *pPt;
b62f651… stephan 6125 p->mTPath = 3;
b62f651… stephan 6126 pObj->mProp |= A_FROM;
b62f651… stephan 6127 pObj->pFrom = pik_last_ref_object(p, pPt);
b62f651… stephan 6128 }
b62f651… stephan 6129
b62f651… stephan 6130 /* Set the "to" of an object
b62f651… stephan 6131 */
b62f651… stephan 6132 static void pik_add_to(Pik *p, PObj *pObj, PToken *pTk, PPoint *pPt){
b62f651… stephan 6133 int n = p->nTPath-1;
b62f651… stephan 6134 if( !pObj->type->isLine ){
b62f651… stephan 6135 pik_error(p, pTk, "use \"at\" to position this object");
b62f651… stephan 6136 return;
b62f651… stephan 6137 }
b62f651… stephan 6138 if( pObj->bClose ){
b62f651… stephan 6139 pik_error(p, pTk, "polygon is closed");
b62f651… stephan 6140 return;
b62f651… stephan 6141 }
b62f651… stephan 6142 pik_reset_samepath(p);
b62f651… stephan 6143 if( n==0 || p->mTPath==3 || p->thenFlag ){
b62f651… stephan 6144 n = pik_next_rpath(p, pTk);
b62f651… stephan 6145 }
b62f651… stephan 6146 p->aTPath[n] = *pPt;
b62f651… stephan 6147 p->mTPath = 3;
b62f651… stephan 6148 pObj->pTo = pik_last_ref_object(p, pPt);
b62f651… stephan 6149 }
b62f651… stephan 6150
b62f651… stephan 6151 static void pik_close_path(Pik *p, PToken *pErr){
b62f651… stephan 6152 PObj *pObj = p->cur;
b62f651… stephan 6153 if( p->nTPath<3 ){
b62f651… stephan 6154 pik_error(p, pErr,
b62f651… stephan 6155 "need at least 3 vertexes in order to close the polygon");
b62f651… stephan 6156 return;
b62f651… stephan 6157 }
b62f651… stephan 6158 if( pObj->bClose ){
b62f651… stephan 6159 pik_error(p, pErr, "polygon already closed");
b62f651… stephan 6160 return;
b62f651… stephan 6161 }
b62f651… stephan 6162 pObj->bClose = 1;
b62f651… stephan 6163 }
b62f651… stephan 6164
b62f651… stephan 6165 /* Lower the layer of the current object so that it is behind the
b62f651… stephan 6166 ** given object.
b62f651… stephan 6167 */
b62f651… stephan 6168 static void pik_behind(Pik *p, PObj *pOther){
b62f651… stephan 6169 PObj *pObj = p->cur;
b62f651… stephan 6170 if( p->nErr==0 && pObj->iLayer>=pOther->iLayer ){
b62f651… stephan 6171 pObj->iLayer = pOther->iLayer - 1;
b62f651… stephan 6172 }
b62f651… stephan 6173 }
b62f651… stephan 6174
b62f651… stephan 6175
b62f651… stephan 6176 /* Set the "at" of an object
b62f651… stephan 6177 */
b62f651… stephan 6178 static void pik_set_at(Pik *p, PToken *pEdge, PPoint *pAt, PToken *pErrTok){
b62f651… stephan 6179 PObj *pObj;
b62f651… stephan 6180 static unsigned char eDirToCp[] = { CP_E, CP_S, CP_W, CP_N };
b62f651… stephan 6181 if( p->nErr ) return;
b62f651… stephan 6182 pObj = p->cur;
b62f651… stephan 6183
b62f651… stephan 6184 if( pObj->type->isLine ){
b62f651… stephan 6185 pik_error(p, pErrTok, "use \"from\" and \"to\" to position this object");
b62f651… stephan 6186 return;
b62f651… stephan 6187 }
b62f651… stephan 6188 if( pObj->mProp & A_AT ){
b62f651… stephan 6189 pik_error(p, pErrTok, "location fixed by prior \"at\"");
b62f651… stephan 6190 return;
b62f651… stephan 6191 }
b62f651… stephan 6192 pObj->mProp |= A_AT;
b62f651… stephan 6193 pObj->eWith = pEdge ? pEdge->eEdge : CP_C;
b62f651… stephan 6194 if( pObj->eWith>=CP_END ){
390e001… drh 6195 int dir = pObj->eWith==CP_END ? pObj->outDir : (pObj->inDir+2)%4;
b62f651… stephan 6196 pObj->eWith = eDirToCp[dir];
b62f651… stephan 6197 }
b62f651… stephan 6198 pObj->with = *pAt;
b62f651… stephan 6199 }
b62f651… stephan 6200
b62f651… stephan 6201 /*
b62f651… stephan 6202 ** Try to add a text attribute to an object
b62f651… stephan 6203 */
b62f651… stephan 6204 static void pik_add_txt(Pik *p, PToken *pTxt, int iPos){
b62f651… stephan 6205 PObj *pObj = p->cur;
b62f651… stephan 6206 PToken *pT;
b62f651… stephan 6207 if( pObj->nTxt >= count(pObj->aTxt) ){
b62f651… stephan 6208 pik_error(p, pTxt, "too many text terms");
b62f651… stephan 6209 return;
b62f651… stephan 6210 }
b62f651… stephan 6211 pT = &pObj->aTxt[pObj->nTxt++];
b62f651… stephan 6212 *pT = *pTxt;
b62f651… stephan 6213 pT->eCode = (short)iPos;
b62f651… stephan 6214 }
b62f651… stephan 6215
b62f651… stephan 6216 /* Merge "text-position" flags
b62f651… stephan 6217 */
b62f651… stephan 6218 static int pik_text_position(int iPrev, PToken *pFlag){
b62f651… stephan 6219 int iRes = iPrev;
b62f651… stephan 6220 switch( pFlag->eType ){
b62f651… stephan 6221 case T_LJUST: iRes = (iRes&~TP_JMASK) | TP_LJUST; break;
b62f651… stephan 6222 case T_RJUST: iRes = (iRes&~TP_JMASK) | TP_RJUST; break;
b62f651… stephan 6223 case T_ABOVE: iRes = (iRes&~TP_VMASK) | TP_ABOVE; break;
b62f651… stephan 6224 case T_CENTER: iRes = (iRes&~TP_VMASK) | TP_CENTER; break;
b62f651… stephan 6225 case T_BELOW: iRes = (iRes&~TP_VMASK) | TP_BELOW; break;
43eefe6… drh 6226 case T_ITALIC: iRes |= TP_ITALIC; break;
43eefe6… drh 6227 case T_BOLD: iRes |= TP_BOLD; break;
43eefe6… drh 6228 case T_MONO: iRes |= TP_MONO; break;
b62f651… stephan 6229 case T_ALIGNED: iRes |= TP_ALIGN; break;
b62f651… stephan 6230 case T_BIG: if( iRes & TP_BIG ) iRes |= TP_XTRA;
b62f651… stephan 6231 else iRes = (iRes &~TP_SZMASK)|TP_BIG; break;
b62f651… stephan 6232 case T_SMALL: if( iRes & TP_SMALL ) iRes |= TP_XTRA;
b62f651… stephan 6233 else iRes = (iRes &~TP_SZMASK)|TP_SMALL; break;
b62f651… stephan 6234 }
b62f651… stephan 6235 return iRes;
b62f651… stephan 6236 }
b62f651… stephan 6237
b62f651… stephan 6238 /*
b62f651… stephan 6239 ** Table of scale-factor estimates for variable-width characters.
b62f651… stephan 6240 ** Actual character widths vary by font. These numbers are only
b62f651… stephan 6241 ** guesses. And this table only provides data for ASCII.
b62f651… stephan 6242 **
b62f651… stephan 6243 ** 100 means normal width.
b62f651… stephan 6244 */
b62f651… stephan 6245 static const unsigned char awChar[] = {
b62f651… stephan 6246 /* Skip initial 32 control characters */
b62f651… stephan 6247 /* ' ' */ 45,
b62f651… stephan 6248 /* '!' */ 55,
b62f651… stephan 6249 /* '"' */ 62,
b62f651… stephan 6250 /* '#' */ 115,
b62f651… stephan 6251 /* '$' */ 90,
b62f651… stephan 6252 /* '%' */ 132,
b62f651… stephan 6253 /* '&' */ 125,
b62f651… stephan 6254 /* '\''*/ 40,
b62f651… stephan 6255
b62f651… stephan 6256 /* '(' */ 55,
b62f651… stephan 6257 /* ')' */ 55,
b62f651… stephan 6258 /* '*' */ 71,
b62f651… stephan 6259 /* '+' */ 115,
b62f651… stephan 6260 /* ',' */ 45,
b62f651… stephan 6261 /* '-' */ 48,
b62f651… stephan 6262 /* '.' */ 45,
b62f651… stephan 6263 /* '/' */ 50,
b62f651… stephan 6264
b62f651… stephan 6265 /* '0' */ 91,
b62f651… stephan 6266 /* '1' */ 91,
b62f651… stephan 6267 /* '2' */ 91,
b62f651… stephan 6268 /* '3' */ 91,
b62f651… stephan 6269 /* '4' */ 91,
b62f651… stephan 6270 /* '5' */ 91,
b62f651… stephan 6271 /* '6' */ 91,
b62f651… stephan 6272 /* '7' */ 91,
b62f651… stephan 6273
b62f651… stephan 6274 /* '8' */ 91,
b62f651… stephan 6275 /* '9' */ 91,
b62f651… stephan 6276 /* ':' */ 50,
b62f651… stephan 6277 /* ';' */ 50,
b62f651… stephan 6278 /* '<' */ 120,
b62f651… stephan 6279 /* '=' */ 120,
b62f651… stephan 6280 /* '>' */ 120,
b62f651… stephan 6281 /* '?' */ 78,
b62f651… stephan 6282
b62f651… stephan 6283 /* '@' */ 142,
b62f651… stephan 6284 /* 'A' */ 102,
b62f651… stephan 6285 /* 'B' */ 105,
b62f651… stephan 6286 /* 'C' */ 110,
b62f651… stephan 6287 /* 'D' */ 115,
b62f651… stephan 6288 /* 'E' */ 105,
b62f651… stephan 6289 /* 'F' */ 98,
b62f651… stephan 6290 /* 'G' */ 105,
b62f651… stephan 6291
b62f651… stephan 6292 /* 'H' */ 125,
b62f651… stephan 6293 /* 'I' */ 58,
b62f651… stephan 6294 /* 'J' */ 58,
b62f651… stephan 6295 /* 'K' */ 107,
b62f651… stephan 6296 /* 'L' */ 95,
b62f651… stephan 6297 /* 'M' */ 145,
b62f651… stephan 6298 /* 'N' */ 125,
b62f651… stephan 6299 /* 'O' */ 115,
b62f651… stephan 6300
b62f651… stephan 6301 /* 'P' */ 95,
b62f651… stephan 6302 /* 'Q' */ 115,
b62f651… stephan 6303 /* 'R' */ 107,
b62f651… stephan 6304 /* 'S' */ 95,
b62f651… stephan 6305 /* 'T' */ 97,
b62f651… stephan 6306 /* 'U' */ 118,
b62f651… stephan 6307 /* 'V' */ 102,
b62f651… stephan 6308 /* 'W' */ 150,
b62f651… stephan 6309
b62f651… stephan 6310 /* 'X' */ 100,
b62f651… stephan 6311 /* 'Y' */ 93,
b62f651… stephan 6312 /* 'Z' */ 100,
b62f651… stephan 6313 /* '[' */ 58,
b62f651… stephan 6314 /* '\\'*/ 50,
b62f651… stephan 6315 /* ']' */ 58,
b62f651… stephan 6316 /* '^' */ 119,
b62f651… stephan 6317 /* '_' */ 72,
b62f651… stephan 6318
b62f651… stephan 6319 /* '`' */ 72,
b62f651… stephan 6320 /* 'a' */ 86,
b62f651… stephan 6321 /* 'b' */ 92,
b62f651… stephan 6322 /* 'c' */ 80,
b62f651… stephan 6323 /* 'd' */ 92,
b62f651… stephan 6324 /* 'e' */ 85,
b62f651… stephan 6325 /* 'f' */ 52,
b62f651… stephan 6326 /* 'g' */ 92,
b62f651… stephan 6327
b62f651… stephan 6328 /* 'h' */ 92,
b62f651… stephan 6329 /* 'i' */ 47,
b62f651… stephan 6330 /* 'j' */ 47,
b62f651… stephan 6331 /* 'k' */ 88,
b62f651… stephan 6332 /* 'l' */ 48,
b62f651… stephan 6333 /* 'm' */ 135,
b62f651… stephan 6334 /* 'n' */ 92,
b62f651… stephan 6335 /* 'o' */ 86,
b62f651… stephan 6336
b62f651… stephan 6337 /* 'p' */ 92,
b62f651… stephan 6338 /* 'q' */ 92,
b62f651… stephan 6339 /* 'r' */ 69,
b62f651… stephan 6340 /* 's' */ 75,
b62f651… stephan 6341 /* 't' */ 58,
b62f651… stephan 6342 /* 'u' */ 92,
b62f651… stephan 6343 /* 'v' */ 80,
b62f651… stephan 6344 /* 'w' */ 121,
b62f651… stephan 6345
b62f651… stephan 6346 /* 'x' */ 81,
b62f651… stephan 6347 /* 'y' */ 80,
b62f651… stephan 6348 /* 'z' */ 76,
b62f651… stephan 6349 /* '{' */ 91,
b62f651… stephan 6350 /* '|'*/ 49,
b62f651… stephan 6351 /* '}' */ 91,
b62f651… stephan 6352 /* '~' */ 118,
b62f651… stephan 6353 };
b62f651… stephan 6354
b62f651… stephan 6355 /* Return an estimate of the width of the displayed characters
b62f651… stephan 6356 ** in a character string. The returned value is 100 times the
b62f651… stephan 6357 ** average character width.
b62f651… stephan 6358 **
b62f651… stephan 6359 ** Omit "\" used to escape characters. And count entities like
b62f651… stephan 6360 ** "&lt;" as a single character. Multi-byte UTF8 characters count
b62f651… stephan 6361 ** as a single character.
b62f651… stephan 6362 **
43eefe6… drh 6363 ** Unless using a monospaced font, attempt to scale the answer by
43eefe6… drh 6364 ** the actual characters seen. Wide characters count more than
43eefe6… drh 6365 ** narrow characters. But the widths are only guesses.
43eefe6… drh 6366 **
b62f651… stephan 6367 */
43eefe6… drh 6368 static int pik_text_length(const PToken *pToken, const int isMonospace){
43eefe6… drh 6369 const int stdAvg=100, monoAvg=82;
b62f651… stephan 6370 int n = pToken->n;
b62f651… stephan 6371 const char *z = pToken->z;
b62f651… stephan 6372 int cnt, j;
b62f651… stephan 6373 for(j=1, cnt=0; j<n-1; j++){
b62f651… stephan 6374 char c = z[j];
b62f651… stephan 6375 if( c=='\\' && z[j+1]!='&' ){
b62f651… stephan 6376 c = z[++j];
b62f651… stephan 6377 }else if( c=='&' ){
b62f651… stephan 6378 int k;
b62f651… stephan 6379 for(k=j+1; k<j+7 && z[k]!=0 && z[k]!=';'; k++){}
b62f651… stephan 6380 if( z[k]==';' ) j = k;
43eefe6… drh 6381 cnt += (isMonospace ? monoAvg : stdAvg) * 3 / 2;
b62f651… stephan 6382 continue;
b62f651… stephan 6383 }
b62f651… stephan 6384 if( (c & 0xc0)==0xc0 ){
b62f651… stephan 6385 while( j+1<n-1 && (z[j+1]&0xc0)==0x80 ){ j++; }
43eefe6… drh 6386 cnt += isMonospace ? monoAvg : stdAvg;
b62f651… stephan 6387 continue;
b62f651… stephan 6388 }
43eefe6… drh 6389 if( isMonospace ){
43eefe6… drh 6390 cnt += monoAvg;
43eefe6… drh 6391 }else if( c >= 0x20 && c <= 0x7e ){
b62f651… stephan 6392 cnt += awChar[c-0x20];
b62f651… stephan 6393 }else{
43eefe6… drh 6394 cnt += stdAvg;
b62f651… stephan 6395 }
b62f651… stephan 6396 }
b62f651… stephan 6397 return cnt;
b62f651… stephan 6398 }
b62f651… stephan 6399
b62f651… stephan 6400 /* Adjust the width, height, and/or radius of the object so that
b62f651… stephan 6401 ** it fits around the text that has been added so far.
b62f651… stephan 6402 **
b62f651… stephan 6403 ** (1) Only text specified prior to this attribute is considered.
b62f651… stephan 6404 ** (2) The text size is estimated based on the charht and charwid
b62f651… stephan 6405 ** variable settings.
b62f651… stephan 6406 ** (3) The fitted attributes can be changed again after this
b62f651… stephan 6407 ** attribute, for example using "width 110%" if this auto-fit
b62f651… stephan 6408 ** underestimates the text size.
b62f651… stephan 6409 ** (4) Previously set attributes will not be altered. In other words,
b62f651… stephan 6410 ** "width 1in fit" might cause the height to change, but the
b62f651… stephan 6411 ** width is now set.
b62f651… stephan 6412 ** (5) This only works for attributes that have an xFit method.
b62f651… stephan 6413 **
b62f651… stephan 6414 ** The eWhich parameter is:
b62f651… stephan 6415 **
b62f651… stephan 6416 ** 1: Fit horizontally only
b62f651… stephan 6417 ** 2: Fit vertically only
b62f651… stephan 6418 ** 3: Fit both ways
b62f651… stephan 6419 */
c32f97e… drh 6420 static void pik_size_to_fit(Pik *p, PObj *pObj, PToken *pFit, int eWhich){
b62f651… stephan 6421 PNum w, h;
b62f651… stephan 6422 PBox bbox;
b62f651… stephan 6423 if( p->nErr ) return;
c32f97e… drh 6424 if( pObj==0 ) pObj = p->cur;
b62f651… stephan 6425
b62f651… stephan 6426 if( pObj->nTxt==0 ){
b62f651… stephan 6427 pik_error(0, pFit, "no text to fit to");
b62f651… stephan 6428 return;
b62f651… stephan 6429 }
b62f651… stephan 6430 if( pObj->type->xFit==0 ) return;
b62f651… stephan 6431 pik_bbox_init(&bbox);
b62f651… stephan 6432 pik_compute_layout_settings(p);
b62f651… stephan 6433 pik_append_txt(p, pObj, &bbox);
f4ec8e0… drh 6434 if( (eWhich & 1)!=0 || pObj->bAltAutoFit ){
f4ec8e0… drh 6435 w = (bbox.ne.x - bbox.sw.x) + p->charWidth;
f4ec8e0… drh 6436 }else{
f4ec8e0… drh 6437 w = 0;
f4ec8e0… drh 6438 }
f4ec8e0… drh 6439 if( (eWhich & 2)!=0 || pObj->bAltAutoFit ){
b62f651… stephan 6440 PNum h1, h2;
b62f651… stephan 6441 h1 = (bbox.ne.y - pObj->ptAt.y);
b62f651… stephan 6442 h2 = (pObj->ptAt.y - bbox.sw.y);
b62f651… stephan 6443 h = 2.0*( h1<h2 ? h2 : h1 ) + 0.5*p->charHeight;
b62f651… stephan 6444 }else{
b62f651… stephan 6445 h = 0;
b62f651… stephan 6446 }
b62f651… stephan 6447 pObj->type->xFit(p, pObj, w, h);
b62f651… stephan 6448 pObj->mProp |= A_FIT;
b62f651… stephan 6449 }
b62f651… stephan 6450
b62f651… stephan 6451 /* Set a local variable name to "val".
b62f651… stephan 6452 **
b62f651… stephan 6453 ** The name might be a built-in variable or a color name. In either case,
b62f651… stephan 6454 ** a new application-defined variable is set. Since app-defined variables
b62f651… stephan 6455 ** are searched first, this will override any built-in variables.
b62f651… stephan 6456 */
b62f651… stephan 6457 static void pik_set_var(Pik *p, PToken *pId, PNum val, PToken *pOp){
b62f651… stephan 6458 PVar *pVar = p->pVar;
b62f651… stephan 6459 while( pVar ){
b62f651… stephan 6460 if( pik_token_eq(pId,pVar->zName)==0 ) break;
b62f651… stephan 6461 pVar = pVar->pNext;
b62f651… stephan 6462 }
b62f651… stephan 6463 if( pVar==0 ){
b62f651… stephan 6464 char *z;
b62f651… stephan 6465 pVar = malloc( pId->n+1 + sizeof(*pVar) );
b62f651… stephan 6466 if( pVar==0 ){
b62f651… stephan 6467 pik_error(p, 0, 0);
b62f651… stephan 6468 return;
b62f651… stephan 6469 }
b62f651… stephan 6470 pVar->zName = z = (char*)&pVar[1];
b62f651… stephan 6471 memcpy(z, pId->z, pId->n);
b62f651… stephan 6472 z[pId->n] = 0;
b62f651… stephan 6473 pVar->pNext = p->pVar;
b62f651… stephan 6474 pVar->val = pik_value(p, pId->z, pId->n, 0);
b62f651… stephan 6475 p->pVar = pVar;
b62f651… stephan 6476 }
b62f651… stephan 6477 switch( pOp->eCode ){
b62f651… stephan 6478 case T_PLUS: pVar->val += val; break;
b62f651… stephan 6479 case T_STAR: pVar->val *= val; break;
b62f651… stephan 6480 case T_MINUS: pVar->val -= val; break;
b62f651… stephan 6481 case T_SLASH:
b62f651… stephan 6482 if( val==0.0 ){
b62f651… stephan 6483 pik_error(p, pOp, "division by zero");
b62f651… stephan 6484 }else{
b62f651… stephan 6485 pVar->val /= val;
b62f651… stephan 6486 }
b62f651… stephan 6487 break;
b62f651… stephan 6488 default: pVar->val = val; break;
b62f651… stephan 6489 }
b62f651… stephan 6490 p->bLayoutVars = 0; /* Clear the layout setting cache */
b62f651… stephan 6491 }
b62f651… stephan 6492
b62f651… stephan 6493 /*
b62f651… stephan 6494 ** Round a PNum into the nearest integer
b62f651… stephan 6495 */
b62f651… stephan 6496 static int pik_round(PNum v){
b62f651… stephan 6497 if( isnan(v) ) return 0;
b62f651… stephan 6498 if( v < -2147483647 ) return (-2147483647-1);
b62f651… stephan 6499 if( v >= 2147483647 ) return 2147483647;
b62f651… stephan 6500 return (int)v;
b62f651… stephan 6501 }
b62f651… stephan 6502
b62f651… stephan 6503 /*
b62f651… stephan 6504 ** Search for the variable named z[0..n-1] in:
b62f651… stephan 6505 **
b62f651… stephan 6506 ** * Application defined variables
b62f651… stephan 6507 ** * Built-in variables
b62f651… stephan 6508 **
b62f651… stephan 6509 ** Return the value of the variable if found. If not found
b62f651… stephan 6510 ** return 0.0. Also if pMiss is not NULL, then set it to 1
b62f651… stephan 6511 ** if not found.
b62f651… stephan 6512 **
b62f651… stephan 6513 ** This routine is a subroutine to pik_get_var(). But it is also
b62f651… stephan 6514 ** used by object implementations to look up (possibly overwritten)
b62f651… stephan 6515 ** values for built-in variables like "boxwid".
b62f651… stephan 6516 */
b62f651… stephan 6517 static PNum pik_value(Pik *p, const char *z, int n, int *pMiss){
b62f651… stephan 6518 PVar *pVar;
b62f651… stephan 6519 int first, last, mid, c;
b62f651… stephan 6520 for(pVar=p->pVar; pVar; pVar=pVar->pNext){
b62f651… stephan 6521 if( strncmp(pVar->zName,z,n)==0 && pVar->zName[n]==0 ){
b62f651… stephan 6522 return pVar->val;
b62f651… stephan 6523 }
b62f651… stephan 6524 }
b62f651… stephan 6525 first = 0;
b62f651… stephan 6526 last = count(aBuiltin)-1;
b62f651… stephan 6527 while( first<=last ){
b62f651… stephan 6528 mid = (first+last)/2;
b62f651… stephan 6529 c = strncmp(z,aBuiltin[mid].zName,n);
b62f651… stephan 6530 if( c==0 && aBuiltin[mid].zName[n] ) c = 1;
b62f651… stephan 6531 if( c==0 ) return aBuiltin[mid].val;
b62f651… stephan 6532 if( c>0 ){
b62f651… stephan 6533 first = mid+1;
b62f651… stephan 6534 }else{
b62f651… stephan 6535 last = mid-1;
b62f651… stephan 6536 }
b62f651… stephan 6537 }
b62f651… stephan 6538 if( pMiss ) *pMiss = 1;
b62f651… stephan 6539 return 0.0;
b62f651… stephan 6540 }
b62f651… stephan 6541 static int pik_value_int(Pik *p, const char *z, int n, int *pMiss){
b62f651… stephan 6542 return pik_round(pik_value(p,z,n,pMiss));
b62f651… stephan 6543 }
b62f651… stephan 6544
b62f651… stephan 6545 /*
b62f651… stephan 6546 ** Look up a color-name. Unlike other names in this program, the
b62f651… stephan 6547 ** color-names are not case sensitive. So "DarkBlue" and "darkblue"
b62f651… stephan 6548 ** and "DARKBLUE" all find the same value (139).
b62f651… stephan 6549 **
b62f651… stephan 6550 ** If not found, return -99.0. Also post an error if p!=NULL.
b62f651… stephan 6551 **
b62f651… stephan 6552 ** Special color names "None" and "Off" return -1.0 without causing
b62f651… stephan 6553 ** an error.
b62f651… stephan 6554 */
b62f651… stephan 6555 static PNum pik_lookup_color(Pik *p, PToken *pId){
b62f651… stephan 6556 int first, last, mid, c = 0;
b62f651… stephan 6557 first = 0;
b62f651… stephan 6558 last = count(aColor)-1;
b62f651… stephan 6559 while( first<=last ){
b62f651… stephan 6560 const char *zClr;
b62f651… stephan 6561 int c1, c2;
b62f651… stephan 6562 unsigned int i;
b62f651… stephan 6563 mid = (first+last)/2;
b62f651… stephan 6564 zClr = aColor[mid].zName;
b62f651… stephan 6565 for(i=0; i<pId->n; i++){
b62f651… stephan 6566 c1 = zClr[i]&0x7f;
c6285e1… stephan 6567 if( IsUpper(c1) ) c1 = ToLower(c1);
b62f651… stephan 6568 c2 = pId->z[i]&0x7f;
c6285e1… stephan 6569 if( IsUpper(c2) ) c2 = ToLower(c2);
b62f651… stephan 6570 c = c2 - c1;
b62f651… stephan 6571 if( c ) break;
b62f651… stephan 6572 }
b62f651… stephan 6573 if( c==0 && aColor[mid].zName[pId->n] ) c = -1;
b62f651… stephan 6574 if( c==0 ) return (double)aColor[mid].val;
b62f651… stephan 6575 if( c>0 ){
b62f651… stephan 6576 first = mid+1;
b62f651… stephan 6577 }else{
b62f651… stephan 6578 last = mid-1;
b62f651… stephan 6579 }
b62f651… stephan 6580 }
b62f651… stephan 6581 if( p ) pik_error(p, pId, "not a known color name");
b62f651… stephan 6582 return -99.0;
b62f651… stephan 6583 }
b62f651… stephan 6584
b62f651… stephan 6585 /* Get the value of a variable.
b62f651… stephan 6586 **
b62f651… stephan 6587 ** Search in order:
b62f651… stephan 6588 **
b62f651… stephan 6589 ** * Application defined variables
b62f651… stephan 6590 ** * Built-in variables
b62f651… stephan 6591 ** * Color names
b62f651… stephan 6592 **
b62f651… stephan 6593 ** If no such variable is found, throw an error.
b62f651… stephan 6594 */
b62f651… stephan 6595 static PNum pik_get_var(Pik *p, PToken *pId){
b62f651… stephan 6596 int miss = 0;
b62f651… stephan 6597 PNum v = pik_value(p, pId->z, pId->n, &miss);
b62f651… stephan 6598 if( miss==0 ) return v;
b62f651… stephan 6599 v = pik_lookup_color(0, pId);
b62f651… stephan 6600 if( v>-90.0 ) return v;
b62f651… stephan 6601 pik_error(p,pId,"no such variable");
b62f651… stephan 6602 return 0.0;
b62f651… stephan 6603 }
b62f651… stephan 6604
b62f651… stephan 6605 /* Convert a T_NTH token (ex: "2nd", "5th"} into a numeric value and
b62f651… stephan 6606 ** return that value. Throw an error if the value is too big.
b62f651… stephan 6607 */
b62f651… stephan 6608 static short int pik_nth_value(Pik *p, PToken *pNth){
b62f651… stephan 6609 int i = atoi(pNth->z);
b62f651… stephan 6610 if( i>1000 ){
b62f651… stephan 6611 pik_error(p, pNth, "value too big - max '1000th'");
b62f651… stephan 6612 i = 1;
b62f651… stephan 6613 }
b62f651… stephan 6614 if( i==0 && pik_token_eq(pNth,"first")==0 ) i = 1;
b62f651… stephan 6615 return (short int)i;
b62f651… stephan 6616 }
b62f651… stephan 6617
b62f651… stephan 6618 /* Search for the NTH object.
b62f651… stephan 6619 **
b62f651… stephan 6620 ** If pBasis is not NULL then it should be a [] object. Use the
b62f651… stephan 6621 ** sublist of that [] object for the search. If pBasis is not a []
b62f651… stephan 6622 ** object, then throw an error.
b62f651… stephan 6623 **
b62f651… stephan 6624 ** The pNth token describes the N-th search. The pNth->eCode value
b62f651… stephan 6625 ** is one more than the number of items to skip. It is negative
b62f651… stephan 6626 ** to search backwards. If pNth->eType==T_ID, then it is the name
b62f651… stephan 6627 ** of a class to search for. If pNth->eType==T_LB, then
b62f651… stephan 6628 ** search for a [] object. If pNth->eType==T_LAST, then search for
b62f651… stephan 6629 ** any type.
b62f651… stephan 6630 **
b62f651… stephan 6631 ** Raise an error if the item is not found.
b62f651… stephan 6632 */
b62f651… stephan 6633 static PObj *pik_find_nth(Pik *p, PObj *pBasis, PToken *pNth){
b62f651… stephan 6634 PList *pList;
b62f651… stephan 6635 int i, n;
b62f651… stephan 6636 const PClass *pClass;
b62f651… stephan 6637 if( pBasis==0 ){
b62f651… stephan 6638 pList = p->list;
b62f651… stephan 6639 }else{
b62f651… stephan 6640 pList = pBasis->pSublist;
b62f651… stephan 6641 }
b62f651… stephan 6642 if( pList==0 ){
b62f651… stephan 6643 pik_error(p, pNth, "no such object");
b62f651… stephan 6644 return 0;
b62f651… stephan 6645 }
b62f651… stephan 6646 if( pNth->eType==T_LAST ){
b62f651… stephan 6647 pClass = 0;
b62f651… stephan 6648 }else if( pNth->eType==T_LB ){
b62f651… stephan 6649 pClass = &sublistClass;
b62f651… stephan 6650 }else{
b62f651… stephan 6651 pClass = pik_find_class(pNth);
b62f651… stephan 6652 if( pClass==0 ){
b62f651… stephan 6653 pik_error(0, pNth, "no such object type");
b62f651… stephan 6654 return 0;
b62f651… stephan 6655 }
b62f651… stephan 6656 }
b62f651… stephan 6657 n = pNth->eCode;
b62f651… stephan 6658 if( n<0 ){
b62f651… stephan 6659 for(i=pList->n-1; i>=0; i--){
b62f651… stephan 6660 PObj *pObj = pList->a[i];
b62f651… stephan 6661 if( pClass && pObj->type!=pClass ) continue;
b62f651… stephan 6662 n++;
b62f651… stephan 6663 if( n==0 ){ return pObj; }
b62f651… stephan 6664 }
b62f651… stephan 6665 }else{
b62f651… stephan 6666 for(i=0; i<pList->n; i++){
b62f651… stephan 6667 PObj *pObj = pList->a[i];
b62f651… stephan 6668 if( pClass && pObj->type!=pClass ) continue;
b62f651… stephan 6669 n--;
b62f651… stephan 6670 if( n==0 ){ return pObj; }
b62f651… stephan 6671 }
b62f651… stephan 6672 }
b62f651… stephan 6673 pik_error(p, pNth, "no such object");
b62f651… stephan 6674 return 0;
b62f651… stephan 6675 }
b62f651… stephan 6676
b62f651… stephan 6677 /* Search for an object by name.
b62f651… stephan 6678 **
b62f651… stephan 6679 ** Search in pBasis->pSublist if pBasis is not NULL. If pBasis is NULL
b62f651… stephan 6680 ** then search in p->list.
b62f651… stephan 6681 */
b62f651… stephan 6682 static PObj *pik_find_byname(Pik *p, PObj *pBasis, PToken *pName){
b62f651… stephan 6683 PList *pList;
b62f651… stephan 6684 int i, j;
b62f651… stephan 6685 if( pBasis==0 ){
b62f651… stephan 6686 pList = p->list;
b62f651… stephan 6687 }else{
b62f651… stephan 6688 pList = pBasis->pSublist;
b62f651… stephan 6689 }
b62f651… stephan 6690 if( pList==0 ){
b62f651… stephan 6691 pik_error(p, pName, "no such object");
b62f651… stephan 6692 return 0;
b62f651… stephan 6693 }
b62f651… stephan 6694 /* First look explicitly tagged objects */
b62f651… stephan 6695 for(i=pList->n-1; i>=0; i--){
b62f651… stephan 6696 PObj *pObj = pList->a[i];
b62f651… stephan 6697 if( pObj->zName && pik_token_eq(pName,pObj->zName)==0 ){
b62f651… stephan 6698 p->lastRef = pObj;
b62f651… stephan 6699 return pObj;
b62f651… stephan 6700 }
b62f651… stephan 6701 }
b62f651… stephan 6702 /* If not found, do a second pass looking for any object containing
b62f651… stephan 6703 ** text which exactly matches pName */
b62f651… stephan 6704 for(i=pList->n-1; i>=0; i--){
b62f651… stephan 6705 PObj *pObj = pList->a[i];
b62f651… stephan 6706 for(j=0; j<pObj->nTxt; j++){
b62f651… stephan 6707 if( pObj->aTxt[j].n==pName->n+2
b62f651… stephan 6708 && memcmp(pObj->aTxt[j].z+1,pName->z,pName->n)==0 ){
b62f651… stephan 6709 p->lastRef = pObj;
b62f651… stephan 6710 return pObj;
b62f651… stephan 6711 }
b62f651… stephan 6712 }
b62f651… stephan 6713 }
b62f651… stephan 6714 pik_error(p, pName, "no such object");
b62f651… stephan 6715 return 0;
b62f651… stephan 6716 }
b62f651… stephan 6717
b62f651… stephan 6718 /* Change most of the settings for the current object to be the
b62f651… stephan 6719 ** same as the pOther object, or the most recent object of the same
b62f651… stephan 6720 ** type if pOther is NULL.
b62f651… stephan 6721 */
b62f651… stephan 6722 static void pik_same(Pik *p, PObj *pOther, PToken *pErrTok){
b62f651… stephan 6723 PObj *pObj = p->cur;
b62f651… stephan 6724 if( p->nErr ) return;
b62f651… stephan 6725 if( pOther==0 ){
b62f651… stephan 6726 int i;
b62f651… stephan 6727 for(i=(p->list ? p->list->n : 0)-1; i>=0; i--){
b62f651… stephan 6728 pOther = p->list->a[i];
b62f651… stephan 6729 if( pOther->type==pObj->type ) break;
b62f651… stephan 6730 }
b62f651… stephan 6731 if( i<0 ){
b62f651… stephan 6732 pik_error(p, pErrTok, "no prior objects of the same type");
b62f651… stephan 6733 return;
b62f651… stephan 6734 }
b62f651… stephan 6735 }
b62f651… stephan 6736 if( pOther->nPath && pObj->type->isLine ){
b62f651… stephan 6737 PNum dx, dy;
b62f651… stephan 6738 int i;
b62f651… stephan 6739 dx = p->aTPath[0].x - pOther->aPath[0].x;
b62f651… stephan 6740 dy = p->aTPath[0].y - pOther->aPath[0].y;
b62f651… stephan 6741 for(i=1; i<pOther->nPath; i++){
b62f651… stephan 6742 p->aTPath[i].x = pOther->aPath[i].x + dx;
b62f651… stephan 6743 p->aTPath[i].y = pOther->aPath[i].y + dy;
b62f651… stephan 6744 }
b62f651… stephan 6745 p->nTPath = pOther->nPath;
b62f651… stephan 6746 p->mTPath = 3;
b62f651… stephan 6747 p->samePath = 1;
b62f651… stephan 6748 }
b62f651… stephan 6749 if( !pObj->type->isLine ){
b62f651… stephan 6750 pObj->w = pOther->w;
b62f651… stephan 6751 pObj->h = pOther->h;
b62f651… stephan 6752 }
b62f651… stephan 6753 pObj->rad = pOther->rad;
b62f651… stephan 6754 pObj->sw = pOther->sw;
b62f651… stephan 6755 pObj->dashed = pOther->dashed;
b62f651… stephan 6756 pObj->dotted = pOther->dotted;
b62f651… stephan 6757 pObj->fill = pOther->fill;
b62f651… stephan 6758 pObj->color = pOther->color;
b62f651… stephan 6759 pObj->cw = pOther->cw;
b62f651… stephan 6760 pObj->larrow = pOther->larrow;
b62f651… stephan 6761 pObj->rarrow = pOther->rarrow;
b62f651… stephan 6762 pObj->bClose = pOther->bClose;
b62f651… stephan 6763 pObj->bChop = pOther->bChop;
b62f651… stephan 6764 pObj->iLayer = pOther->iLayer;
b62f651… stephan 6765 }
b62f651… stephan 6766
b62f651… stephan 6767
b62f651… stephan 6768 /* Return a "Place" associated with object pObj. If pEdge is NULL
b62f651… stephan 6769 ** return the center of the object. Otherwise, return the corner
b62f651… stephan 6770 ** described by pEdge.
b62f651… stephan 6771 */
b62f651… stephan 6772 static PPoint pik_place_of_elem(Pik *p, PObj *pObj, PToken *pEdge){
b62f651… stephan 6773 PPoint pt = cZeroPoint;
b62f651… stephan 6774 const PClass *pClass;
b62f651… stephan 6775 if( pObj==0 ) return pt;
b62f651… stephan 6776 if( pEdge==0 ){
b62f651… stephan 6777 return pObj->ptAt;
b62f651… stephan 6778 }
b62f651… stephan 6779 pClass = pObj->type;
b62f651… stephan 6780 if( pEdge->eType==T_EDGEPT || (pEdge->eEdge>0 && pEdge->eEdge<CP_END) ){
b62f651… stephan 6781 pt = pClass->xOffset(p, pObj, pEdge->eEdge);
b62f651… stephan 6782 pt.x += pObj->ptAt.x;
b62f651… stephan 6783 pt.y += pObj->ptAt.y;
b62f651… stephan 6784 return pt;
b62f651… stephan 6785 }
b62f651… stephan 6786 if( pEdge->eType==T_START ){
b62f651… stephan 6787 return pObj->ptEnter;
b62f651… stephan 6788 }else{
b62f651… stephan 6789 return pObj->ptExit;
b62f651… stephan 6790 }
b62f651… stephan 6791 }
b62f651… stephan 6792
b62f651… stephan 6793 /* Do a linear interpolation of two positions.
b62f651… stephan 6794 */
b62f651… stephan 6795 static PPoint pik_position_between(PNum x, PPoint p1, PPoint p2){
b62f651… stephan 6796 PPoint out;
b62f651… stephan 6797 out.x = p2.x*x + p1.x*(1.0 - x);
b62f651… stephan 6798 out.y = p2.y*x + p1.y*(1.0 - x);
b62f651… stephan 6799 return out;
b62f651… stephan 6800 }
b62f651… stephan 6801
b62f651… stephan 6802 /* Compute the position that is dist away from pt at an heading angle of r
b62f651… stephan 6803 **
b62f651… stephan 6804 ** The angle is a compass heading in degrees. North is 0 (or 360).
b62f651… stephan 6805 ** East is 90. South is 180. West is 270. And so forth.
b62f651… stephan 6806 */
b62f651… stephan 6807 static PPoint pik_position_at_angle(PNum dist, PNum r, PPoint pt){
b62f651… stephan 6808 r *= 0.017453292519943295769; /* degrees to radians */
b62f651… stephan 6809 pt.x += dist*sin(r);
b62f651… stephan 6810 pt.y += dist*cos(r);
b62f651… stephan 6811 return pt;
b62f651… stephan 6812 }
b62f651… stephan 6813
b62f651… stephan 6814 /* Compute the position that is dist away at a compass point
b62f651… stephan 6815 */
b62f651… stephan 6816 static PPoint pik_position_at_hdg(PNum dist, PToken *pD, PPoint pt){
b62f651… stephan 6817 return pik_position_at_angle(dist, pik_hdg_angle[pD->eEdge], pt);
b62f651… stephan 6818 }
b62f651… stephan 6819
b62f651… stephan 6820 /* Return the coordinates for the n-th vertex of a line.
b62f651… stephan 6821 */
b62f651… stephan 6822 static PPoint pik_nth_vertex(Pik *p, PToken *pNth, PToken *pErr, PObj *pObj){
b62f651… stephan 6823 static const PPoint zero = {0, 0};
b62f651… stephan 6824 int n;
b62f651… stephan 6825 if( p->nErr || pObj==0 ) return p->aTPath[0];
b62f651… stephan 6826 if( !pObj->type->isLine ){
b62f651… stephan 6827 pik_error(p, pErr, "object is not a line");
b62f651… stephan 6828 return zero;
b62f651… stephan 6829 }
b62f651… stephan 6830 n = atoi(pNth->z);
b62f651… stephan 6831 if( n<1 || n>pObj->nPath ){
b62f651… stephan 6832 pik_error(p, pNth, "no such vertex");
b62f651… stephan 6833 return zero;
b62f651… stephan 6834 }
b62f651… stephan 6835 return pObj->aPath[n-1];
b62f651… stephan 6836 }
b62f651… stephan 6837
b62f651… stephan 6838 /* Return the value of a property of an object.
b62f651… stephan 6839 */
b62f651… stephan 6840 static PNum pik_property_of(PObj *pObj, PToken *pProp){
b62f651… stephan 6841 PNum v = 0.0;
b62f651… stephan 6842 if( pObj ){
b62f651… stephan 6843 switch( pProp->eType ){
b62f651… stephan 6844 case T_HEIGHT: v = pObj->h; break;
b62f651… stephan 6845 case T_WIDTH: v = pObj->w; break;
b62f651… stephan 6846 case T_RADIUS: v = pObj->rad; break;
b62f651… stephan 6847 case T_DIAMETER: v = pObj->rad*2.0; break;
b62f651… stephan 6848 case T_THICKNESS: v = pObj->sw; break;
b62f651… stephan 6849 case T_DASHED: v = pObj->dashed; break;
b62f651… stephan 6850 case T_DOTTED: v = pObj->dotted; break;
b62f651… stephan 6851 case T_FILL: v = pObj->fill; break;
b62f651… stephan 6852 case T_COLOR: v = pObj->color; break;
b62f651… stephan 6853 case T_X: v = pObj->ptAt.x; break;
b62f651… stephan 6854 case T_Y: v = pObj->ptAt.y; break;
b62f651… stephan 6855 case T_TOP: v = pObj->bbox.ne.y; break;
b62f651… stephan 6856 case T_BOTTOM: v = pObj->bbox.sw.y; break;
b62f651… stephan 6857 case T_LEFT: v = pObj->bbox.sw.x; break;
b62f651… stephan 6858 case T_RIGHT: v = pObj->bbox.ne.x; break;
b62f651… stephan 6859 }
b62f651… stephan 6860 }
b62f651… stephan 6861 return v;
b62f651… stephan 6862 }
b62f651… stephan 6863
b62f651… stephan 6864 /* Compute one of the built-in functions
b62f651… stephan 6865 */
b62f651… stephan 6866 static PNum pik_func(Pik *p, PToken *pFunc, PNum x, PNum y){
b62f651… stephan 6867 PNum v = 0.0;
b62f651… stephan 6868 switch( pFunc->eCode ){
b80ae02… drh 6869 case FN_ABS: v = x<0.0 ? -x : x; break;
b62f651… stephan 6870 case FN_COS: v = cos(x); break;
b62f651… stephan 6871 case FN_INT: v = rint(x); break;
b62f651… stephan 6872 case FN_SIN: v = sin(x); break;
b62f651… stephan 6873 case FN_SQRT:
b62f651… stephan 6874 if( x<0.0 ){
b62f651… stephan 6875 pik_error(p, pFunc, "sqrt of negative value");
b62f651… stephan 6876 v = 0.0;
b62f651… stephan 6877 }else{
b62f651… stephan 6878 v = sqrt(x);
b62f651… stephan 6879 }
b62f651… stephan 6880 break;
b62f651… stephan 6881 case FN_MAX: v = x>y ? x : y; break;
b62f651… stephan 6882 case FN_MIN: v = x<y ? x : y; break;
b62f651… stephan 6883 default: v = 0.0;
b62f651… stephan 6884 }
b62f651… stephan 6885 return v;
b62f651… stephan 6886 }
b62f651… stephan 6887
b62f651… stephan 6888 /* Attach a name to an object
b62f651… stephan 6889 */
b62f651… stephan 6890 static void pik_elem_setname(Pik *p, PObj *pObj, PToken *pName){
b62f651… stephan 6891 if( pObj==0 ) return;
b62f651… stephan 6892 if( pName==0 ) return;
b62f651… stephan 6893 free(pObj->zName);
b62f651… stephan 6894 pObj->zName = malloc(pName->n+1);
b62f651… stephan 6895 if( pObj->zName==0 ){
b62f651… stephan 6896 pik_error(p,0,0);
b62f651… stephan 6897 }else{
b62f651… stephan 6898 memcpy(pObj->zName,pName->z,pName->n);
b62f651… stephan 6899 pObj->zName[pName->n] = 0;
b62f651… stephan 6900 }
b62f651… stephan 6901 return;
b62f651… stephan 6902 }
b62f651… stephan 6903
b62f651… stephan 6904 /*
b62f651… stephan 6905 ** Search for object located at *pCenter that has an xChop method and
b62f651… stephan 6906 ** that does not enclose point pOther.
b62f651… stephan 6907 **
b62f651… stephan 6908 ** Return a pointer to the object, or NULL if not found.
b62f651… stephan 6909 */
b62f651… stephan 6910 static PObj *pik_find_chopper(PList *pList, PPoint *pCenter, PPoint *pOther){
b62f651… stephan 6911 int i;
b62f651… stephan 6912 if( pList==0 ) return 0;
b62f651… stephan 6913 for(i=pList->n-1; i>=0; i--){
b62f651… stephan 6914 PObj *pObj = pList->a[i];
b62f651… stephan 6915 if( pObj->type->xChop!=0
b62f651… stephan 6916 && pObj->ptAt.x==pCenter->x
b62f651… stephan 6917 && pObj->ptAt.y==pCenter->y
b62f651… stephan 6918 && !pik_bbox_contains_point(&pObj->bbox, pOther)
b62f651… stephan 6919 ){
b62f651… stephan 6920 return pObj;
b62f651… stephan 6921 }else if( pObj->pSublist ){
b62f651… stephan 6922 pObj = pik_find_chopper(pObj->pSublist,pCenter,pOther);
b62f651… stephan 6923 if( pObj ) return pObj;
b62f651… stephan 6924 }
b62f651… stephan 6925 }
b62f651… stephan 6926 return 0;
b62f651… stephan 6927 }
b62f651… stephan 6928
b62f651… stephan 6929 /*
b62f651… stephan 6930 ** There is a line traveling from pFrom to pTo.
b62f651… stephan 6931 **
b62f651… stephan 6932 ** If pObj is not null and is a choppable object, then chop at
b62f651… stephan 6933 ** the boundary of pObj - where the line crosses the boundary
b62f651… stephan 6934 ** of pObj.
b62f651… stephan 6935 **
b62f651… stephan 6936 ** If pObj is NULL or has no xChop method, then search for some
b62f651… stephan 6937 ** other object centered at pTo that is choppable and use it
b62f651… stephan 6938 ** instead.
b62f651… stephan 6939 */
b62f651… stephan 6940 static void pik_autochop(Pik *p, PPoint *pFrom, PPoint *pTo, PObj *pObj){
b62f651… stephan 6941 if( pObj==0 || pObj->type->xChop==0 ){
b62f651… stephan 6942 pObj = pik_find_chopper(p->list, pTo, pFrom);
b62f651… stephan 6943 }
b62f651… stephan 6944 if( pObj ){
b62f651… stephan 6945 *pTo = pObj->type->xChop(p, pObj, pFrom);
b62f651… stephan 6946 }
b62f651… stephan 6947 }
b62f651… stephan 6948
b62f651… stephan 6949 /* This routine runs after all attributes have been received
b62f651… stephan 6950 ** on an object.
b62f651… stephan 6951 */
b62f651… stephan 6952 static void pik_after_adding_attributes(Pik *p, PObj *pObj){
b62f651… stephan 6953 int i;
b62f651… stephan 6954 PPoint ofst;
b62f651… stephan 6955 PNum dx, dy;
b62f651… stephan 6956
b62f651… stephan 6957 if( p->nErr ) return;
b62f651… stephan 6958
b62f651… stephan 6959 /* Position block objects */
b62f651… stephan 6960 if( pObj->type->isLine==0 ){
b62f651… stephan 6961 /* A height or width less than or equal to zero means "autofit".
b62f651… stephan 6962 ** Change the height or width to be big enough to contain the text,
b62f651… stephan 6963 */
b62f651… stephan 6964 if( pObj->h<=0.0 ){
b62f651… stephan 6965 if( pObj->nTxt==0 ){
b62f651… stephan 6966 pObj->h = 0.0;
b62f651… stephan 6967 }else if( pObj->w<=0.0 ){
c32f97e… drh 6968 pik_size_to_fit(p, pObj, &pObj->errTok, 3);
b62f651… stephan 6969 }else{
c32f97e… drh 6970 pik_size_to_fit(p, pObj, &pObj->errTok, 2);
b62f651… stephan 6971 }
b62f651… stephan 6972 }
b62f651… stephan 6973 if( pObj->w<=0.0 ){
b62f651… stephan 6974 if( pObj->nTxt==0 ){
b62f651… stephan 6975 pObj->w = 0.0;
b62f651… stephan 6976 }else{
c32f97e… drh 6977 pik_size_to_fit(p, pObj, &pObj->errTok, 1);
b62f651… stephan 6978 }
b62f651… stephan 6979 }
b62f651… stephan 6980 ofst = pik_elem_offset(p, pObj, pObj->eWith);
b62f651… stephan 6981 dx = (pObj->with.x - ofst.x) - pObj->ptAt.x;
b62f651… stephan 6982 dy = (pObj->with.y - ofst.y) - pObj->ptAt.y;
b62f651… stephan 6983 if( dx!=0 || dy!=0 ){
b62f651… stephan 6984 pik_elem_move(pObj, dx, dy);
b62f651… stephan 6985 }
b62f651… stephan 6986 }
b62f651… stephan 6987
b62f651… stephan 6988 /* For a line object with no movement specified, a single movement
b62f651… stephan 6989 ** of the default length in the current direction
b62f651… stephan 6990 */
b62f651… stephan 6991 if( pObj->type->isLine && p->nTPath<2 ){
b62f651… stephan 6992 pik_next_rpath(p, 0);
b62f651… stephan 6993 assert( p->nTPath==2 );
b62f651… stephan 6994 switch( pObj->inDir ){
b62f651… stephan 6995 default: p->aTPath[1].x += pObj->w; break;
b62f651… stephan 6996 case DIR_DOWN: p->aTPath[1].y -= pObj->h; break;
b62f651… stephan 6997 case DIR_LEFT: p->aTPath[1].x -= pObj->w; break;
b62f651… stephan 6998 case DIR_UP: p->aTPath[1].y += pObj->h; break;
b62f651… stephan 6999 }
b62f651… stephan 7000 if( pObj->type->xInit==arcInit ){
b62f651… stephan 7001 pObj->outDir = (pObj->inDir + (pObj->cw ? 1 : 3))%4;
b62f651… stephan 7002 p->eDir = (unsigned char)pObj->outDir;
b62f651… stephan 7003 switch( pObj->outDir ){
b62f651… stephan 7004 default: p->aTPath[1].x += pObj->w; break;
b62f651… stephan 7005 case DIR_DOWN: p->aTPath[1].y -= pObj->h; break;
b62f651… stephan 7006 case DIR_LEFT: p->aTPath[1].x -= pObj->w; break;
b62f651… stephan 7007 case DIR_UP: p->aTPath[1].y += pObj->h; break;
b62f651… stephan 7008 }
b62f651… stephan 7009 }
b62f651… stephan 7010 }
b62f651… stephan 7011
b62f651… stephan 7012 /* Initialize the bounding box prior to running xCheck */
b62f651… stephan 7013 pik_bbox_init(&pObj->bbox);
b62f651… stephan 7014
b62f651… stephan 7015 /* Run object-specific code */
b62f651… stephan 7016 if( pObj->type->xCheck!=0 ){
b62f651… stephan 7017 pObj->type->xCheck(p,pObj);
b62f651… stephan 7018 if( p->nErr ) return;
b62f651… stephan 7019 }
b62f651… stephan 7020
b62f651… stephan 7021 /* Compute final bounding box, entry and exit points, center
b62f651… stephan 7022 ** point (ptAt) and path for the object
b62f651… stephan 7023 */
b62f651… stephan 7024 if( pObj->type->isLine ){
b62f651… stephan 7025 pObj->aPath = malloc( sizeof(PPoint)*p->nTPath );
b62f651… stephan 7026 if( pObj->aPath==0 ){
b62f651… stephan 7027 pik_error(p, 0, 0);
b62f651… stephan 7028 return;
b62f651… stephan 7029 }else{
b62f651… stephan 7030 pObj->nPath = p->nTPath;
b62f651… stephan 7031 for(i=0; i<p->nTPath; i++){
b62f651… stephan 7032 pObj->aPath[i] = p->aTPath[i];
b62f651… stephan 7033 }
b62f651… stephan 7034 }
b62f651… stephan 7035
b62f651… stephan 7036 /* "chop" processing:
b62f651… stephan 7037 ** If the line goes to the center of an object with an
b62f651… stephan 7038 ** xChop method, then use the xChop method to trim the line.
b62f651… stephan 7039 */
b62f651… stephan 7040 if( pObj->bChop && pObj->nPath>=2 ){
b62f651… stephan 7041 int n = pObj->nPath;
b62f651… stephan 7042 pik_autochop(p, &pObj->aPath[n-2], &pObj->aPath[n-1], pObj->pTo);
b62f651… stephan 7043 pik_autochop(p, &pObj->aPath[1], &pObj->aPath[0], pObj->pFrom);
b62f651… stephan 7044 }
b62f651… stephan 7045
b62f651… stephan 7046 pObj->ptEnter = pObj->aPath[0];
b62f651… stephan 7047 pObj->ptExit = pObj->aPath[pObj->nPath-1];
b62f651… stephan 7048
b62f651… stephan 7049 /* Compute the center of the line based on the bounding box over
b62f651… stephan 7050 ** the vertexes. This is a difference from PIC. In Pikchr, the
b62f651… stephan 7051 ** center of a line is the center of its bounding box. In PIC, the
b62f651… stephan 7052 ** center of a line is halfway between its .start and .end. For
b62f651… stephan 7053 ** straight lines, this is the same point, but for multi-segment
b62f651… stephan 7054 ** lines the result is usually diferent */
b62f651… stephan 7055 for(i=0; i<pObj->nPath; i++){
b62f651… stephan 7056 pik_bbox_add_xy(&pObj->bbox, pObj->aPath[i].x, pObj->aPath[i].y);
b62f651… stephan 7057 }
b62f651… stephan 7058 pObj->ptAt.x = (pObj->bbox.ne.x + pObj->bbox.sw.x)/2.0;
b62f651… stephan 7059 pObj->ptAt.y = (pObj->bbox.ne.y + pObj->bbox.sw.y)/2.0;
b62f651… stephan 7060
b62f651… stephan 7061 /* Reset the width and height of the object to be the width and height
b62f651… stephan 7062 ** of the bounding box over vertexes */
b62f651… stephan 7063 pObj->w = pObj->bbox.ne.x - pObj->bbox.sw.x;
b62f651… stephan 7064 pObj->h = pObj->bbox.ne.y - pObj->bbox.sw.y;
b62f651… stephan 7065
b62f651… stephan 7066 /* If this is a polygon (if it has the "close" attribute), then
b62f651… stephan 7067 ** adjust the exit point */
b62f651… stephan 7068 if( pObj->bClose ){
b62f651… stephan 7069 /* For "closed" lines, the .end is one of the .e, .s, .w, or .n
b62f651… stephan 7070 ** points of the bounding box, as with block objects. */
b62f651… stephan 7071 pik_elem_set_exit(pObj, pObj->inDir);
b62f651… stephan 7072 }
b62f651… stephan 7073 }else{
b62f651… stephan 7074 PNum w2 = pObj->w/2.0;
b62f651… stephan 7075 PNum h2 = pObj->h/2.0;
b62f651… stephan 7076 pObj->ptEnter = pObj->ptAt;
b62f651… stephan 7077 pObj->ptExit = pObj->ptAt;
b62f651… stephan 7078 switch( pObj->inDir ){
b62f651… stephan 7079 default: pObj->ptEnter.x -= w2; break;
b62f651… stephan 7080 case DIR_LEFT: pObj->ptEnter.x += w2; break;
b62f651… stephan 7081 case DIR_UP: pObj->ptEnter.y -= h2; break;
b62f651… stephan 7082 case DIR_DOWN: pObj->ptEnter.y += h2; break;
b62f651… stephan 7083 }
b62f651… stephan 7084 switch( pObj->outDir ){
b62f651… stephan 7085 default: pObj->ptExit.x += w2; break;
b62f651… stephan 7086 case DIR_LEFT: pObj->ptExit.x -= w2; break;
b62f651… stephan 7087 case DIR_UP: pObj->ptExit.y += h2; break;
b62f651… stephan 7088 case DIR_DOWN: pObj->ptExit.y -= h2; break;
b62f651… stephan 7089 }
b62f651… stephan 7090 pik_bbox_add_xy(&pObj->bbox, pObj->ptAt.x - w2, pObj->ptAt.y - h2);
b62f651… stephan 7091 pik_bbox_add_xy(&pObj->bbox, pObj->ptAt.x + w2, pObj->ptAt.y + h2);
b62f651… stephan 7092 }
b62f651… stephan 7093 p->eDir = (unsigned char)pObj->outDir;
b62f651… stephan 7094 }
b62f651… stephan 7095
b62f651… stephan 7096 /* Show basic information about each object as a comment in the
b62f651… stephan 7097 ** generated HTML. Used for testing and debugging. Activated
b62f651… stephan 7098 ** by the (undocumented) "debug = 1;"
b62f651… stephan 7099 ** command.
b62f651… stephan 7100 */
b62f651… stephan 7101 static void pik_elem_render(Pik *p, PObj *pObj){
b62f651… stephan 7102 char *zDir;
b62f651… stephan 7103 if( pObj==0 ) return;
b62f651… stephan 7104 pik_append(p,"<!-- ", -1);
b62f651… stephan 7105 if( pObj->zName ){
b62f651… stephan 7106 pik_append_text(p, pObj->zName, -1, 0);
b62f651… stephan 7107 pik_append(p, ": ", 2);
b62f651… stephan 7108 }
b62f651… stephan 7109 pik_append_text(p, pObj->type->zName, -1, 0);
b62f651… stephan 7110 if( pObj->nTxt ){
b62f651… stephan 7111 pik_append(p, " \"", 2);
b62f651… stephan 7112 pik_append_text(p, pObj->aTxt[0].z+1, pObj->aTxt[0].n-2, 1);
b62f651… stephan 7113 pik_append(p, "\"", 1);
b62f651… stephan 7114 }
b62f651… stephan 7115 pik_append_num(p, " w=", pObj->w);
b62f651… stephan 7116 pik_append_num(p, " h=", pObj->h);
b62f651… stephan 7117 pik_append_point(p, " center=", &pObj->ptAt);
b62f651… stephan 7118 pik_append_point(p, " enter=", &pObj->ptEnter);
b62f651… stephan 7119 switch( pObj->outDir ){
b62f651… stephan 7120 default: zDir = " right"; break;
b62f651… stephan 7121 case DIR_LEFT: zDir = " left"; break;
b62f651… stephan 7122 case DIR_UP: zDir = " up"; break;
b62f651… stephan 7123 case DIR_DOWN: zDir = " down"; break;
b62f651… stephan 7124 }
b62f651… stephan 7125 pik_append_point(p, " exit=", &pObj->ptExit);
b62f651… stephan 7126 pik_append(p, zDir, -1);
b62f651… stephan 7127 pik_append(p, " -->\n", -1);
b62f651… stephan 7128 }
b62f651… stephan 7129
b62f651… stephan 7130 /* Render a list of objects
b62f651… stephan 7131 */
b62f651… stephan 7132 void pik_elist_render(Pik *p, PList *pList){
b62f651… stephan 7133 int i;
b62f651… stephan 7134 int iNextLayer = 0;
b62f651… stephan 7135 int iThisLayer;
b62f651… stephan 7136 int bMoreToDo;
b62f651… stephan 7137 int miss = 0;
b62f651… stephan 7138 int mDebug = pik_value_int(p, "debug", 5, 0);
b62f651… stephan 7139 PNum colorLabel;
b62f651… stephan 7140 do{
b62f651… stephan 7141 bMoreToDo = 0;
b62f651… stephan 7142 iThisLayer = iNextLayer;
b62f651… stephan 7143 iNextLayer = 0x7fffffff;
b62f651… stephan 7144 for(i=0; i<pList->n; i++){
b62f651… stephan 7145 PObj *pObj = pList->a[i];
b62f651… stephan 7146 void (*xRender)(Pik*,PObj*);
b62f651… stephan 7147 if( pObj->iLayer>iThisLayer ){
b62f651… stephan 7148 if( pObj->iLayer<iNextLayer ) iNextLayer = pObj->iLayer;
b62f651… stephan 7149 bMoreToDo = 1;
b62f651… stephan 7150 continue; /* Defer until another round */
b62f651… stephan 7151 }else if( pObj->iLayer<iThisLayer ){
b62f651… stephan 7152 continue;
b62f651… stephan 7153 }
b62f651… stephan 7154 if( mDebug & 1 ) pik_elem_render(p, pObj);
b62f651… stephan 7155 xRender = pObj->type->xRender;
b62f651… stephan 7156 if( xRender ){
b62f651… stephan 7157 xRender(p, pObj);
b62f651… stephan 7158 }
b62f651… stephan 7159 if( pObj->pSublist ){
b62f651… stephan 7160 pik_elist_render(p, pObj->pSublist);
b62f651… stephan 7161 }
b62f651… stephan 7162 }
b62f651… stephan 7163 }while( bMoreToDo );
b62f651… stephan 7164
b62f651… stephan 7165 /* If the color_debug_label value is defined, then go through
b62f651… stephan 7166 ** and paint a dot at every label location */
b62f651… stephan 7167 colorLabel = pik_value(p, "debug_label_color", 17, &miss);
b62f651… stephan 7168 if( miss==0 && colorLabel>=0.0 ){
b62f651… stephan 7169 PObj dot;
b62f651… stephan 7170 memset(&dot, 0, sizeof(dot));
b62f651… stephan 7171 dot.type = &noopClass;
b62f651… stephan 7172 dot.rad = 0.015;
b62f651… stephan 7173 dot.sw = 0.015;
b62f651… stephan 7174 dot.fill = colorLabel;
b62f651… stephan 7175 dot.color = colorLabel;
b62f651… stephan 7176 dot.nTxt = 1;
b62f651… stephan 7177 dot.aTxt[0].eCode = TP_ABOVE;
b62f651… stephan 7178 for(i=0; i<pList->n; i++){
b62f651… stephan 7179 PObj *pObj = pList->a[i];
b62f651… stephan 7180 if( pObj->zName==0 ) continue;
b62f651… stephan 7181 dot.ptAt = pObj->ptAt;
b62f651… stephan 7182 dot.aTxt[0].z = pObj->zName;
b62f651… stephan 7183 dot.aTxt[0].n = (int)strlen(pObj->zName);
b62f651… stephan 7184 dotRender(p, &dot);
b62f651… stephan 7185 }
b62f651… stephan 7186 }
b62f651… stephan 7187 }
b62f651… stephan 7188
b62f651… stephan 7189 /* Add all objects of the list pList to the bounding box
b62f651… stephan 7190 */
b62f651… stephan 7191 static void pik_bbox_add_elist(Pik *p, PList *pList, PNum wArrow){
b62f651… stephan 7192 int i;
b62f651… stephan 7193 for(i=0; i<pList->n; i++){
b62f651… stephan 7194 PObj *pObj = pList->a[i];
8ed25a3… drh 7195 if( pObj->sw>=0.0 ) pik_bbox_addbox(&p->bbox, &pObj->bbox);
b62f651… stephan 7196 pik_append_txt(p, pObj, &p->bbox);
b62f651… stephan 7197 if( pObj->pSublist ) pik_bbox_add_elist(p, pObj->pSublist, wArrow);
b62f651… stephan 7198
b62f651… stephan 7199
b62f651… stephan 7200 /* Expand the bounding box to account for arrowheads on lines */
b62f651… stephan 7201 if( pObj->type->isLine && pObj->nPath>0 ){
b62f651… stephan 7202 if( pObj->larrow ){
b62f651… stephan 7203 pik_bbox_addellipse(&p->bbox, pObj->aPath[0].x, pObj->aPath[0].y,
b62f651… stephan 7204 wArrow, wArrow);
b62f651… stephan 7205 }
b62f651… stephan 7206 if( pObj->rarrow ){
b62f651… stephan 7207 int j = pObj->nPath-1;
b62f651… stephan 7208 pik_bbox_addellipse(&p->bbox, pObj->aPath[j].x, pObj->aPath[j].y,
b62f651… stephan 7209 wArrow, wArrow);
b62f651… stephan 7210 }
b62f651… stephan 7211 }
b62f651… stephan 7212 }
b62f651… stephan 7213 }
b62f651… stephan 7214
b62f651… stephan 7215 /* Recompute key layout parameters from variables. */
b62f651… stephan 7216 static void pik_compute_layout_settings(Pik *p){
b62f651… stephan 7217 PNum thickness; /* Line thickness */
b62f651… stephan 7218 PNum wArrow; /* Width of arrowheads */
b62f651… stephan 7219
b62f651… stephan 7220 /* Set up rendering parameters */
b62f651… stephan 7221 if( p->bLayoutVars ) return;
b62f651… stephan 7222 thickness = pik_value(p,"thickness",9,0);
b62f651… stephan 7223 if( thickness<=0.01 ) thickness = 0.01;
b62f651… stephan 7224 wArrow = 0.5*pik_value(p,"arrowwid",8,0);
b62f651… stephan 7225 p->wArrow = wArrow/thickness;
b62f651… stephan 7226 p->hArrow = pik_value(p,"arrowht",7,0)/thickness;
b62f651… stephan 7227 p->fontScale = pik_value(p,"fontscale",9,0);
b62f651… stephan 7228 if( p->fontScale<=0.0 ) p->fontScale = 1.0;
b62f651… stephan 7229 p->rScale = 144.0;
b62f651… stephan 7230 p->charWidth = pik_value(p,"charwid",7,0)*p->fontScale;
b62f651… stephan 7231 p->charHeight = pik_value(p,"charht",6,0)*p->fontScale;
b62f651… stephan 7232 p->bLayoutVars = 1;
b62f651… stephan 7233 }
b62f651… stephan 7234
b62f651… stephan 7235 /* Render a list of objects. Write the SVG into p->zOut.
b62f651… stephan 7236 ** Delete the input object_list before returnning.
b62f651… stephan 7237 */
b62f651… stephan 7238 static void pik_render(Pik *p, PList *pList){
b62f651… stephan 7239 if( pList==0 ) return;
b62f651… stephan 7240 if( p->nErr==0 ){
b62f651… stephan 7241 PNum thickness; /* Stroke width */
b62f651… stephan 7242 PNum margin; /* Extra bounding box margin */
b62f651… stephan 7243 PNum w, h; /* Drawing width and height */
b62f651… stephan 7244 PNum wArrow;
b62f651… stephan 7245 PNum pikScale; /* Value of the "scale" variable */
b62f651… stephan 7246 int miss = 0;
b62f651… stephan 7247
b62f651… stephan 7248 /* Set up rendering parameters */
b62f651… stephan 7249 pik_compute_layout_settings(p);
b62f651… stephan 7250 thickness = pik_value(p,"thickness",9,0);
b62f651… stephan 7251 if( thickness<=0.01 ) thickness = 0.01;
b62f651… stephan 7252 margin = pik_value(p,"margin",6,0);
b62f651… stephan 7253 margin += thickness;
b62f651… stephan 7254 wArrow = p->wArrow*thickness;
b62f651… stephan 7255 miss = 0;
b62f651… stephan 7256 p->fgcolor = pik_value_int(p,"fgcolor",7,&miss);
b62f651… stephan 7257 if( miss ){
b62f651… stephan 7258 PToken t;
b62f651… stephan 7259 t.z = "fgcolor";
b62f651… stephan 7260 t.n = 7;
b62f651… stephan 7261 p->fgcolor = pik_round(pik_lookup_color(0, &t));
b62f651… stephan 7262 }
b62f651… stephan 7263 miss = 0;
b62f651… stephan 7264 p->bgcolor = pik_value_int(p,"bgcolor",7,&miss);
b62f651… stephan 7265 if( miss ){
b62f651… stephan 7266 PToken t;
b62f651… stephan 7267 t.z = "bgcolor";
b62f651… stephan 7268 t.n = 7;
b62f651… stephan 7269 p->bgcolor = pik_round(pik_lookup_color(0, &t));
b62f651… stephan 7270 }
b62f651… stephan 7271
b62f651… stephan 7272 /* Compute a bounding box over all objects so that we can know
b62f651… stephan 7273 ** how big to declare the SVG canvas */
b62f651… stephan 7274 pik_bbox_init(&p->bbox);
b62f651… stephan 7275 pik_bbox_add_elist(p, pList, wArrow);
b62f651… stephan 7276
b62f651… stephan 7277 /* Expand the bounding box slightly to account for line thickness
b62f651… stephan 7278 ** and the optional "margin = EXPR" setting. */
b62f651… stephan 7279 p->bbox.ne.x += margin + pik_value(p,"rightmargin",11,0);
b62f651… stephan 7280 p->bbox.ne.y += margin + pik_value(p,"topmargin",9,0);
b62f651… stephan 7281 p->bbox.sw.x -= margin + pik_value(p,"leftmargin",10,0);
b62f651… stephan 7282 p->bbox.sw.y -= margin + pik_value(p,"bottommargin",12,0);
b62f651… stephan 7283
b62f651… stephan 7284 /* Output the SVG */
4a26cb9… drh 7285 pik_append(p, "<svg xmlns='http://www.w3.org/2000/svg'"
4a26cb9… drh 7286 " style='font-size:initial;'",-1);
b62f651… stephan 7287 if( p->zClass ){
b62f651… stephan 7288 pik_append(p, " class=\"", -1);
b62f651… stephan 7289 pik_append(p, p->zClass, -1);
b62f651… stephan 7290 pik_append(p, "\"", 1);
b62f651… stephan 7291 }
b62f651… stephan 7292 w = p->bbox.ne.x - p->bbox.sw.x;
b62f651… stephan 7293 h = p->bbox.ne.y - p->bbox.sw.y;
b62f651… stephan 7294 p->wSVG = pik_round(p->rScale*w);
b62f651… stephan 7295 p->hSVG = pik_round(p->rScale*h);
b62f651… stephan 7296 pikScale = pik_value(p,"scale",5,0);
b62f651… stephan 7297 if( pikScale>=0.001 && pikScale<=1000.0
b62f651… stephan 7298 && (pikScale<0.99 || pikScale>1.01)
b62f651… stephan 7299 ){
b62f651… stephan 7300 p->wSVG = pik_round(p->wSVG*pikScale);
b62f651… stephan 7301 p->hSVG = pik_round(p->hSVG*pikScale);
b62f651… stephan 7302 pik_append_num(p, " width=\"", p->wSVG);
b62f651… stephan 7303 pik_append_num(p, "\" height=\"", p->hSVG);
b62f651… stephan 7304 pik_append(p, "\"", 1);
b62f651… stephan 7305 }
b62f651… stephan 7306 pik_append_dis(p, " viewBox=\"0 0 ",w,"");
dd20f34… drh 7307 pik_append_dis(p, " ",h,"\"");
dd20f34… drh 7308 pik_append(p, " data-pikchr-date=\"" MANIFEST_ISODATE "\">\n", -1);
b62f651… stephan 7309 pik_elist_render(p, pList);
b62f651… stephan 7310 pik_append(p,"</svg>\n", -1);
b62f651… stephan 7311 }else{
b62f651… stephan 7312 p->wSVG = -1;
b62f651… stephan 7313 p->hSVG = -1;
b62f651… stephan 7314 }
b62f651… stephan 7315 pik_elist_free(p, pList);
b62f651… stephan 7316 }
b62f651… stephan 7317
b62f651… stephan 7318
b62f651… stephan 7319
b62f651… stephan 7320 /*
b62f651… stephan 7321 ** An array of this structure defines a list of keywords.
b62f651… stephan 7322 */
b62f651… stephan 7323 typedef struct PikWord {
b62f651… stephan 7324 char *zWord; /* Text of the keyword */
b62f651… stephan 7325 unsigned char nChar; /* Length of keyword text in bytes */
b62f651… stephan 7326 unsigned char eType; /* Token code */
b62f651… stephan 7327 unsigned char eCode; /* Extra code for the token */
b62f651… stephan 7328 unsigned char eEdge; /* CP_* code for corner/edge keywords */
b62f651… stephan 7329 } PikWord;
b62f651… stephan 7330
b62f651… stephan 7331 /*
b62f651… stephan 7332 ** Keywords
b62f651… stephan 7333 */
b62f651… stephan 7334 static const PikWord pik_keywords[] = {
b62f651… stephan 7335 { "above", 5, T_ABOVE, 0, 0 },
b62f651… stephan 7336 { "abs", 3, T_FUNC1, FN_ABS, 0 },
b62f651… stephan 7337 { "aligned", 7, T_ALIGNED, 0, 0 },
b62f651… stephan 7338 { "and", 3, T_AND, 0, 0 },
b62f651… stephan 7339 { "as", 2, T_AS, 0, 0 },
b62f651… stephan 7340 { "assert", 6, T_ASSERT, 0, 0 },
b62f651… stephan 7341 { "at", 2, T_AT, 0, 0 },
b62f651… stephan 7342 { "behind", 6, T_BEHIND, 0, 0 },
b62f651… stephan 7343 { "below", 5, T_BELOW, 0, 0 },
b62f651… stephan 7344 { "between", 7, T_BETWEEN, 0, 0 },
b62f651… stephan 7345 { "big", 3, T_BIG, 0, 0 },
b62f651… stephan 7346 { "bold", 4, T_BOLD, 0, 0 },
b62f651… stephan 7347 { "bot", 3, T_EDGEPT, 0, CP_S },
b62f651… stephan 7348 { "bottom", 6, T_BOTTOM, 0, CP_S },
b62f651… stephan 7349 { "c", 1, T_EDGEPT, 0, CP_C },
b62f651… stephan 7350 { "ccw", 3, T_CCW, 0, 0 },
b62f651… stephan 7351 { "center", 6, T_CENTER, 0, CP_C },
b62f651… stephan 7352 { "chop", 4, T_CHOP, 0, 0 },
b62f651… stephan 7353 { "close", 5, T_CLOSE, 0, 0 },
b62f651… stephan 7354 { "color", 5, T_COLOR, 0, 0 },
b62f651… stephan 7355 { "cos", 3, T_FUNC1, FN_COS, 0 },
b62f651… stephan 7356 { "cw", 2, T_CW, 0, 0 },
b62f651… stephan 7357 { "dashed", 6, T_DASHED, 0, 0 },
b62f651… stephan 7358 { "define", 6, T_DEFINE, 0, 0 },
b62f651… stephan 7359 { "diameter", 8, T_DIAMETER, 0, 0 },
b62f651… stephan 7360 { "dist", 4, T_DIST, 0, 0 },
b62f651… stephan 7361 { "dotted", 6, T_DOTTED, 0, 0 },
b62f651… stephan 7362 { "down", 4, T_DOWN, DIR_DOWN, 0 },
b62f651… stephan 7363 { "e", 1, T_EDGEPT, 0, CP_E },
b62f651… stephan 7364 { "east", 4, T_EDGEPT, 0, CP_E },
b62f651… stephan 7365 { "end", 3, T_END, 0, CP_END },
b62f651… stephan 7366 { "even", 4, T_EVEN, 0, 0 },
b62f651… stephan 7367 { "fill", 4, T_FILL, 0, 0 },
b62f651… stephan 7368 { "first", 5, T_NTH, 0, 0 },
b62f651… stephan 7369 { "fit", 3, T_FIT, 0, 0 },
b62f651… stephan 7370 { "from", 4, T_FROM, 0, 0 },
b62f651… stephan 7371 { "go", 2, T_GO, 0, 0 },
b62f651… stephan 7372 { "heading", 7, T_HEADING, 0, 0 },
b62f651… stephan 7373 { "height", 6, T_HEIGHT, 0, 0 },
b62f651… stephan 7374 { "ht", 2, T_HEIGHT, 0, 0 },
b62f651… stephan 7375 { "in", 2, T_IN, 0, 0 },
b62f651… stephan 7376 { "int", 3, T_FUNC1, FN_INT, 0 },
b62f651… stephan 7377 { "invis", 5, T_INVIS, 0, 0 },
b62f651… stephan 7378 { "invisible", 9, T_INVIS, 0, 0 },
b62f651… stephan 7379 { "italic", 6, T_ITALIC, 0, 0 },
b62f651… stephan 7380 { "last", 4, T_LAST, 0, 0 },
b62f651… stephan 7381 { "left", 4, T_LEFT, DIR_LEFT, CP_W },
b62f651… stephan 7382 { "ljust", 5, T_LJUST, 0, 0 },
b62f651… stephan 7383 { "max", 3, T_FUNC2, FN_MAX, 0 },
b62f651… stephan 7384 { "min", 3, T_FUNC2, FN_MIN, 0 },
43eefe6… drh 7385 { "mono", 4, T_MONO, 0, 0 },
43eefe6… drh 7386 { "monospace", 9, T_MONO, 0, 0 },
b62f651… stephan 7387 { "n", 1, T_EDGEPT, 0, CP_N },
b62f651… stephan 7388 { "ne", 2, T_EDGEPT, 0, CP_NE },
b62f651… stephan 7389 { "north", 5, T_EDGEPT, 0, CP_N },
b62f651… stephan 7390 { "nw", 2, T_EDGEPT, 0, CP_NW },
b62f651… stephan 7391 { "of", 2, T_OF, 0, 0 },
dd20f34… drh 7392 { "pikchr_date",11, T_ISODATE, 0, 0, },
b62f651… stephan 7393 { "previous", 8, T_LAST, 0, 0, },
b62f651… stephan 7394 { "print", 5, T_PRINT, 0, 0 },
b62f651… stephan 7395 { "rad", 3, T_RADIUS, 0, 0 },
b62f651… stephan 7396 { "radius", 6, T_RADIUS, 0, 0 },
b62f651… stephan 7397 { "right", 5, T_RIGHT, DIR_RIGHT, CP_E },
b62f651… stephan 7398 { "rjust", 5, T_RJUST, 0, 0 },
b62f651… stephan 7399 { "s", 1, T_EDGEPT, 0, CP_S },
b62f651… stephan 7400 { "same", 4, T_SAME, 0, 0 },
b62f651… stephan 7401 { "se", 2, T_EDGEPT, 0, CP_SE },
b62f651… stephan 7402 { "sin", 3, T_FUNC1, FN_SIN, 0 },
b62f651… stephan 7403 { "small", 5, T_SMALL, 0, 0 },
b62f651… stephan 7404 { "solid", 5, T_SOLID, 0, 0 },
b62f651… stephan 7405 { "south", 5, T_EDGEPT, 0, CP_S },
b62f651… stephan 7406 { "sqrt", 4, T_FUNC1, FN_SQRT, 0 },
b62f651… stephan 7407 { "start", 5, T_START, 0, CP_START },
b62f651… stephan 7408 { "sw", 2, T_EDGEPT, 0, CP_SW },
b62f651… stephan 7409 { "t", 1, T_TOP, 0, CP_N },
b62f651… stephan 7410 { "the", 3, T_THE, 0, 0 },
b62f651… stephan 7411 { "then", 4, T_THEN, 0, 0 },
b62f651… stephan 7412 { "thick", 5, T_THICK, 0, 0 },
b62f651… stephan 7413 { "thickness", 9, T_THICKNESS, 0, 0 },
b62f651… stephan 7414 { "thin", 4, T_THIN, 0, 0 },
b62f651… stephan 7415 { "this", 4, T_THIS, 0, 0 },
b62f651… stephan 7416 { "to", 2, T_TO, 0, 0 },
b62f651… stephan 7417 { "top", 3, T_TOP, 0, CP_N },
b62f651… stephan 7418 { "until", 5, T_UNTIL, 0, 0 },
b62f651… stephan 7419 { "up", 2, T_UP, DIR_UP, 0 },
b62f651… stephan 7420 { "vertex", 6, T_VERTEX, 0, 0 },
b62f651… stephan 7421 { "w", 1, T_EDGEPT, 0, CP_W },
b62f651… stephan 7422 { "way", 3, T_WAY, 0, 0 },
b62f651… stephan 7423 { "west", 4, T_EDGEPT, 0, CP_W },
b62f651… stephan 7424 { "wid", 3, T_WIDTH, 0, 0 },
b62f651… stephan 7425 { "width", 5, T_WIDTH, 0, 0 },
b62f651… stephan 7426 { "with", 4, T_WITH, 0, 0 },
b62f651… stephan 7427 { "x", 1, T_X, 0, 0 },
b62f651… stephan 7428 { "y", 1, T_Y, 0, 0 },
b62f651… stephan 7429 };
b62f651… stephan 7430
b62f651… stephan 7431 /*
b62f651… stephan 7432 ** Search a PikWordlist for the given keyword. Return a pointer to the
b62f651… stephan 7433 ** keyword entry found. Or return 0 if not found.
b62f651… stephan 7434 */
b62f651… stephan 7435 static const PikWord *pik_find_word(
b62f651… stephan 7436 const char *zIn, /* Word to search for */
b62f651… stephan 7437 int n, /* Length of zIn */
b62f651… stephan 7438 const PikWord *aList, /* List to search */
b62f651… stephan 7439 int nList /* Number of entries in aList */
b62f651… stephan 7440 ){
b62f651… stephan 7441 int first = 0;
b62f651… stephan 7442 int last = nList-1;
b62f651… stephan 7443 while( first<=last ){
b62f651… stephan 7444 int mid = (first + last)/2;
b62f651… stephan 7445 int sz = aList[mid].nChar;
b62f651… stephan 7446 int c = strncmp(zIn, aList[mid].zWord, sz<n ? sz : n);
b62f651… stephan 7447 if( c==0 ){
b62f651… stephan 7448 c = n - sz;
b62f651… stephan 7449 if( c==0 ) return &aList[mid];
b62f651… stephan 7450 }
b62f651… stephan 7451 if( c<0 ){
b62f651… stephan 7452 last = mid-1;
b62f651… stephan 7453 }else{
b62f651… stephan 7454 first = mid+1;
b62f651… stephan 7455 }
b62f651… stephan 7456 }
b62f651… stephan 7457 return 0;
b62f651… stephan 7458 }
b62f651… stephan 7459
b62f651… stephan 7460 /*
b62f651… stephan 7461 ** Set a symbolic debugger breakpoint on this routine to receive a
b62f651… stephan 7462 ** breakpoint when the "#breakpoint" token is parsed.
b62f651… stephan 7463 */
b62f651… stephan 7464 static void pik_breakpoint(const unsigned char *z){
b62f651… stephan 7465 /* Prevent C compilers from optimizing out this routine. */
b62f651… stephan 7466 if( z[2]=='X' ) exit(1);
b62f651… stephan 7467 }
b62f651… stephan 7468
b62f651… stephan 7469
b62f651… stephan 7470 /*
b62f651… stephan 7471 ** Return the length of next token. The token starts on
b62f651… stephan 7472 ** the pToken->z character. Fill in other fields of the
b62f651… stephan 7473 ** pToken object as appropriate.
b62f651… stephan 7474 */
b62f651… stephan 7475 static int pik_token_length(PToken *pToken, int bAllowCodeBlock){
b62f651… stephan 7476 const unsigned char *z = (const unsigned char*)pToken->z;
b62f651… stephan 7477 int i;
b62f651… stephan 7478 unsigned char c, c2;
b62f651… stephan 7479 switch( z[0] ){
b62f651… stephan 7480 case '\\': {
b62f651… stephan 7481 pToken->eType = T_WHITESPACE;
b62f651… stephan 7482 for(i=1; z[i]=='\r' || z[i]==' ' || z[i]=='\t'; i++){}
b62f651… stephan 7483 if( z[i]=='\n' ) return i+1;
b62f651… stephan 7484 pToken->eType = T_ERROR;
b62f651… stephan 7485 return 1;
b62f651… stephan 7486 }
b62f651… stephan 7487 case ';':
b62f651… stephan 7488 case '\n': {
b62f651… stephan 7489 pToken->eType = T_EOL;
b62f651… stephan 7490 return 1;
b62f651… stephan 7491 }
b62f651… stephan 7492 case '"': {
b62f651… stephan 7493 for(i=1; (c = z[i])!=0; i++){
b62f651… stephan 7494 if( c=='\\' ){
b62f651… stephan 7495 if( z[i+1]==0 ) break;
b62f651… stephan 7496 i++;
b62f651… stephan 7497 continue;
b62f651… stephan 7498 }
b62f651… stephan 7499 if( c=='"' ){
b62f651… stephan 7500 pToken->eType = T_STRING;
b62f651… stephan 7501 return i+1;
b62f651… stephan 7502 }
b62f651… stephan 7503 }
b62f651… stephan 7504 pToken->eType = T_ERROR;
b62f651… stephan 7505 return i;
b62f651… stephan 7506 }
b62f651… stephan 7507 case ' ':
b62f651… stephan 7508 case '\t':
b62f651… stephan 7509 case '\f':
b62f651… stephan 7510 case '\r': {
390e001… drh 7511 for(i=1; (c = z[i])==' ' || c=='\t' || c=='\r' || c=='\f'; i++){}
b62f651… stephan 7512 pToken->eType = T_WHITESPACE;
b62f651… stephan 7513 return i;
b62f651… stephan 7514 }
b62f651… stephan 7515 case '#': {
b62f651… stephan 7516 for(i=1; (c = z[i])!=0 && c!='\n'; i++){}
b62f651… stephan 7517 pToken->eType = T_WHITESPACE;
b62f651… stephan 7518 /* If the comment is "#breakpoint" then invoke the pik_breakpoint()
b62f651… stephan 7519 ** routine. The pik_breakpoint() routie is a no-op that serves as
b62f651… stephan 7520 ** a convenient place to set a gdb breakpoint when debugging. */
b62f651… stephan 7521 if( strncmp((const char*)z,"#breakpoint",11)==0 ) pik_breakpoint(z);
b62f651… stephan 7522 return i;
b62f651… stephan 7523 }
b62f651… stephan 7524 case '/': {
b62f651… stephan 7525 if( z[1]=='*' ){
b62f651… stephan 7526 for(i=2; z[i]!=0 && (z[i]!='*' || z[i+1]!='/'); i++){}
b62f651… stephan 7527 if( z[i]=='*' ){
b62f651… stephan 7528 pToken->eType = T_WHITESPACE;
b62f651… stephan 7529 return i+2;
b62f651… stephan 7530 }else{
b62f651… stephan 7531 pToken->eType = T_ERROR;
b62f651… stephan 7532 return i;
b62f651… stephan 7533 }
b62f651… stephan 7534 }else if( z[1]=='/' ){
b62f651… stephan 7535 for(i=2; z[i]!=0 && z[i]!='\n'; i++){}
b62f651… stephan 7536 pToken->eType = T_WHITESPACE;
b62f651… stephan 7537 return i;
b62f651… stephan 7538 }else if( z[1]=='=' ){
b62f651… stephan 7539 pToken->eType = T_ASSIGN;
b62f651… stephan 7540 pToken->eCode = T_SLASH;
b62f651… stephan 7541 return 2;
b62f651… stephan 7542 }else{
b62f651… stephan 7543 pToken->eType = T_SLASH;
b62f651… stephan 7544 return 1;
b62f651… stephan 7545 }
b62f651… stephan 7546 }
b62f651… stephan 7547 case '+': {
b62f651… stephan 7548 if( z[1]=='=' ){
b62f651… stephan 7549 pToken->eType = T_ASSIGN;
b62f651… stephan 7550 pToken->eCode = T_PLUS;
b62f651… stephan 7551 return 2;
b62f651… stephan 7552 }
b62f651… stephan 7553 pToken->eType = T_PLUS;
b62f651… stephan 7554 return 1;
b62f651… stephan 7555 }
b62f651… stephan 7556 case '*': {
b62f651… stephan 7557 if( z[1]=='=' ){
b62f651… stephan 7558 pToken->eType = T_ASSIGN;
b62f651… stephan 7559 pToken->eCode = T_STAR;
b62f651… stephan 7560 return 2;
b62f651… stephan 7561 }
b62f651… stephan 7562 pToken->eType = T_STAR;
b62f651… stephan 7563 return 1;
b62f651… stephan 7564 }
b62f651… stephan 7565 case '%': { pToken->eType = T_PERCENT; return 1; }
b62f651… stephan 7566 case '(': { pToken->eType = T_LP; return 1; }
b62f651… stephan 7567 case ')': { pToken->eType = T_RP; return 1; }
b62f651… stephan 7568 case '[': { pToken->eType = T_LB; return 1; }
b62f651… stephan 7569 case ']': { pToken->eType = T_RB; return 1; }
b62f651… stephan 7570 case ',': { pToken->eType = T_COMMA; return 1; }
b62f651… stephan 7571 case ':': { pToken->eType = T_COLON; return 1; }
b62f651… stephan 7572 case '>': { pToken->eType = T_GT; return 1; }
b62f651… stephan 7573 case '=': {
b62f651… stephan 7574 if( z[1]=='=' ){
b62f651… stephan 7575 pToken->eType = T_EQ;
b62f651… stephan 7576 return 2;
b62f651… stephan 7577 }
b62f651… stephan 7578 pToken->eType = T_ASSIGN;
b62f651… stephan 7579 pToken->eCode = T_ASSIGN;
b62f651… stephan 7580 return 1;
b62f651… stephan 7581 }
b62f651… stephan 7582 case '-': {
b62f651… stephan 7583 if( z[1]=='>' ){
b62f651… stephan 7584 pToken->eType = T_RARROW;
b62f651… stephan 7585 return 2;
b62f651… stephan 7586 }else if( z[1]=='=' ){
b62f651… stephan 7587 pToken->eType = T_ASSIGN;
b62f651… stephan 7588 pToken->eCode = T_MINUS;
b62f651… stephan 7589 return 2;
b62f651… stephan 7590 }else{
b62f651… stephan 7591 pToken->eType = T_MINUS;
b62f651… stephan 7592 return 1;
b62f651… stephan 7593 }
b62f651… stephan 7594 }
b62f651… stephan 7595 case '<': {
b62f651… stephan 7596 if( z[1]=='-' ){
b62f651… stephan 7597 if( z[2]=='>' ){
b62f651… stephan 7598 pToken->eType = T_LRARROW;
b62f651… stephan 7599 return 3;
b62f651… stephan 7600 }else{
b62f651… stephan 7601 pToken->eType = T_LARROW;
b62f651… stephan 7602 return 2;
b62f651… stephan 7603 }
b62f651… stephan 7604 }else{
b62f651… stephan 7605 pToken->eType = T_LT;
b62f651… stephan 7606 return 1;
b62f651… stephan 7607 }
b62f651… stephan 7608 }
b62f651… stephan 7609 case 0xe2: {
b62f651… stephan 7610 if( z[1]==0x86 ){
b62f651… stephan 7611 if( z[2]==0x90 ){
b62f651… stephan 7612 pToken->eType = T_LARROW; /* <- */
b62f651… stephan 7613 return 3;
b62f651… stephan 7614 }
b62f651… stephan 7615 if( z[2]==0x92 ){
b62f651… stephan 7616 pToken->eType = T_RARROW; /* -> */
b62f651… stephan 7617 return 3;
b62f651… stephan 7618 }
b62f651… stephan 7619 if( z[2]==0x94 ){
b62f651… stephan 7620 pToken->eType = T_LRARROW; /* <-> */
b62f651… stephan 7621 return 3;
b62f651… stephan 7622 }
b62f651… stephan 7623 }
b62f651… stephan 7624 pToken->eType = T_ERROR;
b62f651… stephan 7625 return 1;
b62f651… stephan 7626 }
b62f651… stephan 7627 case '{': {
b62f651… stephan 7628 int len, depth;
b62f651… stephan 7629 i = 1;
b62f651… stephan 7630 if( bAllowCodeBlock ){
b62f651… stephan 7631 depth = 1;
b62f651… stephan 7632 while( z[i] && depth>0 ){
b62f651… stephan 7633 PToken x;
b62f651… stephan 7634 x.z = (char*)(z+i);
b62f651… stephan 7635 len = pik_token_length(&x, 0);
b62f651… stephan 7636 if( len==1 ){
b62f651… stephan 7637 if( z[i]=='{' ) depth++;
b62f651… stephan 7638 if( z[i]=='}' ) depth--;
b62f651… stephan 7639 }
b62f651… stephan 7640 i += len;
b62f651… stephan 7641 }
b62f651… stephan 7642 }else{
b62f651… stephan 7643 depth = 0;
b62f651… stephan 7644 }
b62f651… stephan 7645 if( depth ){
b62f651… stephan 7646 pToken->eType = T_ERROR;
b62f651… stephan 7647 return 1;
b62f651… stephan 7648 }
b62f651… stephan 7649 pToken->eType = T_CODEBLOCK;
b62f651… stephan 7650 return i;
b62f651… stephan 7651 }
b62f651… stephan 7652 case '&': {
b62f651… stephan 7653 static const struct {
b62f651… stephan 7654 int nByte; /* Number of bytes in zEntity */
b62f651… stephan 7655 int eCode; /* Corresponding token code */
b62f651… stephan 7656 const char *zEntity; /* Name of the HTML entity */
b62f651… stephan 7657 } aEntity[] = {
b62f651… stephan 7658 /* 123456789 1234567 */
b62f651… stephan 7659 { 6, T_RARROW, "&rarr;" }, /* Same as -> */
b62f651… stephan 7660 { 12, T_RARROW, "&rightarrow;" }, /* Same as -> */
b62f651… stephan 7661 { 6, T_LARROW, "&larr;" }, /* Same as <- */
b62f651… stephan 7662 { 11, T_LARROW, "&leftarrow;" }, /* Same as <- */
b62f651… stephan 7663 { 16, T_LRARROW, "&leftrightarrow;" }, /* Same as <-> */
b62f651… stephan 7664 };
b62f651… stephan 7665 unsigned int i;
b62f651… stephan 7666 for(i=0; i<sizeof(aEntity)/sizeof(aEntity[0]); i++){
b62f651… stephan 7667 if( strncmp((const char*)z,aEntity[i].zEntity,aEntity[i].nByte)==0 ){
b62f651… stephan 7668 pToken->eType = aEntity[i].eCode;
b62f651… stephan 7669 return aEntity[i].nByte;
b62f651… stephan 7670 }
b62f651… stephan 7671 }
b62f651… stephan 7672 pToken->eType = T_ERROR;
b62f651… stephan 7673 return 1;
b62f651… stephan 7674 }
b62f651… stephan 7675 default: {
b62f651… stephan 7676 c = z[0];
b62f651… stephan 7677 if( c=='.' ){
b62f651… stephan 7678 unsigned char c1 = z[1];
c6285e1… stephan 7679 if( IsLower(c1) ){
b62f651… stephan 7680 const PikWord *pFound;
b62f651… stephan 7681 for(i=2; (c = z[i])>='a' && c<='z'; i++){}
b62f651… stephan 7682 pFound = pik_find_word((const char*)z+1, i-1,
b62f651… stephan 7683 pik_keywords, count(pik_keywords));
b62f651… stephan 7684 if( pFound && (pFound->eEdge>0 ||
b62f651… stephan 7685 pFound->eType==T_EDGEPT ||
b62f651… stephan 7686 pFound->eType==T_START ||
b62f651… stephan 7687 pFound->eType==T_END )
b62f651… stephan 7688 ){
b62f651… stephan 7689 /* Dot followed by something that is a 2-D place value */
b62f651… stephan 7690 pToken->eType = T_DOT_E;
b62f651… stephan 7691 }else if( pFound && (pFound->eType==T_X || pFound->eType==T_Y) ){
b62f651… stephan 7692 /* Dot followed by "x" or "y" */
b62f651… stephan 7693 pToken->eType = T_DOT_XY;
b62f651… stephan 7694 }else{
b62f651… stephan 7695 /* Any other "dot" */
b62f651… stephan 7696 pToken->eType = T_DOT_L;
b62f651… stephan 7697 }
b62f651… stephan 7698 return 1;
c6285e1… stephan 7699 }else if( IsDigit(c1) ){
b62f651… stephan 7700 i = 0;
b62f651… stephan 7701 /* no-op. Fall through to number handling */
c6285e1… stephan 7702 }else if( IsUpper(c1) ){
c6285e1… stephan 7703 for(i=2; (c = z[i])!=0 && (IsAlnum(c) || c=='_'); i++){}
b62f651… stephan 7704 pToken->eType = T_DOT_U;
b62f651… stephan 7705 return 1;
b62f651… stephan 7706 }else{
b62f651… stephan 7707 pToken->eType = T_ERROR;
b62f651… stephan 7708 return 1;
b62f651… stephan 7709 }
b62f651… stephan 7710 }
b62f651… stephan 7711 if( (c>='0' && c<='9') || c=='.' ){
b62f651… stephan 7712 int nDigit;
b62f651… stephan 7713 int isInt = 1;
b62f651… stephan 7714 if( c!='.' ){
b62f651… stephan 7715 nDigit = 1;
b62f651… stephan 7716 for(i=1; (c = z[i])>='0' && c<='9'; i++){ nDigit++; }
b62f651… stephan 7717 if( i==1 && (c=='x' || c=='X') ){
c6285e1… stephan 7718 for(i=2; (c = z[i])!=0 && IsXDigit(c); i++){}
b62f651… stephan 7719 pToken->eType = T_NUMBER;
b62f651… stephan 7720 return i;
b62f651… stephan 7721 }
b62f651… stephan 7722 }else{
b62f651… stephan 7723 isInt = 0;
b62f651… stephan 7724 nDigit = 0;
b62f651… stephan 7725 i = 0;
b62f651… stephan 7726 }
b62f651… stephan 7727 if( c=='.' ){
b62f651… stephan 7728 isInt = 0;
b62f651… stephan 7729 for(i++; (c = z[i])>='0' && c<='9'; i++){ nDigit++; }
b62f651… stephan 7730 }
b62f651… stephan 7731 if( nDigit==0 ){
b62f651… stephan 7732 pToken->eType = T_ERROR;
b62f651… stephan 7733 return i;
b62f651… stephan 7734 }
b62f651… stephan 7735 if( c=='e' || c=='E' ){
b62f651… stephan 7736 int iBefore = i;
b62f651… stephan 7737 i++;
b62f651… stephan 7738 c2 = z[i];
b62f651… stephan 7739 if( c2=='+' || c2=='-' ){
b62f651… stephan 7740 i++;
b62f651… stephan 7741 c2 = z[i];
b62f651… stephan 7742 }
b62f651… stephan 7743 if( c2<'0' || c>'9' ){
b62f651… stephan 7744 /* This is not an exp */
b62f651… stephan 7745 i = iBefore;
b62f651… stephan 7746 }else{
b62f651… stephan 7747 i++;
b62f651… stephan 7748 isInt = 0;
b62f651… stephan 7749 while( (c = z[i])>='0' && c<='9' ){ i++; }
b62f651… stephan 7750 }
b62f651… stephan 7751 }
b62f651… stephan 7752 c2 = c ? z[i+1] : 0;
b62f651… stephan 7753 if( isInt ){
b62f651… stephan 7754 if( (c=='t' && c2=='h')
b62f651… stephan 7755 || (c=='r' && c2=='d')
b62f651… stephan 7756 || (c=='n' && c2=='d')
b62f651… stephan 7757 || (c=='s' && c2=='t')
b62f651… stephan 7758 ){
b62f651… stephan 7759 pToken->eType = T_NTH;
b62f651… stephan 7760 return i+2;
b62f651… stephan 7761 }
b62f651… stephan 7762 }
b62f651… stephan 7763 if( (c=='i' && c2=='n')
b62f651… stephan 7764 || (c=='c' && c2=='m')
b62f651… stephan 7765 || (c=='m' && c2=='m')
b62f651… stephan 7766 || (c=='p' && c2=='t')
b62f651… stephan 7767 || (c=='p' && c2=='x')
b62f651… stephan 7768 || (c=='p' && c2=='c')
b62f651… stephan 7769 ){
b62f651… stephan 7770 i += 2;
b62f651… stephan 7771 }
b62f651… stephan 7772 pToken->eType = T_NUMBER;
b62f651… stephan 7773 return i;
c6285e1… stephan 7774 }else if( IsLower(c) ){
b62f651… stephan 7775 const PikWord *pFound;
c6285e1… stephan 7776 for(i=1; (c = z[i])!=0 && (IsAlnum(c) || c=='_'); i++){}
b62f651… stephan 7777 pFound = pik_find_word((const char*)z, i,
b62f651… stephan 7778 pik_keywords, count(pik_keywords));
b62f651… stephan 7779 if( pFound ){
b62f651… stephan 7780 pToken->eType = pFound->eType;
b62f651… stephan 7781 pToken->eCode = pFound->eCode;
b62f651… stephan 7782 pToken->eEdge = pFound->eEdge;
b62f651… stephan 7783 return i;
b62f651… stephan 7784 }
b62f651… stephan 7785 pToken->n = i;
b62f651… stephan 7786 if( pik_find_class(pToken)!=0 ){
b62f651… stephan 7787 pToken->eType = T_CLASSNAME;
b62f651… stephan 7788 }else{
b62f651… stephan 7789 pToken->eType = T_ID;
b62f651… stephan 7790 }
b62f651… stephan 7791 return i;
b62f651… stephan 7792 }else if( c>='A' && c<='Z' ){
c6285e1… stephan 7793 for(i=1; (c = z[i])!=0 && (IsAlnum(c) || c=='_'); i++){}
b62f651… stephan 7794 pToken->eType = T_PLACENAME;
b62f651… stephan 7795 return i;
c6285e1… stephan 7796 }else if( c=='$' && z[1]>='1' && z[1]<='9' && !IsDigit(z[2]) ){
b62f651… stephan 7797 pToken->eType = T_PARAMETER;
b62f651… stephan 7798 pToken->eCode = z[1] - '1';
b62f651… stephan 7799 return 2;
b62f651… stephan 7800 }else if( c=='_' || c=='$' || c=='@' ){
c6285e1… stephan 7801 for(i=1; (c = z[i])!=0 && (IsAlnum(c) || c=='_'); i++){}
b62f651… stephan 7802 pToken->eType = T_ID;
b62f651… stephan 7803 return i;
b62f651… stephan 7804 }else{
b62f651… stephan 7805 pToken->eType = T_ERROR;
b62f651… stephan 7806 return 1;
b62f651… stephan 7807 }
b62f651… stephan 7808 }
b62f651… stephan 7809 }
b62f651… stephan 7810 }
b62f651… stephan 7811
b62f651… stephan 7812 /*
b62f651… stephan 7813 ** Return a pointer to the next non-whitespace token after pThis.
b62f651… stephan 7814 ** This is used to help form error messages.
b62f651… stephan 7815 */
b62f651… stephan 7816 static PToken pik_next_semantic_token(PToken *pThis){
b62f651… stephan 7817 PToken x;
b62f651… stephan 7818 int sz;
b62f651… stephan 7819 int i = pThis->n;
b62f651… stephan 7820 memset(&x, 0, sizeof(x));
b62f651… stephan 7821 x.z = pThis->z;
b62f651… stephan 7822 while(1){
b62f651… stephan 7823 x.z = pThis->z + i;
b62f651… stephan 7824 sz = pik_token_length(&x, 1);
b62f651… stephan 7825 if( x.eType!=T_WHITESPACE ){
b62f651… stephan 7826 x.n = sz;
b62f651… stephan 7827 return x;
b62f651… stephan 7828 }
b62f651… stephan 7829 i += sz;
b62f651… stephan 7830 }
b62f651… stephan 7831 }
b62f651… stephan 7832
b62f651… stephan 7833 /* Parser arguments to a macro invocation
b62f651… stephan 7834 **
b62f651… stephan 7835 ** (arg1, arg2, ...)
b62f651… stephan 7836 **
b62f651… stephan 7837 ** Arguments are comma-separated, except that commas within string
b62f651… stephan 7838 ** literals or with (...), {...}, or [...] do not count. The argument
b62f651… stephan 7839 ** list begins and ends with parentheses. There can be at most 9
b62f651… stephan 7840 ** arguments.
b62f651… stephan 7841 **
b62f651… stephan 7842 ** Return the number of bytes in the argument list.
b62f651… stephan 7843 */
b62f651… stephan 7844 static unsigned int pik_parse_macro_args(
b62f651… stephan 7845 Pik *p,
b62f651… stephan 7846 const char *z, /* Start of the argument list */
b62f651… stephan 7847 int n, /* Available bytes */
b62f651… stephan 7848 PToken *args, /* Fill in with the arguments */
b62f651… stephan 7849 PToken *pOuter /* Arguments of the next outer context, or NULL */
b62f651… stephan 7850 ){
b62f651… stephan 7851 int nArg = 0;
b62f651… stephan 7852 int i, j, sz;
b62f651… stephan 7853 int iStart;
b62f651… stephan 7854 int depth = 0;
b62f651… stephan 7855 PToken x;
b62f651… stephan 7856 if( z[0]!='(' ) return 0;
b62f651… stephan 7857 args[0].z = z+1;
b62f651… stephan 7858 iStart = 1;
b62f651… stephan 7859 for(i=1; i<n && z[i]!=')'; i+=sz){
b62f651… stephan 7860 x.z = z+i;
b62f651… stephan 7861 sz = pik_token_length(&x, 0);
b62f651… stephan 7862 if( sz!=1 ) continue;
b62f651… stephan 7863 if( z[i]==',' && depth<=0 ){
b62f651… stephan 7864 args[nArg].n = i - iStart;
b62f651… stephan 7865 if( nArg==8 ){
b62f651… stephan 7866 x.z = z;
b62f651… stephan 7867 x.n = 1;
b62f651… stephan 7868 pik_error(p, &x, "too many macro arguments - max 9");
b62f651… stephan 7869 return 0;
b62f651… stephan 7870 }
b62f651… stephan 7871 nArg++;
b62f651… stephan 7872 args[nArg].z = z+i+1;
b62f651… stephan 7873 iStart = i+1;
b62f651… stephan 7874 depth = 0;
b62f651… stephan 7875 }else if( z[i]=='(' || z[i]=='{' || z[i]=='[' ){
b62f651… stephan 7876 depth++;
b62f651… stephan 7877 }else if( z[i]==')' || z[i]=='}' || z[i]==']' ){
b62f651… stephan 7878 depth--;
b62f651… stephan 7879 }
b62f651… stephan 7880 }
b62f651… stephan 7881 if( z[i]==')' ){
b62f651… stephan 7882 args[nArg].n = i - iStart;
adc7bfc… drh 7883 /* Remove leading and trailing whitespace from each argument (including
adc7bfc… drh 7884 ** backslash-escaped newlines). If what remains is one of $1, $2, ... $9
adc7bfc… drh 7885 ** then transfer the corresponding argument from the outer context */
b62f651… stephan 7886 for(j=0; j<=nArg; j++){
b62f651… stephan 7887 PToken *t = &args[j];
adc7bfc… drh 7888 while( (t->n>0 && IsSpace(t->z[0]))
adc7bfc… drh 7889 || (t->n>1 && t->z[0]=='\\' && IsSpace(t->z[1]))
adc7bfc… drh 7890 ){
adc7bfc… drh 7891 t->z++;
adc7bfc… drh 7892 t->n--;
adc7bfc… drh 7893 }
adc7bfc… drh 7894 while( t->n>0 && IsSpace(t->z[t->n-1]) ){
adc7bfc… drh 7895 t->n--;
adc7bfc… drh 7896 if( t->n>0 && t->z[t->n-1]=='\\' ) t->n--;
adc7bfc… drh 7897 }
b62f651… stephan 7898 if( t->n==2 && t->z[0]=='$' && t->z[1]>='1' && t->z[1]<='9' ){
b62f651… stephan 7899 if( pOuter ) *t = pOuter[t->z[1]-'1'];
b62f651… stephan 7900 else t->n = 0;
b62f651… stephan 7901 }
b62f651… stephan 7902 }
b62f651… stephan 7903 return i+1;
b62f651… stephan 7904 }
b62f651… stephan 7905 x.z = z;
b62f651… stephan 7906 x.n = 1;
b62f651… stephan 7907 pik_error(p, &x, "unterminated macro argument list");
b62f651… stephan 7908 return 0;
b62f651… stephan 7909 }
b62f651… stephan 7910
b62f651… stephan 7911 /*
b62f651… stephan 7912 ** Split up the content of a PToken into multiple tokens and
b62f651… stephan 7913 ** send each to the parser.
b62f651… stephan 7914 */
b62f651… stephan 7915 void pik_tokenize(Pik *p, PToken *pIn, yyParser *pParser, PToken *aParam){
b62f651… stephan 7916 unsigned int i;
b62f651… stephan 7917 int sz = 0;
b62f651… stephan 7918 PToken token;
b62f651… stephan 7919 PMacro *pMac;
b62f651… stephan 7920 for(i=0; i<pIn->n && pIn->z[i] && p->nErr==0; i+=sz){
b62f651… stephan 7921 token.eCode = 0;
b62f651… stephan 7922 token.eEdge = 0;
b62f651… stephan 7923 token.z = pIn->z + i;
b62f651… stephan 7924 sz = pik_token_length(&token, 1);
b62f651… stephan 7925 if( token.eType==T_WHITESPACE ){
b62f651… stephan 7926 /* no-op */
b62f651… stephan 7927 }else if( sz>50000 ){
b62f651… stephan 7928 token.n = 1;
b62f651… stephan 7929 pik_error(p, &token, "token is too long - max length 50000 bytes");
b62f651… stephan 7930 break;
b62f651… stephan 7931 }else if( token.eType==T_ERROR ){
b62f651… stephan 7932 token.n = (unsigned short)(sz & 0xffff);
b62f651… stephan 7933 pik_error(p, &token, "unrecognized token");
b62f651… stephan 7934 break;
b62f651… stephan 7935 }else if( sz+i>pIn->n ){
b62f651… stephan 7936 token.n = pIn->n - i;
b62f651… stephan 7937 pik_error(p, &token, "syntax error");
b62f651… stephan 7938 break;
b62f651… stephan 7939 }else if( token.eType==T_PARAMETER ){
b62f651… stephan 7940 /* Substitute a parameter into the input stream */
b62f651… stephan 7941 if( aParam==0 || aParam[token.eCode].n==0 ){
b62f651… stephan 7942 continue;
b62f651… stephan 7943 }
b62f651… stephan 7944 token.n = (unsigned short)(sz & 0xffff);
b62f651… stephan 7945 if( p->nCtx>=count(p->aCtx) ){
b62f651… stephan 7946 pik_error(p, &token, "macros nested too deep");
b62f651… stephan 7947 }else{
b62f651… stephan 7948 p->aCtx[p->nCtx++] = token;
b62f651… stephan 7949 pik_tokenize(p, &aParam[token.eCode], pParser, 0);
b62f651… stephan 7950 p->nCtx--;
b62f651… stephan 7951 }
b62f651… stephan 7952 }else if( token.eType==T_ID
b62f651… stephan 7953 && (token.n = (unsigned short)(sz & 0xffff),
b62f651… stephan 7954 (pMac = pik_find_macro(p,&token))!=0)
b62f651… stephan 7955 ){
b62f651… stephan 7956 PToken args[9];
b62f651… stephan 7957 unsigned int j = i+sz;
b62f651… stephan 7958 if( pMac->inUse ){
b62f651… stephan 7959 pik_error(p, &pMac->macroName, "recursive macro definition");
b62f651… stephan 7960 break;
b62f651… stephan 7961 }
b62f651… stephan 7962 token.n = (short int)(sz & 0xffff);
b62f651… stephan 7963 if( p->nCtx>=count(p->aCtx) ){
b62f651… stephan 7964 pik_error(p, &token, "macros nested too deep");
b62f651… stephan 7965 break;
b62f651… stephan 7966 }
b62f651… stephan 7967 pMac->inUse = 1;
b62f651… stephan 7968 memset(args, 0, sizeof(args));
b62f651… stephan 7969 p->aCtx[p->nCtx++] = token;
b62f651… stephan 7970 sz += pik_parse_macro_args(p, pIn->z+j, pIn->n-j, args, aParam);
b62f651… stephan 7971 pik_tokenize(p, &pMac->macroBody, pParser, args);
b62f651… stephan 7972 p->nCtx--;
b62f651… stephan 7973 pMac->inUse = 0;
b62f651… stephan 7974 }else{
b62f651… stephan 7975 #if 0
b62f651… stephan 7976 printf("******** Token %s (%d): \"%.*s\" **************\n",
b62f651… stephan 7977 yyTokenName[token.eType], token.eType,
c6285e1… stephan 7978 (int)(IsSpace(token.z[0]) ? 0 : sz), token.z);
b62f651… stephan 7979 #endif
b62f651… stephan 7980 token.n = (unsigned short)(sz & 0xffff);
f753041… drh 7981 if( p->nToken++ > PIKCHR_TOKEN_LIMIT ){
f753041… drh 7982 pik_error(p, &token, "script is too complex");
f753041… drh 7983 break;
f753041… drh 7984 }
dd20f34… drh 7985 if( token.eType==T_ISODATE ){
dd20f34… drh 7986 token.z = "\"" MANIFEST_ISODATE "\"";
dd20f34… drh 7987 token.n = sizeof(MANIFEST_ISODATE)+1;
dd20f34… drh 7988 token.eType = T_STRING;
dd20f34… drh 7989 }
b62f651… stephan 7990 pik_parser(pParser, token.eType, token);
b62f651… stephan 7991 }
b62f651… stephan 7992 }
dd20f34… drh 7993 }
dd20f34… drh 7994
dd20f34… drh 7995 /*
dd20f34… drh 7996 ** Return the version name.
dd20f34… drh 7997 */
dd20f34… drh 7998 const char *pikchr_version(void)
dd20f34… drh 7999 /* Emscripten workaround, else it chokes on the inlined version */;
dd20f34… drh 8000
dd20f34… drh 8001 const char *pikchr_version(void){
dd20f34… drh 8002 return RELEASE_VERSION " " MANIFEST_ISODATE;
b62f651… stephan 8003 }
b62f651… stephan 8004
b62f651… stephan 8005 /*
b62f651… stephan 8006 ** Parse the PIKCHR script contained in zText[]. Return a rendering. Or
b62f651… stephan 8007 ** if an error is encountered, return the error text. The error message
b62f651… stephan 8008 ** is HTML formatted. So regardless of what happens, the return text
b62f651… stephan 8009 ** is safe to be insertd into an HTML output stream.
b62f651… stephan 8010 **
b62f651… stephan 8011 ** If pnWidth and pnHeight are not NULL, then this routine writes the
b62f651… stephan 8012 ** width and height of the <SVG> object into the integers that they
b62f651… stephan 8013 ** point to. A value of -1 is written if an error is seen.
b62f651… stephan 8014 **
b62f651… stephan 8015 ** If zClass is not NULL, then it is a class name to be included in
b62f651… stephan 8016 ** the <SVG> markup.
b62f651… stephan 8017 **
b62f651… stephan 8018 ** The returned string is contained in memory obtained from malloc()
b62f651… stephan 8019 ** and should be released by the caller.
b62f651… stephan 8020 */
b62f651… stephan 8021 char *pikchr(
b62f651… stephan 8022 const char *zText, /* Input PIKCHR source text. zero-terminated */
b62f651… stephan 8023 const char *zClass, /* Add class="%s" to <svg> markup */
b62f651… stephan 8024 unsigned int mFlags, /* Flags used to influence rendering behavior */
b62f651… stephan 8025 int *pnWidth, /* Write width of <svg> here, if not NULL */
b62f651… stephan 8026 int *pnHeight /* Write height here, if not NULL */
b62f651… stephan 8027 ){
b62f651… stephan 8028 Pik s;
b62f651… stephan 8029 yyParser sParse;
b62f651… stephan 8030
b62f651… stephan 8031 memset(&s, 0, sizeof(s));
b62f651… stephan 8032 s.sIn.z = zText;
b62f651… stephan 8033 s.sIn.n = (unsigned int)strlen(zText);
b62f651… stephan 8034 s.eDir = DIR_RIGHT;
b62f651… stephan 8035 s.zClass = zClass;
b62f651… stephan 8036 s.mFlags = mFlags;
b62f651… stephan 8037 pik_parserInit(&sParse, &s);
b62f651… stephan 8038 #if 0
b62f651… stephan 8039 pik_parserTrace(stdout, "parser: ");
b62f651… stephan 8040 #endif
b62f651… stephan 8041 pik_tokenize(&s, &s.sIn, &sParse, 0);
b62f651… stephan 8042 if( s.nErr==0 ){
b62f651… stephan 8043 PToken token;
b62f651… stephan 8044 memset(&token,0,sizeof(token));
b62f651… stephan 8045 token.z = zText + (s.sIn.n>0 ? s.sIn.n-1 : 0);
b62f651… stephan 8046 token.n = 1;
b62f651… stephan 8047 pik_parser(&sParse, 0, token);
b62f651… stephan 8048 }
b62f651… stephan 8049 pik_parserFinalize(&sParse);
b62f651… stephan 8050 if( s.zOut==0 && s.nErr==0 ){
b62f651… stephan 8051 pik_append(&s, "<!-- empty pikchr diagram -->\n", -1);
b62f651… stephan 8052 }
b62f651… stephan 8053 while( s.pVar ){
b62f651… stephan 8054 PVar *pNext = s.pVar->pNext;
b62f651… stephan 8055 free(s.pVar);
b62f651… stephan 8056 s.pVar = pNext;
b62f651… stephan 8057 }
b62f651… stephan 8058 while( s.pMacros ){
b62f651… stephan 8059 PMacro *pNext = s.pMacros->pNext;
b62f651… stephan 8060 free(s.pMacros);
b62f651… stephan 8061 s.pMacros = pNext;
b62f651… stephan 8062 }
b62f651… stephan 8063 if( pnWidth ) *pnWidth = s.nErr ? -1 : s.wSVG;
b62f651… stephan 8064 if( pnHeight ) *pnHeight = s.nErr ? -1 : s.hSVG;
b62f651… stephan 8065 if( s.zOut ){
b62f651… stephan 8066 s.zOut[s.nOut] = 0;
b62f651… stephan 8067 s.zOut = realloc(s.zOut, s.nOut+1);
b62f651… stephan 8068 }
b62f651… stephan 8069 return s.zOut;
b62f651… stephan 8070 }
b62f651… stephan 8071
b62f651… stephan 8072 #if defined(PIKCHR_FUZZ)
b62f651… stephan 8073 #include <stdint.h>
b62f651… stephan 8074 int LLVMFuzzerTestOneInput(const uint8_t *aData, size_t nByte){
b62f651… stephan 8075 int w,h;
b62f651… stephan 8076 char *zIn, *zOut;
b62f651… stephan 8077 unsigned int mFlags = nByte & 3;
b62f651… stephan 8078 zIn = malloc( nByte + 1 );
b62f651… stephan 8079 if( zIn==0 ) return 0;
b62f651… stephan 8080 memcpy(zIn, aData, nByte);
b62f651… stephan 8081 zIn[nByte] = 0;
b62f651… stephan 8082 zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
b62f651… stephan 8083 free(zIn);
b62f651… stephan 8084 free(zOut);
b62f651… stephan 8085 return 0;
b62f651… stephan 8086 }
b62f651… stephan 8087 #endif /* PIKCHR_FUZZ */
b62f651… stephan 8088
b62f651… stephan 8089 #if defined(PIKCHR_SHELL)
b62f651… stephan 8090 /* Print a usage comment for the shell and exit. */
b62f651… stephan 8091 static void usage(const char *argv0){
b62f651… stephan 8092 fprintf(stderr, "usage: %s [OPTIONS] FILE ...\n", argv0);
b62f651… stephan 8093 fprintf(stderr,
b62f651… stephan 8094 "Convert Pikchr input files into SVG. Filename \"-\" means stdin.\n"
d5ec362… stephan 8095 "All output goes to stdout.\n"
b62f651… stephan 8096 "Options:\n"
390e001… drh 8097 " --dark-mode Generate \"dark mode\" output\n"
b62f651… stephan 8098 " --dont-stop Process all files even if earlier files have errors\n"
d5ec362… stephan 8099 " --svg-only Emit raw SVG without the HTML wrapper\n"
b62f651… stephan 8100 );
b62f651… stephan 8101 exit(1);
b62f651… stephan 8102 }
b62f651… stephan 8103
b62f651… stephan 8104 /* Send text to standard output, but escape HTML markup */
b62f651… stephan 8105 static void print_escape_html(const char *z){
b62f651… stephan 8106 int j;
b62f651… stephan 8107 char c;
b62f651… stephan 8108 while( z[0]!=0 ){
b62f651… stephan 8109 for(j=0; (c = z[j])!=0 && c!='<' && c!='>' && c!='&'; j++){}
b62f651… stephan 8110 if( j ) printf("%.*s", j, z);
b62f651… stephan 8111 z += j+1;
b62f651… stephan 8112 j = -1;
b62f651… stephan 8113 if( c=='<' ){
b62f651… stephan 8114 printf("&lt;");
b62f651… stephan 8115 }else if( c=='>' ){
b62f651… stephan 8116 printf("&gt;");
b62f651… stephan 8117 }else if( c=='&' ){
b62f651… stephan 8118 printf("&amp;");
b62f651… stephan 8119 }else if( c==0 ){
b62f651… stephan 8120 break;
b62f651… stephan 8121 }
b62f651… stephan 8122 }
b62f651… stephan 8123 }
b62f651… stephan 8124
b62f651… stephan 8125 /* Read the content of file zFilename into memory obtained from malloc()
b62f651… stephan 8126 ** Return the memory. If something goes wrong (ex: the file does not exist
b62f651… stephan 8127 ** or cannot be opened) put an error message on stderr and return NULL.
b62f651… stephan 8128 **
b62f651… stephan 8129 ** If the filename is "-" read stdin.
b62f651… stephan 8130 */
b62f651… stephan 8131 static char *readFile(const char *zFilename){
b62f651… stephan 8132 FILE *in;
b62f651… stephan 8133 size_t n;
b62f651… stephan 8134 size_t nUsed = 0;
b62f651… stephan 8135 size_t nAlloc = 0;
b62f651… stephan 8136 char *z = 0, *zNew = 0;
b62f651… stephan 8137 in = strcmp(zFilename,"-")==0 ? stdin : fopen(zFilename, "rb");
b62f651… stephan 8138 if( in==0 ){
b62f651… stephan 8139 fprintf(stderr, "cannot open \"%s\" for reading\n", zFilename);
b62f651… stephan 8140 return 0;
b62f651… stephan 8141 }
b62f651… stephan 8142 while(1){
b62f651… stephan 8143 if( nUsed+2>=nAlloc ){
b62f651… stephan 8144 nAlloc = nAlloc*2 + 4000;
b62f651… stephan 8145 zNew = realloc(z, nAlloc);
b62f651… stephan 8146 }
b62f651… stephan 8147 if( zNew==0 ){
b62f651… stephan 8148 free(z);
b62f651… stephan 8149 fprintf(stderr, "out of memory trying to allocate %lld bytes\n",
b62f651… stephan 8150 (long long int)nAlloc);
b62f651… stephan 8151 exit(1);
b62f651… stephan 8152 }
b62f651… stephan 8153 z = zNew;
b62f651… stephan 8154 n = fread(z+nUsed, 1, nAlloc-nUsed-1, in);
b62f651… stephan 8155 if( n<=0 ){
b62f651… stephan 8156 break;
b62f651… stephan 8157 }
b62f651… stephan 8158 nUsed += n;
b62f651… stephan 8159 }
b62f651… stephan 8160 if( in!=stdin ) fclose(in);
b62f651… stephan 8161 z[nUsed] = 0;
b62f651… stephan 8162 return z;
b62f651… stephan 8163 }
b62f651… stephan 8164
b62f651… stephan 8165
b62f651… stephan 8166 /* Testing interface
b62f651… stephan 8167 **
b62f651… stephan 8168 ** Generate HTML on standard output that displays both the original
b62f651… stephan 8169 ** input text and the rendered SVG for all files named on the command
b62f651… stephan 8170 ** line.
b62f651… stephan 8171 */
b62f651… stephan 8172 int main(int argc, char **argv){
b62f651… stephan 8173 int i;
b62f651… stephan 8174 int bSvgOnly = 0; /* Output SVG only. No HTML wrapper */
b62f651… stephan 8175 int bDontStop = 0; /* Continue in spite of errors */
b62f651… stephan 8176 int exitCode = 0; /* What to return */
b62f651… stephan 8177 int mFlags = 0; /* mFlags argument to pikchr() */
b62f651… stephan 8178 const char *zStyle = ""; /* Extra styling */
b62f651… stephan 8179 const char *zHtmlHdr =
b62f651… stephan 8180 "<!DOCTYPE html>\n"
b62f651… stephan 8181 "<html lang=\"en-US\">\n"
b62f651… stephan 8182 "<head>\n<title>PIKCHR Test</title>\n"
b62f651… stephan 8183 "<style>\n"
b62f651… stephan 8184 " .hidden {\n"
b62f651… stephan 8185 " position: absolute !important;\n"
b62f651… stephan 8186 " opacity: 0 !important;\n"
b62f651… stephan 8187 " pointer-events: none !important;\n"
b62f651… stephan 8188 " display: none !important;\n"
b62f651… stephan 8189 " }\n"
b62f651… stephan 8190 "</style>\n"
b62f651… stephan 8191 "<script>\n"
b62f651… stephan 8192 " function toggleHidden(id){\n"
b62f651… stephan 8193 " for(var c of document.getElementById(id).children){\n"
b62f651… stephan 8194 " c.classList.toggle('hidden');\n"
b62f651… stephan 8195 " }\n"
b62f651… stephan 8196 " }\n"
b62f651… stephan 8197 "</script>\n"
b62f651… stephan 8198 "<meta charset=\"utf-8\">\n"
b62f651… stephan 8199 "</head>\n"
b62f651… stephan 8200 "<body>\n"
b62f651… stephan 8201 ;
b62f651… stephan 8202 if( argc<2 ) usage(argv[0]);
b62f651… stephan 8203 for(i=1; i<argc; i++){
b62f651… stephan 8204 char *zIn;
b62f651… stephan 8205 char *zOut;
b62f651… stephan 8206 int w, h;
b62f651… stephan 8207
b62f651… stephan 8208 if( argv[i][0]=='-' && argv[i][1]!=0 ){
b62f651… stephan 8209 char *z = argv[i];
b62f651… stephan 8210 z++;
b62f651… stephan 8211 if( z[0]=='-' ) z++;
b62f651… stephan 8212 if( strcmp(z,"dont-stop")==0 ){
b62f651… stephan 8213 bDontStop = 1;
b62f651… stephan 8214 }else
b62f651… stephan 8215 if( strcmp(z,"dark-mode")==0 ){
b62f651… stephan 8216 zStyle = "color:white;background-color:black;";
b62f651… stephan 8217 mFlags |= PIKCHR_DARK_MODE;
b62f651… stephan 8218 }else
b62f651… stephan 8219 if( strcmp(z,"svg-only")==0 ){
b62f651… stephan 8220 if( zHtmlHdr==0 ){
b62f651… stephan 8221 fprintf(stderr, "the \"%s\" option must come first\n",argv[i]);
b62f651… stephan 8222 exit(1);
b62f651… stephan 8223 }
b62f651… stephan 8224 bSvgOnly = 1;
b62f651… stephan 8225 mFlags |= PIKCHR_PLAINTEXT_ERRORS;
b62f651… stephan 8226 }else
dd20f34… drh 8227 if( strcmp(z,"version")==0 || strcmp(z,"v")==0 ){
dd20f34… drh 8228 printf("pikchr %s\n", pikchr_version());
dd20f34… drh 8229 return 0;
dd20f34… drh 8230 }else
b62f651… stephan 8231 {
b62f651… stephan 8232 fprintf(stderr,"unknown option: \"%s\"\n", argv[i]);
b62f651… stephan 8233 usage(argv[0]);
b62f651… stephan 8234 }
b62f651… stephan 8235 continue;
b62f651… stephan 8236 }
b62f651… stephan 8237 zIn = readFile(argv[i]);
b62f651… stephan 8238 if( zIn==0 ) continue;
b62f651… stephan 8239 zOut = pikchr(zIn, "pikchr", mFlags, &w, &h);
390e001… drh 8240 if( w<0 && !bDontStop ) exitCode = 1;
b62f651… stephan 8241 if( zOut==0 ){
b62f651… stephan 8242 fprintf(stderr, "pikchr() returns NULL. Out of memory?\n");
b62f651… stephan 8243 if( !bDontStop ) exit(1);
b62f651… stephan 8244 }else if( bSvgOnly ){
b62f651… stephan 8245 printf("%s\n", zOut);
b62f651… stephan 8246 }else{
b62f651… stephan 8247 if( zHtmlHdr ){
b62f651… stephan 8248 printf("%s", zHtmlHdr);
b62f651… stephan 8249 zHtmlHdr = 0;
b62f651… stephan 8250 }
b62f651… stephan 8251 printf("<h1>File %s</h1>\n", argv[i]);
b62f651… stephan 8252 if( w<0 ){
b62f651… stephan 8253 printf("<p>ERROR</p>\n%s\n", zOut);
b62f651… stephan 8254 }else{
b62f651… stephan 8255 printf("<div id=\"svg-%d\" onclick=\"toggleHidden('svg-%d')\">\n",i,i);
b62f651… stephan 8256 printf("<div style='border:3px solid lightgray;max-width:%dpx;%s'>\n",
b62f651… stephan 8257 w,zStyle);
b62f651… stephan 8258 printf("%s</div>\n", zOut);
b62f651… stephan 8259 printf("<pre class='hidden'>");
b62f651… stephan 8260 print_escape_html(zIn);
b62f651… stephan 8261 printf("</pre>\n</div>\n");
b62f651… stephan 8262 }
b62f651… stephan 8263 }
b62f651… stephan 8264 free(zOut);
b62f651… stephan 8265 free(zIn);
b62f651… stephan 8266 }
b62f651… stephan 8267 if( !bSvgOnly ){
b62f651… stephan 8268 printf("</body></html>\n");
b62f651… stephan 8269 }
adc7bfc… drh 8270 return exitCode ? EXIT_FAILURE : EXIT_SUCCESS;
b62f651… stephan 8271 }
b62f651… stephan 8272 #endif /* PIKCHR_SHELL */
b62f651… stephan 8273
b62f651… stephan 8274 #ifdef PIKCHR_TCL
b62f651… stephan 8275 #include <tcl.h>
adc7bfc… drh 8276 /* Compatability between Tcl8.6 and Tcl9.0 */
adc7bfc… drh 8277 #if TCL_MAJOR_VERSION==9
adc7bfc… drh 8278 # define CONST const
adc7bfc… drh 8279 #elif !defined(Tcl_Size)
adc7bfc… drh 8280 typedef int Tcl_Size;
adc7bfc… drh 8281 #endif
adc7bfc… drh 8282
b62f651… stephan 8283 /*
b62f651… stephan 8284 ** An interface to TCL
b62f651… stephan 8285 **
b62f651… stephan 8286 ** TCL command: pikchr $INPUTTEXT
b62f651… stephan 8287 **
b62f651… stephan 8288 ** Returns a list of 3 elements which are the output text, the width, and
b62f651… stephan 8289 ** the height.
b62f651… stephan 8290 **
b62f651… stephan 8291 ** Register the "pikchr" command by invoking Pikchr_Init(Tcl_Interp*). Or
b62f651… stephan 8292 ** compile this source file as a shared library and load it using the
b62f651… stephan 8293 ** "load" command of Tcl.
b62f651… stephan 8294 **
b62f651… stephan 8295 ** Compile this source-code file into a shared library using a command
b62f651… stephan 8296 ** similar to this:
b62f651… stephan 8297 **
b62f651… stephan 8298 ** gcc -c pikchr.so -DPIKCHR_TCL -shared pikchr.c
b62f651… stephan 8299 */
b62f651… stephan 8300 static int pik_tcl_command(
b62f651… stephan 8301 ClientData clientData, /* Not Used */
b62f651… stephan 8302 Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
b62f651… stephan 8303 int objc, /* Number of arguments */
adc7bfc… drh 8304 Tcl_Obj *CONST objv[] /* Command arguments */
b62f651… stephan 8305 ){
b62f651… stephan 8306 int w, h; /* Width and height of the pikchr */
b62f651… stephan 8307 const char *zIn; /* Source text input */
b62f651… stephan 8308 char *zOut; /* SVG output text */
b62f651… stephan 8309 Tcl_Obj *pRes; /* The result TCL object */
b62f651… stephan 8310
b62f651… stephan 8311 (void)clientData;
b62f651… stephan 8312 if( objc!=2 ){
b62f651… stephan 8313 Tcl_WrongNumArgs(interp, 1, objv, "PIKCHR_SOURCE_TEXT");
b62f651… stephan 8314 return TCL_ERROR;
b62f651… stephan 8315 }
b62f651… stephan 8316 zIn = Tcl_GetString(objv[1]);
b62f651… stephan 8317 w = h = 0;
b62f651… stephan 8318 zOut = pikchr(zIn, "pikchr", 0, &w, &h);
b62f651… stephan 8319 if( zOut==0 ){
b62f651… stephan 8320 return TCL_ERROR; /* Out of memory */
b62f651… stephan 8321 }
b62f651… stephan 8322 pRes = Tcl_NewObj();
b62f651… stephan 8323 Tcl_ListObjAppendElement(0, pRes, Tcl_NewStringObj(zOut, -1));
b62f651… stephan 8324 free(zOut);
b62f651… stephan 8325 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(w));
b62f651… stephan 8326 Tcl_ListObjAppendElement(0, pRes, Tcl_NewIntObj(h));
b62f651… stephan 8327 Tcl_SetObjResult(interp, pRes);
b62f651… stephan 8328 return TCL_OK;
b62f651… stephan 8329 }
b62f651… stephan 8330
b62f651… stephan 8331 #ifndef PACKAGE_NAME
b62f651… stephan 8332 # define PACKAGE_NAME "pikchr"
b62f651… stephan 8333 #endif
b62f651… stephan 8334 #ifndef PACKAGE_VERSION
b62f651… stephan 8335 # define PACKAGE_VERSION "1.0"
b62f651… stephan 8336 #endif
b62f651… stephan 8337
b62f651… stephan 8338 /* Invoke this routine to register the "pikchr" command with the interpreter
b62f651… stephan 8339 ** given in the argument */
b62f651… stephan 8340 int Pikchr_Init(Tcl_Interp *interp){
b62f651… stephan 8341 Tcl_CreateObjCommand(interp, "pikchr", pik_tcl_command, 0, 0);
b62f651… stephan 8342 Tcl_PkgProvide(interp, PACKAGE_NAME, PACKAGE_VERSION);
b62f651… stephan 8343 return TCL_OK;
b62f651… stephan 8344 }
b62f651… stephan 8345
b62f651… stephan 8346
b62f651… stephan 8347 #endif /* PIKCHR_TCL */
b62f651… stephan 8348
b62f651… stephan 8349
adc7bfc… drh 8350 #line 8350 "pikchr.c"

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button