PageRenderTime 263ms CodeModel.GetById 62ms app.highlight 176ms RepoModel.GetById 1ms app.codeStats 1ms

/reportlab-2.5/src/rl_addons/renderPM/gt1/gt1-parset1.c

#
C | 3242 lines | 2767 code | 326 blank | 149 comment | 630 complexity | e4ecef74d647c9a9056d513636877363 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1#include <stdio.h>
   2#include <string.h>
   3#include <ctype.h>
   4#include <math.h>
   5
   6#if defined(macintosh)
   7#	include <extras.h>
   8#	define strdup _strdup
   9#endif
  10
  11#include "libart_lgpl/art_bpath.h"
  12
  13
  14#include "gt1-misc.h"
  15#include "gt1-region.h"
  16#include "gt1-namecontext.h"
  17#include "gt1-value.h"
  18#include "gt1-dict.h"
  19
  20#include "gt1-parset1.h"
  21#ifdef	AFM
  22#	include "parseAFM.h"
  23#endif
  24
  25
  26/* a big-assed module to parse Adobe Type 1 fonts into meaningful
  27	 info */
  28
  29#define noVERBOSE
  30
  31static int
  32read_int32_lsb (const char *p)
  33{
  34	const unsigned char *q = (unsigned char *)p;
  35
  36	return q[0] + (q[1] << 8) + (q[2] << 16) + (q[3] << 24);
  37}
  38
  39/* this is a pfb to pfa converter
  40
  41 Reference: Adobe technical note 5040, "Supporting Downloadable PostScript
  42 Language Fonts", page 9 */
  43static char *
  44pfb_to_flat (const char *input, int input_size)
  45{
  46	const unsigned char *in = (unsigned char *)input;
  47	char *flat;
  48	int flat_size, flat_size_max;
  49	int in_idx;
  50	int length;
  51	int i;
  52	const char hextab[16] = "0123456789abcdef";
  53
  54	flat_size = 0;
  55	flat_size_max = 32768;
  56	flat = gt1_new (char, flat_size_max);
  57
  58	for (in_idx = 0; in_idx < input_size;)
  59		{
  60			if (in[in_idx] != 128)
  61	{
  62		gt1_free (flat);
  63		return NULL;
  64	}
  65			switch (in[in_idx + 1])
  66	{
  67	case 1:
  68		length = read_int32_lsb (input + in_idx + 2);
  69		if (flat_size + length > flat_size_max)
  70			{
  71				do
  72		flat_size_max <<= 1;
  73				while (flat_size + length > flat_size_max);
  74				flat = gt1_renew (flat, char, flat_size_max);
  75			}
  76		in_idx += 6;
  77		memcpy (flat + flat_size, in + in_idx, length);
  78		flat_size += length;
  79		in_idx += length;
  80		break;
  81	case 2:
  82		length = read_int32_lsb (input + in_idx + 2);
  83		if (flat_size + length * 3 > flat_size_max)
  84			{
  85				do
  86		flat_size_max <<= 1;
  87				while (flat_size + length * 3 > flat_size_max);
  88				flat = gt1_renew (flat, char, flat_size_max);
  89			}
  90		in_idx += 6;
  91		for (i = 0; i < length; i++)
  92			{
  93				flat[flat_size++] = hextab[in[in_idx] >> 4];
  94				flat[flat_size++] = hextab[in[in_idx] & 15];
  95				in_idx++;
  96				if ((i & 31) == 31 || i == length - 1)
  97		flat[flat_size++] = '\n';
  98			}
  99		break;
 100	case 3:
 101		/* zero terminate the returned string */
 102		if (flat_size == flat_size_max)
 103			gt1_double (flat, char, flat_size_max);
 104		flat[flat_size] = 0;
 105		return flat;
 106	default:
 107			gt1_free (flat);
 108			return NULL;
 109	}
 110		}
 111	return flat;
 112}
 113
 114struct _Gt1TokenContext {
 115	char *source;
 116	int index;
 117	int pos;
 118};
 119
 120typedef enum {
 121	TOK_NUM,
 122	TOK_STR,
 123	TOK_NAME, /* initial / */
 124	TOK_IDENT,
 125	TOK_OPENBRACE,
 126	TOK_CLOSEBRACE,
 127	TOK_END
 128} TokenType;
 129
 130/* we're phasing this out in favor of value.h's Gt1String */
 131typedef struct _MyGt1String MyGt1String;
 132
 133struct _MyGt1String {
 134	char *start;
 135	char *fin;
 136};
 137
 138static void
 139tokenize_free (Gt1TokenContext *tc)
 140{
 141	gt1_free (tc->source);
 142	gt1_free (tc);
 143}
 144
 145
 146static Gt1TokenContext *
 147tokenize_new (const char *input)
 148{
 149	Gt1TokenContext *tc;
 150	int length;
 151
 152	tc = gt1_new (Gt1TokenContext, 1);
 153	length = strlen (input);
 154	tc->source = gt1_new (char, length + 1);
 155	memcpy (tc->source, input, length + 1);
 156	tc->index = 0;
 157	tc->pos = 0;
 158
 159	return tc;
 160}
 161
 162static Gt1TokenContext *
 163tokenize_new_from_mystring (MyGt1String *input)
 164{
 165	Gt1TokenContext *tc;
 166	int length;
 167
 168	tc = gt1_new (Gt1TokenContext, 1);
 169	length = input->fin - input->start;
 170	tc->source = gt1_new (char, length + 1);
 171	memcpy (tc->source, input->start, length + 1);
 172	tc->index = 0;
 173	tc->pos = 0;
 174
 175	return tc;
 176}
 177
 178/* this returns a TokenType, and sets result to the token contents.
 179
 180	 Note: this strips delimiters, like the initial /, and the enclosing ().
 181*/
 182static TokenType
 183tokenize_get (Gt1TokenContext *tc, MyGt1String *result)
 184{
 185	unsigned char *s = (unsigned char *)tc->source;
 186	int index = tc->index;
 187	int pos = tc->pos;
 188	unsigned char c;
 189	TokenType type;
 190
 191	/* skip comments altogether (maybe later we want them, though) */
 192	while (c = s[index], isspace (c) || c == '%')
 193		{
 194			/* skip leading whitespace */
 195			while (isspace (s[index]))
 196	{
 197		if (s[index] == '\r' || s[index] == '\n')
 198			pos = 0;
 199		else
 200			pos++;
 201		index++;
 202	}
 203
 204			if (s[index] == '%')
 205	{
 206		do
 207			/* skip past end-of-line */
 208			{
 209				while (c = s[index], c && c != '\r' && c != '\n')
 210		index++;
 211				if (s[index] != 0) index++;
 212			}
 213		while (s[index] == '%');
 214	}
 215		}
 216
 217	/* skip leading whitespace */
 218	while (c = s[index], isspace (c))
 219		{
 220			if (c == '\r' || c == '\n')
 221	pos = 0;
 222			else
 223	pos++;
 224			index++;
 225		}
 226
 227
 228	/* ok, so now we're at the actual start of a token */
 229	result->start = (char*)s + index;
 230
 231	c = s[index];
 232
 233	if (c == 0)
 234		{
 235			result->fin = (char*)s + index;
 236			type = TOK_END;
 237		}
 238	/* note: GhostScript checks much more strenuously. Further, this
 239		 predicate does not pass the valid number -.9 */
 240	else if (isdigit (c) || c == '.' || (c == '-' && isdigit (s[index + 1])))
 241		{
 242			/* numeric token */
 243			while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
 244			 c != '[' && c != ']' && c != '}')
 245	{
 246		index++;
 247		pos++;
 248	}
 249			result->fin = (char*)s + index;
 250			type = TOK_NUM;
 251		}
 252	else if (c == '/')
 253		{
 254			/* an atom, or whatever that's called */
 255			index++;
 256			result->start = (char*)s + index;
 257			while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
 258			 c != '[' && c != ']' && c != '}' && c != '(')
 259	{
 260		index++;
 261		pos++;
 262	}
 263			result->fin = (char*)s + index;
 264			type = TOK_NAME;
 265		}
 266	else if (c == '(')
 267		{
 268			int nest;
 269			int backslash;
 270
 271			nest = 1;
 272			index++;
 273			backslash = 0;
 274			result->start = (char*)s + index;
 275			while (c = s[index], c && nest)
 276	{
 277		if (backslash)
 278			backslash = 0;
 279		else if (c == '(')
 280			nest++;
 281		else if (c == ')')
 282			nest--;
 283		else if (c == '\\')
 284			backslash = 1;
 285		index++;
 286		if (c == '\r' || c == '\n')
 287			pos = 0;
 288		else
 289			pos++;
 290	}
 291			/* we could have a c == 0 error case here */
 292			result->fin = (char*)s + index - 1;
 293			type = TOK_STR;
 294		}
 295	else if (c == '{')
 296		{
 297			index++;
 298			result->fin = (char*)s + index;
 299			type = TOK_OPENBRACE;
 300		}
 301	else if (c == '}')
 302		{
 303			index++;
 304			result->fin = (char*)s + index;
 305			type = TOK_CLOSEBRACE;
 306		}
 307	else if (c == '[' || c == ']')
 308		{
 309			index++;
 310			result->fin = (char*)s + index;
 311			type = TOK_IDENT;
 312		}
 313	else
 314		{
 315			/* treat everything else as an identifier */
 316			while (c = s[index], c && !isspace (c) && c != '{' && c != '/' &&
 317			 c != '[' && c != ']' && c != '}' && c != '(')
 318	{
 319		index++;
 320		pos++;
 321	}
 322			result->fin = (char*)s + index;
 323			if (isspace(c))
 324	index++; /* skip single trailing whitespace char - this is
 325				useful for readstring */
 326			type = TOK_IDENT;
 327		}
 328
 329	tc->index = index;
 330	tc->pos = pos;
 331	return type;
 332}
 333
 334static int
 335ascii_to_hex (unsigned char c)
 336{
 337	if (c <= '9') return c - '0';
 338	else if (c >= 'a') return c + 10 - 'a';
 339	else return c + 10 - 'A';
 340}
 341
 342/* return a hex byte, or -1 on error */
 343
 344/* we don't deal with comments here */
 345static int
 346tokenize_get_hex_byte (Gt1TokenContext *tc)
 347{
 348	const unsigned char *s = (const unsigned char *)tc->source;
 349	int index = tc->index;
 350	int pos = tc->pos;
 351	int byte;
 352
 353	/* skip leading whitespace */
 354	while (isspace (s[index]))
 355		{
 356			if (s[index] == '\r' || s[index] == '\n')
 357	pos = 0;
 358			else
 359	pos++;
 360			index++;
 361		}
 362
 363	if (isxdigit (s[index]) && isxdigit (s[index + 1]))
 364		{
 365			byte = (ascii_to_hex (s[index]) << 4) | ascii_to_hex (s[index + 1]);
 366			index += 2;
 367		}
 368	else
 369		byte = -1;
 370
 371	tc->index = index;
 372	tc->pos = pos;
 373	return byte;
 374}
 375
 376/* careful, we're _not_ protected against buffer overruns here */
 377/* todo: fix this, it's definitely a potential security violation.
 378	 This almost certainly implies changing the Gt1TokenContext structure
 379	 to incorporate a size field, and de-emphasizing the use of
 380	 zero-termination */
 381static void
 382tokenize_get_raw (Gt1TokenContext *tc, char *buf, int buf_size)
 383{
 384	memcpy (buf, tc->source + tc->index, buf_size);
 385	tc->index += buf_size;
 386}
 387
 388#ifdef DEBUG
 389
 390static void
 391print_token (TokenType type, MyGt1String *lexeme)
 392{
 393	char *start, *fin;
 394
 395	start = lexeme->start;
 396	fin = lexeme->fin;
 397
 398	switch (type)
 399		{
 400		case TOK_NUM:
 401			printf ("number				 ");
 402			break;
 403		case TOK_IDENT:
 404			printf ("identifier		 ");
 405			break;
 406		case TOK_NAME:
 407			printf ("name					 ");
 408			break;
 409		case TOK_STR:
 410			printf ("string				 ");
 411			break;
 412		case TOK_OPENBRACE:
 413			printf ("open brace		 ");
 414			break;
 415		case TOK_CLOSEBRACE:
 416			printf ("close brace	 ");
 417			break;
 418		case TOK_END:
 419			printf ("end					 ");
 420			break;
 421		default:
 422			break;
 423		}
 424	while (start != fin)
 425		printf ("%c", *start++);
 426	printf ("\n");
 427}
 428
 429static void
 430test_token (const char *flat)
 431{
 432	Gt1TokenContext *tc;
 433	TokenType type;
 434	MyGt1String lexeme;
 435
 436	tc = tokenize_new (flat);
 437	while (1)
 438		{
 439			type = tokenize_get (tc, &lexeme);
 440			if (type == TOK_END) break;
 441			print_token (type, &lexeme);
 442		 }
 443}
 444
 445#endif
 446
 447/* basic PostScript language types */
 448
 449typedef struct _Gt1ProcStep {
 450	TokenType tok_type;
 451	MyGt1String lexeme;
 452} Gt1ProcStep;
 453
 454struct _Gt1Proc {
 455	int n_steps;
 456	/* sooner or later, we'll want to replace proc steps with
 457		 plain PostScript values. - probably sooner in fact, because that's
 458		 the best way to implement nested procedures, which currently do
 459		 not work. */
 460	Gt1Value steps[1];
 461};
 462
 463/* low-level PostScript routines */
 464
 465/* note: resulting array is _uninitialized_ ! */
 466static Gt1Array *
 467array_new (Gt1Region *r, int size)
 468{
 469	Gt1Array *array;
 470
 471	array = (Gt1Array *)gt1_region_alloc (r, sizeof(Gt1Array) +
 472				 (size - 1) * sizeof(Gt1Value));
 473	array->n_values = size;
 474	return array;
 475}
 476
 477struct _Gt1PSContext {
 478	Gt1Region *r; /* the region all PS values are allocated into */
 479
 480	Gt1TokenContext *tc; /* this is for readstring, eexec, etc. */
 481
 482	Gt1NameContext *nc; /* the context for all names */
 483
 484	Gt1Value *value_stack;
 485	int n_values, n_values_max;
 486
 487	/* ghostscript also has an execution stack - what's that? */
 488
 489	Gt1Dict **gt1_dict_stack;
 490	int n_dicts, n_dicts_max;
 491
 492	/* a special dict that holds all the fonts */
 493	Gt1Dict *fonts;
 494
 495	Gt1TokenContext **file_stack; /* invariant: top of file stack == tc */
 496	int n_files, n_files_max;
 497
 498	int quit; /* maybe this should be a string, for error messages too */
 499};
 500
 501/* a very basic PostScript interpreter */
 502
 503/* make sure that value stack has enough room for pushing n values. */
 504static void
 505ensure_stack (Gt1PSContext *psc, int n)
 506{
 507	if (psc->n_values + n == psc->n_values_max)
 508		{
 509			psc->n_values_max <<= 1;
 510			psc->value_stack = gt1_renew (psc->value_stack, Gt1Value, psc->n_values_max);
 511		}
 512}
 513
 514static double
 515parse_num (MyGt1String *number)
 516{
 517	double sign;
 518	double mantissa;
 519	double decimal;
 520	int exp_sign;
 521	int exp;
 522	int i, length;
 523	const unsigned char *start;
 524
 525	start = (const unsigned char *)number->start;
 526	length = number->fin - number->start;
 527
 528	i = 0;
 529	sign = 1;
 530	if (i < length && start[i] == '-')
 531		{
 532			sign = -1;
 533			i++;
 534		}
 535	else if (i < length && start[i] == '+')
 536		i++;
 537
 538	mantissa = 0;
 539	while (i < length && isdigit (start[i]))
 540		{
 541			mantissa = (mantissa * 10) + start[i] - '0';
 542			i++;
 543		}
 544	if (i < length && start[i] == '.')
 545		{
 546			i++;
 547			decimal = 1;
 548			while (i < length && isdigit (start[i]))
 549	{
 550		decimal *= 0.1;
 551		mantissa += (start[i] - '0') * decimal;
 552		i++;
 553	}
 554		}
 555	if (i < length && (start[i] == 'e' || start[i] == 'E'))
 556		{
 557			i++;
 558			exp_sign = 1;
 559			if (i < length && start[i] == '-')
 560	{
 561		exp_sign = -1;
 562		i++;
 563	}
 564			else if (i < length && start[i] == '+')
 565	i++;
 566
 567			exp = 0;
 568			while (i < length && isdigit (start[i]))
 569	{
 570		exp = (exp * 10) + start[i] - '0';
 571		i++;
 572	}
 573			mantissa *= pow (10, exp * exp_sign);
 574		}
 575	return sign * mantissa;
 576}
 577
 578#ifdef DEBUG
 579
 580static void
 581print_mystring (MyGt1String *str)
 582{
 583	char *start, *fin;
 584
 585	start = str->start;
 586	fin = str->fin;
 587
 588	while (start != fin)
 589		printf ("%c", *start++);
 590}
 591
 592#endif
 593
 594static void
 595print_string (Gt1String *str)
 596{
 597	char *start;
 598	int size;
 599	int i;
 600
 601	start = str->start;
 602	size = str->size;
 603
 604	for (i = 0; i < size; i++);
 605		printf ("%c", start[i]);
 606}
 607
 608static void
 609print_value (Gt1PSContext *psc, Gt1Value *val)
 610{
 611	switch (val->type)
 612		{
 613		case GT1_VAL_NUM:
 614			printf ("%g", val->val.num_val);
 615			break;
 616		case GT1_VAL_BOOL:
 617			printf ("%s", val->val.bool_val ? "true" : "false");
 618			break;
 619		case GT1_VAL_STR:
 620			printf ("\"");
 621			print_string (&val->val.str_val);
 622			printf ("\"");
 623			break;
 624		case GT1_VAL_NAME:
 625			printf ("/%s", gt1_name_context_string (psc->nc, val->val.name_val));
 626			break;
 627		case GT1_VAL_UNQ_NAME:
 628			printf ("%s", gt1_name_context_string (psc->nc, val->val.name_val));
 629			break;
 630		case GT1_VAL_DICT:
 631			printf ("<dictionary %d/%d>",
 632				val->val.dict_val->n_entries,
 633				val->val.dict_val->n_entries_max);
 634			break;
 635		case GT1_VAL_ARRAY:
 636			printf ("<array>");
 637			break;
 638		case GT1_VAL_PROC:
 639#if 1
 640			printf ("<proc>");
 641#else
 642			printf ("{ ");
 643			{ int i;
 644			for (i = 0; i < val->val.proc_val->n_values; i++)
 645	{
 646		print_value (psc, &val->val.proc_val->vals[i]);
 647		printf (" ");
 648	}
 649			printf ("}");
 650			}
 651#endif
 652			break;
 653		case GT1_VAL_FILE:
 654			printf ("<file>");
 655			break;
 656		case GT1_VAL_INTERNAL:
 657			printf ("<internal function>");
 658		case GT1_VAL_MARK:
 659			printf ("<mark>");
 660			break;
 661		default:
 662			printf ("???%d", val->type);
 663		}
 664}
 665
 666#ifdef DEBUG
 667
 668static void
 669print_token_short (TokenType type, MyGt1String *lexeme)
 670{
 671	char *start, *fin;
 672
 673	start = lexeme->start;
 674	fin = lexeme->fin;
 675
 676	switch (type)
 677		{
 678		case TOK_NUM:
 679			print_mystring (lexeme);
 680			break;
 681		case TOK_IDENT:
 682			print_mystring (lexeme);
 683			break;
 684		case TOK_NAME:
 685			printf ("/");
 686			print_mystring (lexeme);
 687			break;
 688		case TOK_STR:
 689			printf ("(");
 690			print_mystring (lexeme);
 691			printf (")");
 692			break;
 693		case TOK_OPENBRACE:
 694			printf ("{");
 695			break;
 696		case TOK_CLOSEBRACE:
 697			printf ("}");
 698			break;
 699		case TOK_END:
 700			printf ("end					 ");
 701			break;
 702		default:
 703			break;
 704		}
 705}
 706
 707#endif
 708
 709static void
 710print_value_deep (Gt1PSContext *psc, Gt1Value *val, int nest)
 711{
 712	int i, j;
 713
 714	for (i = 0; i < nest; i++)
 715		printf (" ");
 716
 717	switch (val->type)
 718		{
 719		case GT1_VAL_NUM:
 720			printf ("%g", val->val.num_val);
 721			break;
 722		case GT1_VAL_BOOL:
 723			printf ("%s", val->val.bool_val ? "true" : "false");
 724			break;
 725		case GT1_VAL_STR:
 726			printf ("\"");
 727			print_string (&val->val.str_val);
 728			printf ("\"");
 729			break;
 730		case GT1_VAL_NAME:
 731			printf ("/%s", gt1_name_context_string (psc->nc, val->val.name_val));
 732			break;
 733		case GT1_VAL_UNQ_NAME:
 734			printf ("%s", gt1_name_context_string (psc->nc, val->val.name_val));
 735			break;
 736		case GT1_VAL_DICT:
 737			printf ("<dictionary %d/%d> [\n",
 738				val->val.dict_val->n_entries,
 739				val->val.dict_val->n_entries_max);
 740			for (i = 0; i < val->val.dict_val->n_entries; i++)
 741	{
 742		for (j = 0; j < nest; j++)
 743			printf (" ");
 744		printf ("key %d\n", val->val.dict_val->entries[i].key);
 745		print_value_deep (psc, &val->val.dict_val->entries[i].val, nest + 1);
 746	}
 747			for (j = 0; j < nest; j++)
 748	printf (" ");
 749			printf ("]");
 750			break;
 751		case GT1_VAL_ARRAY:
 752			printf ("[\n");
 753			for (i = 0; i < val->val.array_val->n_values; i++)
 754	{
 755		print_value_deep (psc, &val->val.array_val->vals[i], nest + 1);
 756	}
 757			for (j = 0; j < nest; j++)
 758	printf (" ");
 759			printf ("]");
 760			break;
 761		case GT1_VAL_PROC:
 762			printf ("{\n");
 763			for (i = 0; i < val->val.proc_val->n_values; i++)
 764	{
 765		print_value_deep (psc, &val->val.proc_val->vals[i], nest + 1);
 766	}
 767			for (j = 0; j < nest; j++)
 768	printf (" ");
 769			printf ("}");
 770			break;
 771		case GT1_VAL_FILE:
 772			printf ("<file>");
 773			break;
 774		case GT1_VAL_INTERNAL:
 775			printf ("<internal function>");
 776		case GT1_VAL_MARK:
 777			printf ("<mark>");
 778			break;
 779		default:
 780			printf ("???");
 781		}
 782	printf ("\n");
 783}
 784
 785#ifdef DEBUG
 786
 787static void
 788print_stack (Gt1PSContext *psc)
 789{
 790	int i;
 791
 792	for (i = 0; i < psc->n_values; i++)
 793		{
 794			print_value (psc, &psc->value_stack[i]);
 795			if (i != psc->n_values - 1)
 796	printf (" ");
 797		}
 798	printf ("\n");
 799}
 800#endif
 801
 802static void
 803eval_ps_val (Gt1PSContext *psc, Gt1Value *val);
 804
 805static void
 806eval_proc (Gt1PSContext *psc, Gt1Proc *proc)
 807{
 808	int i;
 809
 810#ifdef VERBOSE
 811	printf ("begin proc evaluation\n");
 812#endif
 813	for (i = 0; !psc->quit && i < proc->n_values; i++)
 814		eval_ps_val (psc, &proc->vals[i]);
 815#ifdef VERBOSE
 816	printf ("end proc evaluation\n");
 817#endif
 818}
 819
 820static Gt1Value *
 821gt1_dict_stack_lookup (Gt1PSContext *psc, Gt1NameId key)
 822{
 823	int i;
 824	Gt1Value *val;
 825
 826	for (i = psc->n_dicts - 1; i >= 0; i--)
 827		{
 828			val = gt1_dict_lookup (psc->gt1_dict_stack[i], key);
 829			if (val != NULL)
 830	return val;
 831		}
 832	return NULL;
 833}
 834
 835/* return 1 on success, with result set to the top of the value stack */
 836static int
 837get_stack_number (Gt1PSContext *psc, double *result, int index)
 838{
 839	if (psc->n_values < index)
 840		{
 841			printf ("stack underflow\n");
 842			psc->quit = 1;
 843			return 0;
 844		}
 845	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_NUM)
 846		{
 847			printf ("type error - expecting number\n");
 848			psc->quit = 1;
 849			return 0;
 850		}
 851	*result = psc->value_stack[psc->n_values - index].val.num_val;
 852	return 1;
 853}
 854
 855/* return 1 on success, with result set to the top of the value stack */
 856static int
 857get_stack_dict (Gt1PSContext *psc, Gt1Dict **result, int index)
 858{
 859	if (psc->n_values < index)
 860		{
 861			printf ("stack underflow\n");
 862			psc->quit = 1;
 863			return 0;
 864		}
 865	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_DICT)
 866		{
 867			printf ("type error - expecting dict\n");
 868			psc->quit = 1;
 869			return 0;
 870		}
 871	*result = psc->value_stack[psc->n_values - index].val.dict_val;
 872	return 1;
 873}
 874
 875/* return 1 on success, with result set to the top of the value stack */
 876static int
 877get_stack_name (Gt1PSContext *psc, Gt1NameId *result, int index)
 878{
 879	if (psc->n_values < index)
 880		{
 881			printf ("stack underflow\n");
 882			psc->quit = 1;
 883			return 0;
 884		}
 885	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_NAME)
 886		{
 887			printf ("type error - expecting atom\n");
 888			psc->quit = 1;
 889			return 0;
 890		}
 891	*result = psc->value_stack[psc->n_values - index].val.name_val;
 892	return 1;
 893}
 894
 895/* return 1 on success, with result set to the top of the value stack */
 896static int
 897get_stack_file (Gt1PSContext *psc, Gt1TokenContext **result, int index)
 898{
 899	if (psc->n_values < index)
 900		{
 901			printf ("stack underflow\n");
 902			psc->quit = 1;
 903			return 0;
 904		}
 905	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_FILE)
 906		{
 907			printf ("type error - expecting file\n");
 908			psc->quit = 1;
 909			return 0;
 910		}
 911	*result = psc->value_stack[psc->n_values - index].val.file_val;
 912	return 1;
 913}
 914
 915/* return 1 on success, with result set to the top of the value stack */
 916static int
 917get_stack_string (Gt1PSContext *psc, Gt1String *result, int index)
 918{
 919	if (psc->n_values < index)
 920		{
 921			printf ("stack underflow\n");
 922			psc->quit = 1;
 923			return 0;
 924		}
 925	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_STR)
 926		{
 927			printf ("type error - expecting string\n");
 928			psc->quit = 1;
 929			return 0;
 930		}
 931	*result = psc->value_stack[psc->n_values - index].val.str_val;
 932	return 1;
 933}
 934
 935/* return 1 on success, with result set to the top of the value stack */
 936static int
 937get_stack_array (Gt1PSContext *psc, Gt1Array **result, int index)
 938{
 939	if (psc->n_values < index)
 940		{
 941			printf ("stack underflow\n");
 942			psc->quit = 1;
 943			return 0;
 944		}
 945	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_ARRAY)
 946		{
 947			printf ("type error - expecting array\n");
 948			psc->quit = 1;
 949			return 0;
 950		}
 951	*result = psc->value_stack[psc->n_values - index].val.array_val;
 952	return 1;
 953}
 954
 955/* return 1 on success, with result set to the top of the value stack */
 956static int
 957get_stack_bool (Gt1PSContext *psc, int *result, int index)
 958{
 959	if (psc->n_values < index)
 960		{
 961			printf ("stack underflow\n");
 962			psc->quit = 1;
 963			return 0;
 964		}
 965	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_BOOL)
 966		{
 967			printf ("type error - expecting bool\n");
 968			psc->quit = 1;
 969			return 0;
 970		}
 971	*result = psc->value_stack[psc->n_values - index].val.bool_val;
 972	return 1;
 973}
 974
 975/* return 1 on success, with result set to the top of the value stack */
 976static int
 977get_stack_proc (Gt1PSContext *psc, Gt1Proc **result, int index)
 978{
 979	if (psc->n_values < index)
 980		{
 981			printf ("stack underflow\n");
 982			psc->quit = 1;
 983			return 0;
 984		}
 985	if (psc->value_stack[psc->n_values - index].type != GT1_VAL_PROC)
 986		{
 987			printf ("type error - expecting proc\n");
 988			psc->quit = 1;
 989			return 0;
 990		}
 991	*result = psc->value_stack[psc->n_values - index].val.proc_val;
 992	return 1;
 993}
 994
 995/* here begin the internal procedures */
 996
 997static void
 998internal_dict (Gt1PSContext *psc)
 999{
1000	Gt1Dict *dict;
1001	double d_size;
1002
1003	if (get_stack_number (psc, &d_size, 1))
1004		{
1005			dict = gt1_dict_new (psc->r, (int)d_size);
1006			psc->value_stack[psc->n_values - 1].type = GT1_VAL_DICT;
1007			psc->value_stack[psc->n_values - 1].val.dict_val = dict;
1008		}
1009}
1010
1011static void
1012internal_begin (Gt1PSContext *psc)
1013{
1014	Gt1Dict *dict;
1015
1016	if (get_stack_dict (psc, &dict, 1))
1017		{
1018			if (psc->n_dicts == psc->n_dicts_max)
1019	gt1_double (psc->gt1_dict_stack, Gt1Dict *, psc->n_dicts_max);
1020			psc->gt1_dict_stack[psc->n_dicts++] = dict;
1021			psc->n_values--;
1022		}
1023}
1024
1025static void
1026internal_end (Gt1PSContext *psc)
1027{
1028	/* note: this magic constant changes if we separate out the internal
1029		 dict from the user one; in fact, GhostScript uses three. */
1030	if (psc->n_dicts == 1)
1031		{
1032			printf ("dict stack underflow\n");
1033			psc->quit = 1;
1034		}
1035	psc->n_dicts--;
1036}
1037
1038static void
1039internal_dup (Gt1PSContext *psc)
1040{
1041	if (psc->n_values == 0)
1042		{
1043			printf ("stack underflow\n");
1044			psc->quit = 1;
1045		}
1046	else
1047		{
1048			ensure_stack (psc, 1);
1049			psc->value_stack[psc->n_values] =
1050	psc->value_stack[psc->n_values - 1];
1051			psc->n_values++;
1052		}
1053}
1054
1055static void
1056internal_pop (Gt1PSContext *psc)
1057{
1058	if (psc->n_values == 0)
1059		{
1060			printf ("stack underflow\n");
1061			psc->quit = 1;
1062		}
1063	else
1064			psc->n_values--;
1065}
1066
1067static void
1068internal_exch (Gt1PSContext *psc)
1069{
1070	Gt1Value tmp;
1071	int stack_size;
1072
1073	stack_size = psc->n_values;
1074	if (stack_size < 2)
1075		{
1076			printf ("stack underflow\n");
1077			psc->quit = 1;
1078		}
1079	else
1080		{
1081			tmp = psc->value_stack[stack_size - 2];
1082			psc->value_stack[stack_size - 2] =
1083	psc->value_stack[stack_size - 1];
1084			psc->value_stack[stack_size - 1] = tmp;
1085		}
1086}
1087
1088/* this doesn't do anything - we don't enforce readonly */
1089static void
1090internal_readonly (Gt1PSContext *psc)
1091{
1092	if (psc->n_values == 0)
1093		{
1094			printf ("stack underflow\n");
1095			psc->quit = 1;
1096		}
1097}
1098
1099/* this doesn't do anything - we don't enforce executeonly */
1100static void
1101internal_executeonly (Gt1PSContext *psc)
1102{
1103	if (psc->n_values == 0)
1104		{
1105			printf ("stack underflow\n");
1106			psc->quit = 1;
1107		}
1108}
1109
1110/* this doesn't do anything - we don't enforce noaccess */
1111static void
1112internal_noaccess (Gt1PSContext *psc)
1113{
1114	if (psc->n_values == 0)
1115		{
1116			printf ("stack underflow\n");
1117			psc->quit = 1;
1118		}
1119}
1120
1121static void
1122internal_def (Gt1PSContext *psc)
1123{
1124	Gt1NameId key;
1125	Gt1Dict *dict;
1126
1127	if (get_stack_name (psc, &key, 2))
1128		{
1129			dict = psc->gt1_dict_stack[psc->n_dicts - 1];
1130			gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
1131			psc->n_values -= 2;
1132		}
1133}
1134
1135static void
1136internal_false (Gt1PSContext *psc)
1137{
1138	ensure_stack (psc, 1);
1139	psc->value_stack[psc->n_values].type = GT1_VAL_BOOL;
1140	psc->value_stack[psc->n_values].val.bool_val = gt1_false;
1141	psc->n_values++;
1142}
1143
1144static void
1145internal_true (Gt1PSContext *psc)
1146{
1147	ensure_stack (psc, 1);
1148	psc->value_stack[psc->n_values].type = GT1_VAL_BOOL;
1149	psc->value_stack[psc->n_values].val.bool_val = gt1_true;
1150	psc->n_values++;
1151}
1152
1153static void
1154internal_StandardEncoding (Gt1PSContext *psc)
1155{
1156	ensure_stack (psc, 1);
1157	/* todo: push actual encoding array */
1158	psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
1159	psc->value_stack[psc->n_values].val.num_val = 42;
1160	psc->n_values++;
1161}
1162
1163static void
1164internalop_openbracket (Gt1PSContext *psc)
1165{
1166	ensure_stack (psc, 1);
1167	psc->value_stack[psc->n_values].type = GT1_VAL_MARK;
1168	psc->n_values++;
1169}
1170
1171static void
1172internalop_closebracket (Gt1PSContext *psc)
1173{
1174	int i;
1175	Gt1Array *array;
1176	int size, start_idx;
1177
1178	for (i = psc->n_values - 1; i >= 0; i--)
1179		if (psc->value_stack[i].type == GT1_VAL_MARK)
1180			break;
1181	if (psc->value_stack[i].type != GT1_VAL_MARK)
1182		{
1183			printf ("unmatched mark\n");
1184			psc->quit = 1;
1185		}
1186	start_idx = i + 1;
1187	size = psc->n_values - start_idx;
1188	array = array_new (psc->r, size);
1189	for (i = 0; i < size; i++)
1190		array->vals[i] = psc->value_stack[start_idx + i];
1191	psc->n_values -= size;
1192	psc->value_stack[psc->n_values - 1].type = GT1_VAL_ARRAY;
1193	psc->value_stack[psc->n_values - 1].val.array_val = array;
1194}
1195
1196static void
1197internal_currentdict (Gt1PSContext *psc)
1198{
1199	ensure_stack (psc, 1);
1200	psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
1201	psc->value_stack[psc->n_values].val.dict_val =
1202		psc->gt1_dict_stack[psc->n_dicts - 1];
1203	psc->n_values++;
1204}
1205
1206static void
1207internal_currentfile (Gt1PSContext *psc)
1208{
1209	/* todo: we want to move away from a tc pointer towards tags, to avoid
1210		 potential security holes from misusing these data structures */
1211	ensure_stack (psc, 1);
1212	psc->value_stack[psc->n_values].type = GT1_VAL_FILE;
1213	psc->value_stack[psc->n_values].val.file_val = psc->tc;
1214	psc->n_values++;
1215}
1216
1217#define EEXEC_C1 ((unsigned short)52845)
1218#define EEXEC_C2 ((unsigned short)22719)
1219
1220/* return number of bytes in result */
1221static int
1222decrypt_eexec (char *plaintext, const char *ciphertext, int ciphertext_size)
1223{
1224	int i;
1225	unsigned short r;
1226	unsigned char cipher;
1227	unsigned char plain;
1228
1229	r = 55665;	/* initial key */
1230
1231	for (i = 0; i < ciphertext_size; i++)
1232		{
1233			cipher = ciphertext[i];
1234			plain = (cipher ^ (r>>8));
1235			r = (cipher + r) * EEXEC_C1 + EEXEC_C2;
1236			if (i >= 4)
1237	plaintext[i - 4] = plain;
1238		}
1239	return ciphertext_size - 4;
1240}
1241
1242/* this one is great fun! */
1243static void
1244internal_eexec (Gt1PSContext *psc)
1245{
1246	Gt1TokenContext *file_tc;
1247	char *ciphertext;
1248	int ciphertext_size, ciphertext_size_max;
1249	char *plaintext;
1250	int plaintext_size;
1251	int num_nulls;
1252	int byte;
1253	MyGt1String string;
1254	Gt1TokenContext *new_tc;
1255
1256	if (get_stack_file (psc, &file_tc, 1))
1257		{
1258			psc->n_values--;
1259
1260			/* first, suck the encrypted stream from the specified file */
1261			ciphertext_size = 0;
1262			ciphertext_size_max = 512;
1263			ciphertext = gt1_new (char, ciphertext_size_max);
1264			num_nulls = 0;
1265			while (num_nulls < 16)
1266	{
1267		if (ciphertext_size == ciphertext_size_max)
1268			gt1_double (ciphertext, char, ciphertext_size_max);
1269		byte = tokenize_get_hex_byte (file_tc);
1270		if (byte < 0)
1271			{
1272				printf ("eexec input appears to be truncated\n");
1273				psc->quit = 1;
1274				return;
1275			}
1276		if (byte == 0)
1277			num_nulls++;
1278		else
1279			num_nulls = 0;
1280		ciphertext[ciphertext_size++] = byte;
1281	}
1282
1283			/* then, decrypt it */
1284			plaintext = gt1_new (char, ciphertext_size);
1285			plaintext_size = decrypt_eexec (plaintext, ciphertext, ciphertext_size);
1286			gt1_free (ciphertext);
1287
1288#if 1 && defined(VERBOSE)
1289			fwrite (plaintext, 1, plaintext_size, stdout);
1290#endif
1291
1292			/* finally, create a new Gt1TokenContext for the string, and switch
1293	 to executing it. */
1294			string.start = plaintext;
1295			string.fin = plaintext + plaintext_size;
1296			new_tc = tokenize_new_from_mystring (&string);
1297			gt1_free (plaintext);
1298
1299			if (psc->n_files_max == psc->n_files)
1300	{
1301		printf ("overflow of file stack\n");
1302		psc->quit = 1;
1303		return;
1304	}
1305			psc->file_stack[psc->n_files++] = new_tc;
1306			psc->tc = new_tc;
1307
1308			/* alternatively, we could have recursively called the PostScript
1309	 evaluation loop from here, but this seems to be just as good. */
1310		}
1311}
1312
1313static void
1314internal_array (Gt1PSContext *psc)
1315{
1316	Gt1Array *array;
1317	double d_size;
1318
1319	if (get_stack_number (psc, &d_size, 1))
1320		{
1321			array = array_new (psc->r, (int)d_size);
1322			psc->value_stack[psc->n_values - 1].type = GT1_VAL_ARRAY;
1323			psc->value_stack[psc->n_values - 1].val.array_val = array;
1324		}
1325}
1326
1327static void
1328internal_string (Gt1PSContext *psc)
1329{
1330	Gt1String string;
1331	double d_size;
1332	int size;
1333
1334	if (get_stack_number (psc, &d_size, 1))
1335		{
1336			size = (int)d_size;
1337			string.start = gt1_region_alloc (psc->r, size);
1338			string.size = size;
1339			memset (string.start, 0, size);
1340			psc->value_stack[psc->n_values - 1].type = GT1_VAL_STR;
1341			psc->value_stack[psc->n_values - 1].val.str_val = string;
1342		}
1343}
1344
1345static void
1346internal_readstring (Gt1PSContext *psc)
1347{
1348	Gt1String string;
1349	Gt1TokenContext *file_tc;
1350
1351	if (get_stack_string (psc, &string, 1) &&
1352			get_stack_file (psc, &file_tc, 2))
1353		{
1354			tokenize_get_raw (file_tc, string.start, string.size);
1355			psc->value_stack[psc->n_values - 2].type = GT1_VAL_STR;
1356			psc->value_stack[psc->n_values - 2].val.str_val = string;
1357			psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
1358			psc->value_stack[psc->n_values - 1].val.bool_val = gt1_true;
1359		}
1360}
1361
1362static void
1363internal_put (Gt1PSContext *psc)
1364{
1365	Gt1Array *array;
1366	double d_index;
1367	int index;
1368	Gt1Dict *dict;
1369	Gt1NameId key;
1370
1371	if (psc->n_values >= 3 &&
1372			psc->value_stack[psc->n_values - 3].type == GT1_VAL_DICT &&
1373			get_stack_name (psc, &key, 2))
1374		{
1375			/* dict key val		put  -- */
1376			get_stack_dict (psc, &dict, 3);
1377			gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
1378			psc->n_values -= 3;
1379		}
1380	else if (psc->n_values >= 3 &&
1381		 psc->value_stack[psc->n_values - 3].type == GT1_VAL_PROC &&
1382		 get_stack_number (psc, &d_index, 2))
1383		{
1384			array = psc->value_stack[psc->n_values - 3].val.proc_val;
1385			index = (int)d_index;
1386			if (index < 0 || index >= array->n_values)
1387	{
1388		printf ("range check\n");
1389		psc->quit = 1;
1390		return;
1391	}
1392			array->vals[index] = psc->value_stack[psc->n_values - 1];
1393			psc->n_values -= 3;
1394		}
1395	else if (psc->n_values >= 3 &&
1396		 get_stack_array (psc, &array, 3) &&
1397		 get_stack_number (psc, &d_index, 2))
1398		{
1399			/* array index val	put  -- */
1400			index = (int)d_index;
1401			if (index < 0 || index >= array->n_values)
1402	{
1403		printf ("range check\n");
1404		psc->quit = 1;
1405		return;
1406	}
1407			array->vals[index] = psc->value_stack[psc->n_values - 1];
1408			psc->n_values -= 3;
1409		}
1410}
1411
1412static void
1413internal_get (Gt1PSContext *psc)
1414{
1415	Gt1Array *array;
1416	double d_index;
1417	int index;
1418	Gt1Dict *dict;
1419	Gt1NameId key;
1420	Gt1Value *val;
1421
1422	if (psc->n_values >= 2 &&
1423			psc->value_stack[psc->n_values - 2].type == GT1_VAL_DICT &&
1424			get_stack_name (psc, &key, 1))
1425		{
1426			/* dict key		 get	val */
1427			get_stack_dict (psc, &dict, 2);
1428			val = gt1_dict_lookup (dict, key);
1429			if (val == NULL)
1430	{
1431		printf ("key not found\n");
1432		psc->quit = 1;
1433		return;
1434	}
1435#ifdef VERBOSE
1436			printf ("value: ");
1437			print_value (psc, val);
1438			printf ("\n");
1439#endif
1440			psc->n_values -= 1;
1441			psc->value_stack[psc->n_values - 1] = *val;
1442		}
1443	else if (psc->n_values >= 2 &&
1444		 psc->value_stack[psc->n_values - 2].type == GT1_VAL_PROC &&
1445		 get_stack_number (psc, &d_index, 1))
1446		{
1447			/* array index	get  val */
1448			array = psc->value_stack[psc->n_values - 2].val.proc_val;
1449			index = (int)d_index;
1450			if (index < 0 || index >= array->n_values)
1451	{
1452		printf ("range check\n");
1453		psc->quit = 1;
1454		return;
1455	}
1456			psc->n_values -= 1;
1457			psc->value_stack[psc->n_values - 1] = array->vals[index];
1458		}
1459	else if (get_stack_array (psc, &array, 2) &&
1460		 get_stack_number (psc, &d_index, 1))
1461		{
1462			/* array index	get  val */
1463			index = (int)d_index;
1464			if (index < 0 || index >= array->n_values)
1465	{
1466		printf ("range check\n");
1467		psc->quit = 1;
1468		return;
1469	}
1470			psc->n_values -= 1;
1471			psc->value_stack[psc->n_values - 1] = array->vals[index];
1472		}
1473}
1474
1475static void
1476internal_index (Gt1PSContext *psc)
1477{
1478	double d_index;
1479	int index;
1480
1481	if (get_stack_number (psc, &d_index, 1))
1482		{
1483			index = (int)d_index;
1484			if (index < 0 || index > psc->n_values - 2)
1485	{
1486		printf ("index range check\n");
1487		psc->quit = 1;
1488		return;
1489	}
1490			psc->value_stack[psc->n_values - 1] =
1491	psc->value_stack[psc->n_values - (index + 2)];
1492		}
1493}
1494
1495static void
1496internal_definefont (Gt1PSContext *psc)
1497{
1498	Gt1NameId key;
1499	Gt1Dict *dict;
1500
1501	if (psc->n_values < 2)
1502		{
1503			printf ("stack underflow\n");
1504			psc->quit = 1;
1505		}
1506	else if (get_stack_name (psc, &key, 2))
1507		{
1508			dict = psc->fonts;
1509			gt1_dict_def (psc->r, dict, key, &psc->value_stack[psc->n_values - 1]);
1510#ifdef VERBOSE
1511			print_value_deep (psc, &psc->value_stack[psc->n_values - 1], 0);
1512#endif
1513			psc->n_values -= 1;
1514		}
1515}
1516
1517static void
1518internal_mark (Gt1PSContext *psc)
1519{
1520	ensure_stack (psc, 1);
1521	psc->value_stack[psc->n_values].type = GT1_VAL_MARK;
1522	psc->n_values++;
1523}
1524
1525static void
1526internal_closefile (Gt1PSContext *psc)
1527{
1528	Gt1TokenContext *tc;
1529
1530	if (get_stack_file (psc, &tc, 1))
1531		{
1532			if (psc->n_files == 1)
1533	{
1534		printf ("file stack underflow\n");
1535		psc->quit = 1;
1536	}
1537			else if (psc->file_stack[psc->n_files - 1] == tc)
1538	{
1539		/* pop the file stack */
1540		tokenize_free (psc->tc);
1541		psc->n_files--;
1542		psc->tc = psc->file_stack[psc->n_files - 1];
1543		psc->n_values--;
1544	}
1545			else
1546	{
1547		printf ("closefile: whoa, file cowboy!\n");
1548		psc->quit = 1;
1549	}
1550		}
1551}
1552
1553static void
1554internal_cleartomark (Gt1PSContext *psc)
1555{
1556	int i;
1557
1558	for (i = psc->n_values - 1; i >= 0; i--)
1559		if (psc->value_stack[i].type == GT1_VAL_MARK)
1560			break;
1561	if (psc->value_stack[i].type != GT1_VAL_MARK)
1562		{
1563			printf ("cleartomark: unmatched mark\n");
1564			psc->quit = 1;
1565		}
1566	psc->n_values = i;
1567}
1568
1569static void
1570internal_systemdict (Gt1PSContext *psc)
1571{
1572	ensure_stack (psc, 1);
1573	psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
1574	psc->value_stack[psc->n_values].val.dict_val =
1575		psc->gt1_dict_stack[0];
1576	psc->n_values++;
1577}
1578
1579static void
1580internal_userdict (Gt1PSContext *psc)
1581{
1582	ensure_stack (psc, 1);
1583	psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
1584	psc->value_stack[psc->n_values].val.dict_val =
1585		psc->gt1_dict_stack[2];
1586	psc->n_values++;
1587}
1588
1589static void
1590internal_known (Gt1PSContext *psc)
1591{
1592	Gt1NameId key;
1593	Gt1Dict *dict;
1594	int known;
1595
1596	if (psc->n_values >= 2 &&
1597			get_stack_dict (psc, &dict, 2) &&
1598			get_stack_name (psc, &key, 1))
1599		{
1600			known = (gt1_dict_lookup (dict, key) != 0);
1601			psc->n_values -= 1;
1602			psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
1603			psc->value_stack[psc->n_values - 1].val.bool_val = known;
1604		}
1605}
1606
1607static void
1608internal_ifelse (Gt1PSContext *psc)
1609{
1610	Gt1Proc *proc1, *proc2;
1611	int bool;
1612
1613	if (psc->n_values >= 3 &&
1614			get_stack_bool (psc, &bool, 3) &&
1615			get_stack_proc (psc, &proc1, 2) &&
1616			get_stack_proc (psc, &proc2, 1))
1617		{
1618			psc->n_values -= 3;
1619			if (bool)
1620	eval_proc (psc, proc1);
1621			else
1622	eval_proc (psc, proc2);
1623		}
1624}
1625
1626static void
1627internal_if (Gt1PSContext *psc)
1628{
1629	Gt1Proc *proc;
1630	int bool;
1631
1632	if (psc->n_values >= 2 &&
1633			get_stack_bool (psc, &bool, 2) &&
1634			get_stack_proc (psc, &proc, 1))
1635		{
1636			psc->n_values -= 2;
1637			if (bool)
1638	eval_proc (psc, proc);
1639		}
1640}
1641
1642static void
1643internal_for (Gt1PSContext *psc)
1644{
1645	double initial, increment, limit;
1646	Gt1Proc *proc;
1647	double val;
1648
1649	if (psc->n_values >= 4 &&
1650			get_stack_number (psc, &initial, 4) &&
1651			get_stack_number (psc, &increment, 3) &&
1652			get_stack_number (psc, &limit, 2) &&
1653			get_stack_proc (psc, &proc, 1))
1654		{
1655			psc->n_values -= 4;
1656			for (val = initial; !psc->quit &&
1657			 (increment > 0 ? (val <= limit) : (val >= limit));
1658		 val += increment)
1659	{
1660		ensure_stack (psc, 1);
1661		psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
1662		psc->value_stack[psc->n_values].val.num_val = val;
1663		psc->n_values++;
1664		eval_proc (psc, proc);
1665	}
1666		}
1667}
1668
1669static void
1670internal_not (Gt1PSContext *psc)
1671{
1672	int bool;
1673
1674	if (psc->n_values >= 1 &&
1675			get_stack_bool (psc, &bool, 1))
1676		{
1677			psc->value_stack[psc->n_values - 1].val.bool_val = !bool;
1678		}
1679}
1680
1681static void
1682internal_bind (Gt1PSContext *psc)
1683{
1684	Gt1Proc *proc;
1685
1686	if (psc->n_values >= 1 &&
1687			get_stack_proc (psc, &proc, 1))
1688		{
1689			/* todo: implement, when procs become normal values */
1690		}
1691}
1692
1693static void
1694internal_exec (Gt1PSContext *psc)
1695{
1696	Gt1Proc *proc;
1697
1698	if (psc->n_values >= 1 &&
1699			get_stack_proc (psc, &proc, 1))
1700		{
1701			psc->n_values -= 1;
1702			eval_proc (psc, proc);
1703		}
1704}
1705
1706static void
1707internal_count (Gt1PSContext *psc)
1708{
1709	ensure_stack (psc, 1);
1710	psc->value_stack[psc->n_values].type = GT1_VAL_NUM;
1711	psc->value_stack[psc->n_values].val.num_val = psc->n_values;
1712	psc->n_values++;
1713}
1714
1715static void
1716internal_eq (Gt1PSContext *psc)
1717{
1718	double a, b;
1719	Gt1NameId na, nb;
1720
1721	if (psc->n_values < 2)
1722		{
1723			printf ("stack underflow\n");
1724			psc->quit = 1;
1725			return;
1726		}
1727	if (psc->value_stack[psc->n_values - 1].type == GT1_VAL_NAME &&
1728			get_stack_name (psc, &na, 2) &&
1729			get_stack_name (psc, &nb, 1))
1730		{
1731			psc->n_values -= 1;
1732			psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
1733			psc->value_stack[psc->n_values - 1].val.bool_val = (na == nb);
1734		}
1735	else if (get_stack_number (psc, &a, 2) &&
1736			get_stack_number (psc, &b, 1))
1737		{
1738			psc->n_values -= 1;
1739			psc->value_stack[psc->n_values - 1].type = GT1_VAL_BOOL;
1740			psc->value_stack[psc->n_values - 1].val.bool_val = (a == b);
1741		}
1742}
1743
1744static void
1745internal_ne (Gt1PSContext *psc)
1746{
1747	internal_eq (psc);
1748	if (!psc->quit)
1749		psc->value_stack[psc->n_values - 1].val.bool_val =
1750			!psc->value_stack[psc->n_values - 1].val.bool_val;
1751}
1752
1753static void
1754internal_type (Gt1PSContext *psc)
1755{
1756	Gt1ValueType type;
1757
1758	if (psc->n_values >= 1)
1759		{
1760			type = psc->value_stack[psc->n_values - 1].type;
1761			if (type == GT1_VAL_NUM)
1762	{
1763		psc->value_stack[psc->n_values - 1].type = GT1_VAL_NAME;
1764		psc->value_stack[psc->n_values - 1].val.name_val =
1765			gt1_name_context_intern (psc->nc, "integertype");
1766	}
1767			else
1768	{
1769		printf ("type not fully implemented");
1770	}
1771		}
1772}
1773
1774static void
1775internal_cvx (Gt1PSContext *psc)
1776{
1777	Gt1Value *val;
1778
1779	if (psc->n_values < 1)
1780		{
1781			printf ("stack underflow\n");
1782			psc->quit = 1;
1783		}
1784	else
1785		{
1786			val = &psc->value_stack[psc->n_values - 1];
1787			if (val->type == GT1_VAL_NAME)
1788	val->type = GT1_VAL_UNQ_NAME;
1789			else if (val->type == GT1_VAL_ARRAY)
1790	val->type = GT1_VAL_PROC;
1791			else
1792	{
1793		printf ("warning: cvx called on ");
1794		print_value (psc, val);
1795		printf ("\n");
1796	}
1797		}
1798}
1799
1800static void
1801internal_matrix (Gt1PSContext *psc)
1802{
1803	Gt1Array *array;
1804	int i;
1805
1806	array = array_new (psc->r, 6);
1807	for (i = 0; i < 6; i++)
1808		{
1809			array->vals[i].type = GT1_VAL_NUM;
1810			array->vals[i].val.num_val = (i == 0 || i == 3);
1811		}
1812	psc->value_stack[psc->n_values].type = GT1_VAL_ARRAY;
1813	psc->value_stack[psc->n_values].val.array_val = array;
1814	psc->n_values++;
1815}
1816
1817static void
1818internal_FontDirectory (Gt1PSContext *psc)
1819{
1820	ensure_stack (psc, 1);
1821	psc->value_stack[psc->n_values].type = GT1_VAL_DICT;
1822	psc->value_stack[psc->n_values].val.dict_val = psc->fonts;
1823	psc->n_values++;
1824}
1825
1826/* the table of internal procedures */
1827
1828typedef struct _InternalGt1ProcListing {
1829	char *name;
1830	void (*function) (Gt1PSContext *psc);
1831} InternalGt1ProcListing;
1832
1833InternalGt1ProcListing internal_procs[] = {
1834	{ "dict", internal_dict },
1835	{ "begin", internal_begin },
1836	{ "end", internal_end },
1837	{ "dup", internal_dup },
1838	{ "pop", internal_pop },
1839	{ "exch", internal_exch },
1840	{ "readonly", internal_readonly },
1841	{ "executeonly", internal_executeonly },
1842	{ "noaccess", internal_noaccess },
1843	{ "def", internal_def },
1844	{ "false", internal_false },
1845	{ "true", internal_true },
1846	{ "StandardEncoding", internal_StandardEncoding },
1847	{ "[", internalop_openbracket },
1848	{ "]", internalop_closebracket },
1849	{ "currentdict", internal_currentdict },
1850	{ "currentfile", internal_currentfile },
1851	{ "eexec", internal_eexec },
1852	{ "array", internal_array },
1853	{ "string", internal_string },
1854	{ "readstring", internal_readstring },
1855	{ "put", internal_put },
1856	{ "get", internal_get },
1857	{ "index", internal_index },
1858	{ "definefont", internal_definefont },
1859	{ "mark", internal_mark },
1860	{ "closefile", internal_closefile },
1861	{ "cleartomark", internal_cleartomark },
1862	{ "systemdict", internal_systemdict },
1863	{ "userdict", internal_userdict },
1864	{ "known", internal_known },
1865	{ "ifelse", internal_ifelse },
1866	{ "if", internal_if },
1867	{ "for", internal_for },
1868	{ "not", internal_not },
1869	{ "bind", internal_bind },
1870	{ "exec", internal_exec },
1871	{ "count", internal_count },
1872	{ "eq", internal_eq },
1873	{ "ne", internal_ne },
1874	{ "type", internal_type },
1875	{ "cvx", internal_cvx },
1876	{ "matrix", internal_matrix },
1877	{ "FontDirectory", internal_FontDirectory }
1878};
1879
1880/* here end the internal procedures */
1881
1882static Gt1PSContext *
1883pscontext_new (Gt1TokenContext *tc)
1884{
1885	Gt1PSContext *psc;
1886	Gt1Dict *systemdict;
1887	Gt1Dict *globaldict;
1888	Gt1Dict *userdict;
1889	int i;
1890	Gt1Value val;
1891
1892	psc = gt1_new (Gt1PSContext, 1);
1893	psc->r = gt1_region_new ();
1894	psc->tc = tc;
1895
1896	psc->nc = gt1_name_context_new ();
1897
1898	psc->n_values = 0;
1899	psc->n_values_max = 16;
1900	psc->value_stack = gt1_new (Gt1Value, psc->n_values_max);
1901
1902	psc->n_dicts_max = 16;
1903	psc->gt1_dict_stack = gt1_new (Gt1Dict *, psc->n_dicts_max);
1904
1905	systemdict = gt1_dict_new (psc->r, sizeof(internal_procs) /
1906			 sizeof(InternalGt1ProcListing));
1907	for (i = 0; i < sizeof(internal_procs) / sizeof(InternalGt1ProcListing); i++)
1908		{
1909			val.type = GT1_VAL_INTERNAL;
1910			val.val.internal_val = internal_procs[i].function;
1911			gt1_dict_def (psc->r, systemdict,
1912				gt1_name_context_intern (psc->nc,
1913							 internal_procs[i].name),
1914				&val);
1915		}
1916	psc->gt1_dict_stack[0] = systemdict;
1917	globaldict = gt1_dict_new (psc->r, 16);
1918	psc->gt1_dict_stack[1] = globaldict;
1919	userdict = gt1_dict_new (psc->r, 16);
1920	psc->gt1_dict_stack[2] = userdict;
1921	psc->n_dicts = 3;
1922
1923	psc->fonts = gt1_dict_new (psc->r, 1);
1924
1925	psc->n_files_max = 16;
1926	psc->file_stack = gt1_new (Gt1TokenContext *, psc->n_files_max);
1927	psc->file_stack[0] = tc;
1928	psc->n_files = 1;
1929
1930	psc->quit = 0;
1931	return psc;
1932}
1933
1934static void
1935pscontext_free (Gt1PSContext *psc)
1936{
1937	/* Empty the value stack.  */
1938	while (psc->n_values > 0) internal_pop (psc);
1939	gt1_free (psc->value_stack);
1940
1941	gt1_free	(psc->file_stack);
1942	gt1_free	(psc->gt1_dict_stack);
1943
1944	gt1_name_context_free (psc->nc);
1945	gt1_region_free (psc->r);
1946
1947	gt1_free (psc);
1948}
1949
1950
1951
1952static void
1953eval_executable (Gt1PSContext *psc, Gt1Value *val)
1954{
1955	switch (val->type)
1956		{
1957		case GT1_VAL_INTERNAL:
1958			val->val.internal_val (psc);
1959			break;
1960		case GT1_VAL_PROC:
1961			eval_proc (psc, val->val.proc_val);
1962			break;
1963		default:
1964			ensure_stack (psc, 1);
1965			psc->value_stack[psc->n_values] = *val;
1966			psc->n_values++;
1967			break;
1968		}
1969}
1970
1971/* Scan a value from the psc's token context - usually one token, or
1972	 a proc. Return the token type. */
1973static TokenType
1974parse_ps_token (Gt1PSContext *psc, Gt1Value *val)
1975{
1976	MyGt1String lexeme;
1977	TokenType type;
1978	Gt1Proc *proc;
1979	int n_proc, n_proc_max;
1980
1981	type = tokenize_get (psc->tc, &lexeme);
1982	switch (type)
1983		{
1984		case TOK_NUM:
1985			val->type = GT1_VAL_NUM;
1986			val->val.num_val = parse_num (&lexeme);
1987			break;
1988		case TOK_NAME:
1989			val->type = GT1_VAL_NAME;
1990			val->val.name_val =
1991	gt1_name_context_intern_size (psc->nc, lexeme.start,
1992					lexeme.fin - lexeme.start);
1993					break;
1994		case TOK_STR:
1995			val->type = GT1_VAL_STR;
1996			/* todo: processing of escape characters */
1997			val->val.str_val.start = lexeme.start;
1998			val->val.str_val.size = lexeme.fin - lexeme.start;
1999			break;
2000		case TOK_IDENT:
2001			val->type = GT1_VAL_UNQ_NAME;
2002			val->val.name_val =
2003	gt1_name_context_intern_size (psc->nc, lexeme.start,
2004					lexeme.fin - lexeme.start);
2005			break;
2006		case TOK_OPENBRACE:
2007			n_proc = 0;
2008			n_proc_max = 16;
2009			proc = (Gt1Proc *)gt1_region_alloc (psc->r, sizeof(Gt1Proc) +
2010					 (n_proc_max - 1) *
2011					 sizeof(Gt1Value));
2012			while (1)
2013	{
2014		if (n_proc == n_proc_max)
2015			{
2016				int old_size;
2017
2018				old_size = sizeof(Gt1Proc) + (n_proc_max - 1) * sizeof(Gt1Value);
2019				n_proc_max <<= 1;
2020
2021				proc = (Gt1Proc *)gt1_region_realloc (psc->r, proc,
2022							 old_size,
2023							 sizeof(Gt1Proc) +
2024							 (n_proc_max - 1) *
2025							 sizeof(Gt1Value));
2026			}
2027		if (parse_ps_token (psc, &proc->vals[n_proc]) == TOK_CLOSEBRACE ||
2028				psc->quit)
2029			break;
2030		n_proc++;
2031	}
2032			proc->n_values = n_proc;
2033			val->type = GT1_VAL_PROC;
2034			val->val.proc_val = proc;
2035			break;
2036		case TOK_CLOSEBRACE:
2037		case TOK_END:
2038			break;
2039		default:
2040			printf ("unimplemented token type\n");
2041			psc->quit = 1;
2042			break;
2043		}
2044	return type;
2045}
2046
2047static void
2048eval_ps_val (Gt1PSContext *psc, Gt1Value *val)
2049{
2050	Gt1Value *new_val;
2051
2052#ifdef VERBOSE
2053	print_value (psc, val);
2054	printf ("\n");
2055#endif
2056	switch (val->type)
2057		{
2058		case GT1_VAL_NUM:
2059		case GT1_VAL_BOOL:
2060		case GT1_VAL_STR:
2061		case GT1_VAL_NAME:
2062		case GT1_VAL_ARRAY:
2063		case GT1_VAL_PROC:
2064		case GT1_VAL_DICT:
2065			ensure_stack (psc, 1);
2066			psc->value_stack[psc->n_values] = *val;
2067			psc->n_values++;
2068			break;
2069		case GT1_VAL_UNQ_NAME:
2070			new_val = gt1_dict_stack_lookup (psc, val->val.name_val);
2071			if (new_val != NULL)
2072	eval_executable (psc, new_val);
2073			else
2074	{
2075		printf ("undefined identifier ");
2076		print_value (psc, val);
2077		putchar ('\n');
2078		psc->quit = 1;
2079	}
2080			break;
2081		case GT1_VAL_INTERNAL:
2082			val->val.internal_val (psc);
2083			break;
2084		default:
2085			printf ("value not handled\n");
2086			psc->quit = 1;
2087			break;
2088		}
2089#ifdef VERBOSE
2090	if (!psc->quit)
2091		{
2092			printf ("		");
2093			print_stack (psc);
2094		}
2095#endif
2096}
2097
2098/* maybe we should return the dict; easier to handle */
2099static Gt1PSContext *
2100eval_ps (Gt1TokenContext *tc)
2101{
2102	TokenType type;
2103	Gt1PSContext *psc;
2104	Gt1Value val;
2105
2106	psc = pscontext_new (tc);
2107	do {
2108		type = parse_ps_token (psc, &val);
2109		if (type == TOK_END) break;
2110		if (type == TOK_CLOSEBRACE)
2111			{
2112	printf ("unexpected close brace\n");
2113	break;
2114			}
2115		eval_ps_val (psc, &val);
2116	} while (!psc->quit);
2117
2118	return psc;
2119}
2120
2121/* This routine _assumes_ that plaintext is passed in with enough
2122	 space to hold the decrypted text */
2123static void
2124charstring_decrypt (Gt1String *plaintext, Gt1String *ciphertext)
2125{
2126	int ciphertext_size;
2127	int i;
2128	unsigned short r;
2129	unsigned char cipher;
2130	unsigned char plain;
2131
2132	ciphertext_size = ciphertext->size;
2133	if (plaintext->size < ciphertext_size - 4)
2134		{
2135			printf ("not enough space allocated for charstring decryption\n");
2136			return;
2137		}
2138
2139	r = 4330;  /* initial key */
2140
2141	for (i = 0; i < ciphertext_size; i++)
2142		{
2143			cipher = ciphertext->start[i];
2144			plain = (cipher ^ (r>>8));
2145			r = (cipher + r) * EEXEC_C1 + EEXEC_C2;
2146			if (i >= 4)
2147	plaintext->start[i - 4] = plain;
2148		}
2149	plaintext->size = ciphertext->size - 4;
2150}
2151
2152#ifdef VERBOSE
2153static void
2154print_glyph_code (Gt1String *glyph_code)
2155{
2156	Gt1String plaintext;
2157	int i;
2158	int byte, byte1, byte2, byte3, byte4;
2159
2160	plaintext.start = gt1_alloc (glyph_code->size);
2161	plaintext.size = glyph_code->size;
2162	charstring_decrypt (&plaintext, glyph_code);
2163
2164	for (i = 0; i < plaintext.size; i++)
2165		{
2166			byte = ((unsigned char *)plaintext.start)[i];
2167			if (byte >= 32 && byte <= 246)
2168	printf (" %d", byte - 139);
2169			else if (byte >= 247 && byte <= 250)
2170	{
2171		byte1 = ((unsigned char *)plaintext.start)[++i];
2172		printf (" %d", ((byte - 247) << 8) + byte1 + 108);
2173	}
2174			else if (byte >= 251 && byte <= 254)
2175	{
2176		byte1 = ((unsigned char *)plaintext.start)[++i];
2177		printf (" %d", -((byte - 251) << 8) - byte1 - 108);
2178	}
2179			else if (byte == 255)
2180	{
2181		byte1 = ((unsigned char *)plaintext.start)[++i];
2182		byte2 = ((unsigned char *)plaintext.start)[++i];
2183		byte3 = ((unsigned char *)plaintext.start)[++i];
2184		byte4 = ((unsigned char *)plaintext.start)[++i];
2185		/* warning: this _must_ be a 32 bit int - alpha portability
2186			 issue! */
2187		printf (" %d", (byte1 << 24) + (byte2 << 16) + (byte3 << 8) + byte4);
2188	}
2189			else if (byte == 12)
2190	{
2191		byte1 = ((unsigned char *)plaintext.start)[++i];
2192		if (byte1 == 6)
2193			printf (" seac");
2194		else if (byte1 == 7)
2195			printf (" sbw");
2196		else if (byte1 == 0)
2197			printf (" dotsection");
2198		else if (byte1 == 2)
2199			printf (" hstem3");
2200		else if (byte1 == 1)
2201			printf (" vstem3");
2202		else if (byte1 == 12)
2203			printf (" div");
2204		else if (byte1 == 16)
2205			printf (" callothersubr");
2206		else if (byte1 == 17)
2207			printf (" pop");
2208		else if (byte1 == 33)
2209			printf (" setcurrentpoint");
2210		else
2211			printf (" esc%d", byte1);
2212	}
2213			else if (byte == 14)
2214	printf (" endchar");
2215			else if (byte == 13)
2216	printf (" hsbw");
2217			else if (byte == 9)
2218	printf (" closepath");
2219			else if (byte == 6)
2220	printf (" hlineto");
2221			else if (byte == 22)
2222	printf (" hmoveto");
2223			else if (byte == 31)
2224	printf (" hvcurveto");
2225			else if (byte == 5)
2226	printf (" rlineto");
2227			else if (byte == 21)
2228	printf (" rmoveto");
2229			else if (byte == 8)
2230	printf (" rrcurveto");
2231			else if (byte == 30)
2232	printf (" vhcurveto");
2233			else if (byte == 7)
2234	printf (" vlineto");
2235			else if (byte == 4)
2236	printf (" vmoveto");
2237			else if (byte == 1)
2238	printf (" hstem");
2239			else if (byte == 3)
2240	printf (" vstem");
2241			else if (byte == 10)
2242	printf (" callsubr");
2243			else if (byte == 11)
2244	printf (" return");
2245			else
2246	printf (" com%d", byte);
2247		}
2248	printf ("\n");
2249	gt1_free (plaintext.start);
2250}
2251#endif
2252
2253/* Gt1Dict is the toplevel font dict. This allocates a new string for the
2254	 plaintext and stores it in body. */
2255static void
2256get_subr_body (Gt1PSContext *psc, Gt1String *body, Gt1Dict *fontdict, int subr)
2257{
2258	Gt1Value *private_val;
2259	Gt1Value *subrs_val;
2260	Gt1Array *subrs_array;
2261	Gt1String *ciphertext;
2262
2263	private_val = gt1_dict_lookup (fontdict,
2264					 gt1_name_context_intern (psc->nc, "Private"));
2265	if (private_val == NULL)
2266		{
2267			printf ("No Private array\n");
2268			return;
2269		}
2270	subrs_val = gt1_dict_lookup (private_val->val.dict_val,
2271				 gt1_name_context_intern (psc->nc, "Subrs"));
2272	if (subrs_val == NULL)
2273		{
2274			printf ("No Subrs array\n");
2275			return;
2276		}
2277	subrs_array = subrs_val->val.array_val;
2278	/* more type & range checking */
2279	ciphertext = &subrs_array->vals[subr].val.str_val;
2280	body->start = gt1_alloc (ciphertext->size);
2281	body->size = ciphertext->size;
2282	charstring_decrypt (body, ciphertext);
2283}
2284
2285typedef struct _BezState {
2286	ArtBpath *bezpath;
2287	int size_bezpath, size_bezpath_max;
2288
2289/* this is designed to do compression of a string of moveto's in a row. */
2290	int need_moveto;
2291
2292	double x, y; /* current point */
2293	double x0, y0; /* beginning of subpath */
2294} BezState;
2295
2296static BezState *
2297bs_new (void)
2298{
2299	BezState *bs;
2300
2301	bs = gt1_new (BezState, 1);
2302
2303	bs->size_bezpath = 0;
2304	bs->size_bezpath_max = 16;
2305	bs->bezpath = gt1_new (ArtBpath, bs->size_bezpath_max);
2306
2307	bs->x = 0;
2308	bs->y = 0;
2309	bs->x0 = 0;
2310	bs->y0 = 0;
2311	bs->need_moveto = 1;
2312
2313	return bs;
2314}
2315
2316static void
2317bs_moveto (BezState *bs, double x, double y)
2318{
2319	bs->x = x;
2320	bs->y = y;
2321	bs->need_moveto = 1;
2322}
2323
2324static void
2325bs_rmoveto (BezState *bs, double dx, double dy)
2326{
2327	bs->x += dx;
2328	bs->y += dy;
2329	bs->need_moveto = 1;
2330}
2331
2332static void
2333bs_do_moveto (BezState *bs)
2334{
2335	ArtBpath *bezpath;
2336	int size_bezpath;
2337
2338	if (bs->need_moveto)
2339		{
2340			bezpath = bs->bezpath;
2341			size_bezpath = bs->size_bezpath;
2342
2343			if (size_bezpath == bs->size_bezpath_max)
2344	{
2345		gt1_double (bezpath, ArtBpath, bs->size_bezpath_max);
2346		bs->bezpath = bezpath;
2347	}
2348			bezpath[size_bezpath].code = ART_MOVETO;
2349			bezpath[size_bezpath].x1 = 0;
2350			bezpath[size_bezpath].y1 = 0;
2351			bezpath[size_bezpath].x2 = 0;
2352			bezpath[size_bezpath].y2 = 0;
2353			bezpath[size_bezpath].x3 = bs->x;
2354			bezpath[size_bezpath].y3 = bs->y;
2355			bs->size_bezpath++;
2356			bs->x0 = bs->x;
2357			bs->y0 = bs->y;
2358			bs->need_moveto = 0;
2359		}
2360}
2361
2362static void
2363bs_rlineto (BezState *bs, double dx, double dy)
2364{
2365	ArtBpath *bezpath;
2366	int size_bezpath;
2367
2368	bs_do_moveto (bs);
2369
2370	bezpath = bs->bezpath;
2371	size_bezpath = bs->size_bezpath;
2372
2373	if (size_bezpath == 

Large files files are truncated, but you can click here to view the full file