1 /* Basic ops on symbols.
2  */
3 
4 /*
5 
6     Copyright (C) 1991-2003 The National Gallery
7 
8     This program is free software; you can redistribute it and/or modify
9     it under the terms of the GNU General Public License as published by
10     the Free Software Foundation; either version 2 of the License, or
11     (at your option) any later version.
12 
13     This program is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16     GNU General Public License for more details.
17 
18     You should have received a copy of the GNU General Public License along
19     with this program; if not, write to the Free Software Foundation, Inc.,
20     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21 
22  */
23 
24 /*
25 
26     These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
27 
28  */
29 
30 #include "ip.h"
31 
32 /* All debug
33 #define DEBUG
34  */
35 
36 /* Just trace create/destroy.
37 #define DEBUG_MAKE
38  */
39 
40 /* Time recomputes.
41 #define DEBUG_TIME
42  */
43 
44 /* Show symbols as we recalc
45 #define DEBUG_RECALC
46  */
47 
48 /* If DEBUG is on, make sure other debugs are on too.
49  */
50 #ifdef DEBUG
51 # ifndef DEBUG_MAKE
52 #  define DEBUG_MAKE
53 # endif
54 # ifndef DEBUG_TIME
55 #  define DEBUG_TIME
56 # endif
57 # ifndef DEBUG_RECALC
58 #  define DEBUG_RECALC
59 # endif
60 #endif
61 
62 /* Our signals.
63  */
64 enum {
65 	SIG_NEW_VALUE,		/* new value for sym->expr */
66 	SIG_LAST
67 };
68 
69 static guint symbol_signals[SIG_LAST] = { 0 };
70 
71 /* Global symbol - top-level definitions are locals to this symbol.
72  */
73 Symbol *symbol_root = NULL;
74 
75 /* Set of dirty top-level symbols with no dirty children which do not contain
76  * errors. Used to generate next-to-recalc.
77  */
78 static GSList *symbol_leaf_set = NULL;
79 
80 static FilemodelClass *parent_class = NULL;
81 
82 /* Apply a function to a symbol ... and any locals.
83  */
84 Symbol *
symbol_map_all(Symbol * sym,symbol_map_fn fn,void * a,void * b)85 symbol_map_all( Symbol *sym, symbol_map_fn fn, void *a, void *b )
86 {
87 	Symbol *res;
88 
89 	/* Apply to this sym.
90 	 */
91 	if( (res = fn( sym, a, b, NULL )) )
92 		return( res );
93 
94 	/* And over any locals of those locals.
95 	 */
96 	if( sym->expr && sym->expr->compile &&
97 		(res = icontainer_map3( ICONTAINER( sym->expr->compile ),
98 			(icontainer_map3_fn) symbol_map_all,
99 			(void *) fn, a, b )) )
100 		return( res );
101 
102 	return( NULL );
103 }
104 
105 /* Find a symbol's enclosing sym.
106  */
107 Symbol *
symbol_get_parent(Symbol * sym)108 symbol_get_parent( Symbol *sym )
109 {
110 	if( !ICONTAINER( sym )->parent )
111 		return( NULL );
112 
113 	return( COMPILE( ICONTAINER( sym )->parent )->sym );
114 }
115 
116 /* Find the enclosing workspace, if any.
117  */
118 Workspace *
symbol_get_workspace(Symbol * sym)119 symbol_get_workspace( Symbol *sym )
120 {
121 	if( !sym->expr || !sym->expr->row )
122 		return( NULL );
123 
124 	return( row_get_workspace( sym->expr->row ) );
125 }
126 
127 /* Find the enclosing tool, if any.
128  */
129 Tool *
symbol_get_tool(Symbol * sym)130 symbol_get_tool( Symbol *sym )
131 {
132 	Symbol *i;
133 
134 	for( i = sym; i && !i->tool; i = symbol_get_parent( i ) )
135 		;
136 	if( i )
137 		return( i->tool );
138 
139 	return( NULL );
140 }
141 
142 /* Get the enclosing scope for a sym.
143  */
144 Symbol *
symbol_get_scope(Symbol * sym)145 symbol_get_scope( Symbol *sym )
146 {
147 	Symbol *i;
148 
149 	for( i = sym; i && !is_scope( i ); i = symbol_get_parent( i ) )
150 		;
151 
152 	return( i );
153 }
154 
155 /* Make a fully-qualified symbol name .. eg fred.jim, given jim. Don't print
156  * static scopes.
157  */
158 void
symbol_qualified_name(Symbol * sym,VipsBuf * buf)159 symbol_qualified_name( Symbol *sym, VipsBuf *buf )
160 {
161 	Symbol *parent = symbol_get_parent( sym );
162 
163 	if( parent && !is_scope( parent ) ) {
164 		symbol_qualified_name( parent, buf );
165 		vips_buf_appends( buf, "." );
166 	}
167 
168 	vips_buf_appends( buf, NN( IOBJECT( sym )->name ) );
169 }
170 
171 /* Make a symbol name relative to a scope context ... ie. from the point of
172  * view of a local of context, what name will find sym.
173  */
174 void
symbol_qualified_name_relative(Symbol * context,Symbol * sym,VipsBuf * buf)175 symbol_qualified_name_relative( Symbol *context, Symbol *sym, VipsBuf *buf )
176 {
177 	Symbol *parent = symbol_get_parent( sym );
178 
179 	if( parent && !is_ancestor( context, parent ) ) {
180 		symbol_qualified_name_relative( context, parent, buf );
181 		vips_buf_appends( buf, "." );
182 	}
183 
184 	vips_buf_appends( buf, NN( IOBJECT( sym )->name ) );
185 }
186 
187 /* As above, but include stuff about where the symbol is defined, handy for
188  * building error messages.
189  */
190 void *
symbol_name_error(Symbol * sym,VipsBuf * buf)191 symbol_name_error( Symbol *sym, VipsBuf *buf )
192 {
193 	Tool *tool;
194 
195 	symbol_qualified_name( sym, buf );
196 	if( (tool = symbol_get_tool( sym )) )
197 		tool_error( tool, buf );
198 
199 	vips_buf_appends( buf, " " );
200 
201 	return( NULL );
202 }
203 
204 /* Handy for error messages ... but nowt else. Return string overwritten on
205  * next call.
206  */
207 const char *
symbol_name(Symbol * sym)208 symbol_name( Symbol *sym )
209 {
210 	static char txt[200];
211 	static VipsBuf buf = VIPS_BUF_STATIC( txt );
212 
213 	vips_buf_rewind( &buf );
214 	symbol_qualified_name( sym, &buf );
215 
216 	return( vips_buf_all( &buf ) );
217 }
218 
219 /* Convenience ... print a qual name to stdout.
220  */
221 void *
symbol_name_print(Symbol * sym)222 symbol_name_print( Symbol *sym )
223 {
224 	printf( "%s ", symbol_name( sym ) );
225 
226 	return( NULL );
227 }
228 
229 /* Print a symbol's name, including the enclosing static scope. Return value
230  * is a pointer to a static buffer :(
231  */
232 const char *
symbol_name_scope(Symbol * sym)233 symbol_name_scope( Symbol *sym )
234 {
235 	Symbol *scope = symbol_get_scope( sym );
236 
237 	static char txt[200];
238 	static VipsBuf buf = VIPS_BUF_STATIC( txt );
239 
240 	vips_buf_rewind( &buf );
241 	vips_buf_appends( &buf, NN( IOBJECT( scope )->name ) );
242 	vips_buf_appends( &buf, "." );
243 	symbol_qualified_name_relative( scope, sym, &buf );
244 
245 	return( vips_buf_all( &buf ) );
246 }
247 
248 /* Convenience ... print a qual name to stdout.
249  */
250 void
symbol_name_scope_print(Symbol * sym)251 symbol_name_scope_print( Symbol *sym )
252 {
253 	printf( "%s", symbol_name_scope( sym ) );
254 }
255 
256 void
symbol_new_value(Symbol * sym)257 symbol_new_value( Symbol *sym )
258 {
259 	g_signal_emit( G_OBJECT( sym ), symbol_signals[SIG_NEW_VALUE], 0 );
260 }
261 
262 /* Add a pointer to a patch list.
263  */
264 void *
symbol_patch_add(void ** pnt,Symbol * sym)265 symbol_patch_add( void **pnt, Symbol *sym )
266 {
267 	g_assert( sym->type == SYM_ZOMBIE );
268 
269 	sym->patch = g_slist_prepend( sym->patch, pnt );
270 
271 	return( NULL );
272 }
273 
274 static void
symbol_clear(Symbol * sym)275 symbol_clear( Symbol *sym )
276 {
277 	sym->type = SYM_ZOMBIE;
278 
279 	sym->patch = NULL;
280 
281 	sym->expr = NULL;
282 
283 	sym->base.type = ELEMENT_NOVAL;
284 	sym->base.ele = (void *) 15;	/* handy for debugging */
285 
286 	sym->dirty = FALSE;
287 	sym->parents = NULL;
288 
289 	sym->topchildren = NULL;
290 	sym->topparents = NULL;
291 	sym->ndirtychildren = 0;
292 	sym->leaf = FALSE;
293 
294 	sym->generated = FALSE;
295 	sym->placeholder = FALSE;
296 
297 	sym->tool = NULL;
298 
299 	sym->function = NULL;
300 
301 	sym->builtin = NULL;
302 
303 	sym->wsr = NULL;
304 
305 	sym->ws = NULL;
306 }
307 
308 /* Initialise root symbol.
309  */
310 Symbol *
symbol_root_init(void)311 symbol_root_init( void )
312 {
313 	Symbol *root = SYMBOL( g_object_new( TYPE_SYMBOL, NULL ) );
314 
315 	symbol_clear( root );
316 	iobject_set( IOBJECT( root ), "$$ROOT", NULL );
317 	root->type = SYM_ROOT;
318 	root->expr = expr_new( root );
319 	(void) compile_new_local( root->expr );
320 
321 	symbol_root = symbol_new( root->expr->compile, "root" );
322 	symbol_root->type = SYM_ROOT;
323 	symbol_root->expr = expr_new( symbol_root );
324 	(void) compile_new( symbol_root->expr );
325 
326 	return( root );
327 }
328 
329 /* Should a symbol be in the leaf set?
330  */
331 static gboolean
symbol_is_leafable(Symbol * sym)332 symbol_is_leafable( Symbol *sym )
333 {
334 	if( is_top( sym ) &&
335 		sym->dirty &&
336 		sym->expr &&
337 		!sym->expr->err &&
338 		sym->ndirtychildren == 0 )
339 		return( TRUE );
340 
341 	return( FALSE );
342 }
343 
344 #ifdef DEBUG
345 /* Do a sanity check on a symbol.
346  */
347 void *
symbol_sanity(Symbol * sym)348 symbol_sanity( Symbol *sym )
349 {
350 	if( is_top( sym ) ) {
351 		if( symbol_ndirty( sym ) != sym->ndirtychildren )
352 			error( "sanity failure #1 for sym \"%s\"",
353 				symbol_name( sym ) );
354 	}
355 
356 	if( symbol_is_leafable( sym ) && !sym->leaf )
357 		error( "sanity failure #2 for sym \"%s\"", symbol_name( sym ) );
358 	if( !symbol_is_leafable( sym ) && sym->leaf )
359 		error( "sanity failure #3 for sym \"%s\"", symbol_name( sym ) );
360 	if( sym->leaf && !g_slist_find( symbol_leaf_set, sym ) )
361 		error( "sanity failure #6 for sym \"%s\"", symbol_name( sym ) );
362 	if( !sym->leaf && g_slist_find( symbol_leaf_set, sym ) )
363 		error( "sanity failure #7 for sym \"%s\"", symbol_name( sym ) );
364 
365 	return( NULL );
366 }
367 #endif/*DEBUG*/
368 
369 #ifdef DEBUG
370 /* Test the leaf set for sanity.
371  */
372 void
symbol_leaf_set_sanity(void)373 symbol_leaf_set_sanity( void )
374 {
375 	slist_map( symbol_leaf_set, (SListMapFn) symbol_sanity, NULL );
376 	icontainer_map( ICONTAINER( symbol_root->expr->compile ),
377 		(icontainer_map_fn) symbol_sanity, NULL, NULL );
378 
379 	/* Commented out to reduce spam
380 	 *
381 	printf( "Leaf set: " );
382 	slist_map( symbol_leaf_set, (SListMapFn) dump_tiny, NULL );
383 	printf( "\n" );
384 	 */
385 }
386 #endif /*DEBUG*/
387 
388 /* Strip a symbol down, ready for redefinition.
389  */
390 void *
symbol_strip(Symbol * sym)391 symbol_strip( Symbol *sym )
392 {
393 #ifdef DEBUG_MAKE
394 	printf( "symbol_strip: " );
395 	symbol_name_print( sym );
396 	printf( "\n" );
397 #endif /*DEBUG_MAKE*/
398 
399 	/* Anything that refers to us will need a recomp.
400 	 */
401 	if( is_top( sym ) )
402 		symbol_dirty_intrans( sym, link_serial_new() );
403 
404 	/* Clean out old exprinfo.
405 	 */
406 	icontainer_map( ICONTAINER( sym ),
407 		(icontainer_map_fn) expr_strip, NULL, NULL );
408 
409 	/* Free any top-links we made.
410 	 */
411 	(void) slist_map( sym->topchildren, (SListMapFn) link_destroy, NULL );
412 
413 	/* Can free the patch list. We should not have to resolve off this
414 	 * name again.
415 	 */
416 	IM_FREEF( g_slist_free, sym->patch );
417 
418 	/* Workspaceroot? Unlink from wsr.
419 	 */
420 	if( sym->wsr ) {
421 		sym->wsr->sym = NULL;
422 		sym->wsr = NULL;
423 	}
424 
425 	/* Workspace? Unlink from ws.
426 	 */
427 	if( sym->ws ) {
428 		sym->ws->sym = NULL;
429 		sym->ws = NULL;
430 	}
431 
432 	/* It's a ZOMBIE now.
433 	 */
434 	sym->type = SYM_ZOMBIE;
435 
436 #ifdef DEBUG
437 	symbol_sanity( sym );
438 #endif /*DEBUG*/
439 
440 	return( NULL );
441 }
442 
443 static void *
symbol_made_error_clear(Link * link)444 symbol_made_error_clear( Link *link )
445 {
446 	expr_error_clear( link->parent->expr );
447 
448 	return( NULL );
449 }
450 
451 /* Finish creating a symbol. Sequence is: symbol_new(), specialise ZOMBIE
452  * into a particular symbol type, symbol_made(). Do any final tidying up.
453  */
454 void
symbol_made(Symbol * sym)455 symbol_made( Symbol *sym )
456 {
457 #ifdef DEBUG_MAKE
458 	printf( "symbol_made: " );
459 	symbol_name_print( sym );
460 	printf( "\n" );
461 #endif /*DEBUG_MAKE*/
462 
463 	if( is_top( sym ) ) {
464 		/* Remake all top-level dependencies.
465 		 */
466 		(void) symbol_link_build( sym );
467 
468 		/* Clear error on every symbol that refs us, then mark dirty.
469 		 * This lets us replace refed-to syms cleanly.
470 		 */
471 		slist_map( sym->topparents,
472 			(SListMapFn) symbol_made_error_clear, NULL );
473 
474 		/* Real dirrrrty.
475 		 */
476 		if( sym->expr )
477 			expr_dirty( sym->expr, link_serial_new() );
478 	}
479 
480 #ifdef DEBUG
481 	dump_symbol( sym );
482 #endif /*DEBUG*/
483 }
484 
485 static void *
symbol_not_defined_sub(Link * link,VipsBuf * buf)486 symbol_not_defined_sub( Link *link, VipsBuf *buf )
487 {
488 	symbol_name_error( link->parent, buf );
489 
490 	return( NULL );
491 }
492 
493 /* Make a "not defined" error message. Can be called before symbol is removed,
494  * so don't assume it's a ZOMBIE.
495  */
496 void
symbol_not_defined(Symbol * sym)497 symbol_not_defined( Symbol *sym )
498 {
499 	char txt[256];
500 	VipsBuf buf = VIPS_BUF_STATIC( txt );
501 
502 	error_top( _( "Not found." ) );
503 	vips_buf_appendf( &buf, _( "Symbol %s is not defined." ),
504 		symbol_name( sym ) );
505 	if( sym->topparents ) {
506 		vips_buf_appends( &buf, "\n" );
507 		vips_buf_appendf( &buf, _( "%s is referred to by" ),
508 			symbol_name( sym ) );
509 		vips_buf_appends( &buf, ": " );
510 		slist_map2( sym->topparents,
511 			(SListMap2Fn) symbol_not_defined_sub, &buf, NULL );
512 		vips_buf_appends( &buf, "\n" );
513 	}
514 	error_sub( "%s", vips_buf_all( &buf ) );
515 }
516 
517 /* Compile refers to sym, which is going ... mark compile as containing an
518  * error.
519  */
520 static void *
symbol_destroy_error(Compile * compile,Symbol * sym)521 symbol_destroy_error( Compile *compile, Symbol *sym )
522 {
523 	symbol_not_defined( sym );
524 	compile_error_set( compile );
525 
526 	return( NULL );
527 }
528 
529 static void
symbol_dispose(GObject * gobject)530 symbol_dispose( GObject *gobject )
531 {
532 	Symbol *sym;
533 	Compile *compile;
534 
535 	g_return_if_fail( gobject != NULL );
536 	g_return_if_fail( IS_SYMBOL( gobject ) );
537 
538 	sym = SYMBOL( gobject );
539 	compile = COMPILE( ICONTAINER( sym )->parent );
540 
541 #ifdef DEBUG_MAKE
542 	printf( "symbol_dispose: " );
543 	symbol_name_print( sym );
544 	printf( "(%p)\n", sym );
545 #endif /*DEBUG_MAKE*/
546 
547 	/* Make sure we're not leaving last_sym dangling.
548 	 */
549 	if( compile && compile->last_sym == sym )
550 		compile->last_sym = NULL;
551 
552 	/* Clear state.
553 	 */
554 	if( is_top( sym ) ) {
555 		/* All stuff that depends on this sym is now dirty.
556 		 */
557 		symbol_dirty_intrans( sym, link_serial_new() );
558 
559 		/* This will knock this sym off the leaf set as well.
560 		 */
561 		symbol_dirty_clear( sym );
562 	}
563 
564 	/* Strip it down.
565 	 */
566 	(void) symbol_strip( sym );
567 	IDESTROY( sym->tool );
568 
569 	/* Any exprs which refer to us must have errors.
570 	 */
571 	(void) slist_map( sym->parents,
572 		(SListMapFn) symbol_destroy_error, sym );
573 
574 	/* Remove links from any expr which refer to us.
575 	 */
576 	(void) slist_map( sym->parents, (SListMapFn) compile_link_break, sym );
577 
578 	/* No other syms should have toplinks to us.
579 	 */
580 	(void) slist_map( sym->topparents, (SListMapFn) link_destroy, NULL );
581 
582 	/* Unregister value with GC.
583 	 */
584 	reduce_unregister( sym );
585 
586 	/* Free other stuff.
587 	 */
588 	sym->type = SYM_ZOMBIE;
589 
590 	g_assert( !sym->tool );
591 	g_assert( !sym->parents );
592 	g_assert( !sym->topparents );
593 	g_assert( !sym->topchildren );
594 
595 	IM_FREEF( g_slist_free, sym->patch );
596 	IM_FREEF( g_slist_free, sym->parents );
597 
598 	G_OBJECT_CLASS( parent_class )->dispose( gobject );
599 }
600 
601 static void
symbol_changed(iObject * iobject)602 symbol_changed( iObject *iobject )
603 {
604 	Symbol *sym = SYMBOL( iobject );
605 
606 	/* If we have a tool, signal changed on that as well.
607 	 */
608 	if( sym->tool )
609 		iobject_changed( IOBJECT( sym->tool ) );
610 
611 	IOBJECT_CLASS( parent_class )->changed( iobject );
612 }
613 
614 static void
symbol_real_new_value(Symbol * symbol)615 symbol_real_new_value( Symbol *symbol )
616 {
617 }
618 
619 static void
symbol_class_init(SymbolClass * class)620 symbol_class_init( SymbolClass *class )
621 {
622 	GObjectClass *gobject_class = G_OBJECT_CLASS( class );
623 	iObjectClass *iobject_class = (iObjectClass *) class;
624 
625 	parent_class = g_type_class_peek_parent( class );
626 
627 	gobject_class->dispose = symbol_dispose;
628 
629 	iobject_class->changed = symbol_changed;
630 
631 	symbol_signals[SIG_NEW_VALUE] = g_signal_new( "new_value",
632 		G_OBJECT_CLASS_TYPE( gobject_class ),
633 		G_SIGNAL_RUN_FIRST,
634 		G_STRUCT_OFFSET( SymbolClass, new_value ),
635 		NULL, NULL,
636 		g_cclosure_marshal_VOID__VOID,
637 		G_TYPE_NONE, 0 );
638 
639 	class->new_value = symbol_real_new_value;
640 }
641 
642 static void
symbol_init(Symbol * sym)643 symbol_init( Symbol *sym )
644 {
645 	symbol_clear( sym );
646 
647 #ifdef DEBUG_MAKE
648 	printf( "symbol_init: (%p)\n", sym );
649 #endif /*DEBUG_MAKE*/
650 }
651 
652 GtkType
symbol_get_type(void)653 symbol_get_type( void )
654 {
655 	static GtkType symbol_type = 0;
656 
657 	if( !symbol_type ) {
658 		static const GTypeInfo info = {
659 			sizeof( SymbolClass ),
660 			NULL,           /* base_init */
661 			NULL,           /* base_finalize */
662 			(GClassInitFunc) symbol_class_init,
663 			NULL,           /* class_finalize */
664 			NULL,           /* class_data */
665 			sizeof( Symbol ),
666 			32,             /* n_preallocs */
667 			(GInstanceInitFunc) symbol_init,
668 		};
669 
670 		symbol_type = g_type_register_static( TYPE_FILEMODEL,
671 			"Symbol", &info, 0 );
672 	}
673 
674 	return( symbol_type );
675 }
676 
677 /* Make a new symbol on an expr. If it's already there and a ZOMBIE, just
678  * return it. If it's not a ZOMBIE, turn it into one. Otherwise make and
679  * link on a new symbol.
680  */
681 Symbol *
symbol_new(Compile * compile,const char * name)682 symbol_new( Compile *compile, const char *name )
683 {
684 	Symbol *sym;
685 
686 	if( (sym = compile_lookup( compile, name )) ) {
687 		if( sym->type != SYM_ZOMBIE )
688 			/* Already exists: strip it down.
689 			 */
690 			(void) symbol_strip( sym );
691 
692 #ifdef DEBUG_MAKE
693 		printf( "symbol_new: redefining " );
694 		symbol_name_print( sym );
695 		printf( "(%p)\n", sym );
696 #endif /*DEBUG_MAKE*/
697 	}
698 	else {
699 		sym = SYMBOL( g_object_new( TYPE_SYMBOL, NULL ) );
700 		iobject_set( IOBJECT( sym ), name, NULL );
701 		icontainer_child_add( ICONTAINER( compile ),
702 			ICONTAINER( sym ), -1 );
703 
704 #ifdef DEBUG_MAKE
705 		printf( "symbol_new: creating " );
706 		symbol_name_print( sym );
707 		printf( "(%p)\n", sym );
708 #endif /*DEBUG_MAKE*/
709 	}
710 
711 	return( sym );
712 }
713 
714 gboolean
symbol_rename(Symbol * sym,const char * new_name)715 symbol_rename( Symbol *sym, const char *new_name )
716 {
717 	Compile *compile = COMPILE( ICONTAINER( sym )->parent );
718 	Symbol *old_sym;
719 
720 	if( strcmp( IOBJECT( sym )->name, new_name ) == 0 )
721 		return( TRUE );
722 
723 	if( (old_sym = compile_lookup( compile, new_name )) ) {
724 		error_top( "%s", _( "Name in use." ) );
725 		error_sub( _( "Can't rename %s \"%s\" as \"%s\". "
726 			"The name is already in use." ),
727 			decode_SymbolType_user( sym->type ),
728 			IOBJECT( sym )->name,
729 			new_name );
730 		return( FALSE );
731 	}
732 
733 	/* Everything that depends on us will break.
734 	 */
735 	symbol_dirty_intrans( sym, link_serial_new() );
736 
737 	g_object_ref( sym );
738 
739 	icontainer_child_remove( ICONTAINER( sym ) );
740 	iobject_set( IOBJECT( sym ), new_name, NULL );
741 	icontainer_child_add( ICONTAINER( compile ), ICONTAINER( sym ),
742 		ICONTAINER( sym )->pos );
743 
744 	g_object_unref( sym );
745 
746 	return( TRUE );
747 }
748 
749 void
symbol_error_redefine(Symbol * sym)750 symbol_error_redefine( Symbol *sym )
751 {
752 	static char txt[200];
753 	static VipsBuf buf = VIPS_BUF_STATIC( txt );
754 
755 	vips_buf_rewind( &buf );
756 	vips_buf_appendf( &buf, _( "Redefinition of \"%s\"." ),
757 		IOBJECT( sym )->name );
758 	if( sym->tool && sym->tool->lineno != -1 ) {
759 		vips_buf_appendf( &buf, "\n" );
760 		vips_buf_appendf( &buf, _( "Previously defined at line %d." ),
761 			sym->tool->lineno );
762 	}
763 
764 	yyerror( vips_buf_all( &buf ) );
765 }
766 
767 /* Name in defining occurence. If this is a top-level definition, clean the
768  * old symbol and get ready to attach a user function to it. If its not a top-
769  * level definition, we flag an error. Consider repeated parameter names,
770  * repeated occurence of names in locals, local name clashes with parameter
771  * name etc.
772  * We make a ZOMBIE: our caller should turn it into a blank user definition, a
773  * parameter etc.
774  */
775 Symbol *
symbol_new_defining(Compile * compile,const char * name)776 symbol_new_defining( Compile *compile, const char *name )
777 {
778 	Symbol *sym;
779 
780 	/* Block definition of "root" anywhere ... too confusing.
781 	 */
782 	if( strcmp( name, IOBJECT( symbol_root )->name ) == 0 )
783 		nip2yyerror( _( "Attempt to redefine root symbol \"%s\"." ),
784 			name );
785 
786 	/* Is this a redefinition of an existing symbol?
787 	 */
788 	if( (sym = compile_lookup( compile, name )) ) {
789 		/* Yes. Check that this redefinition is legal.
790 		 */
791 		switch( sym->type ) {
792 		case SYM_VALUE:
793 			/* Redef of existing symbol? Only allowed at top
794 			 * level.
795 			 */
796 			if( !is_scope( compile->sym ) )
797 				symbol_error_redefine( sym );
798 			break;
799 
800 		case SYM_ZOMBIE:
801 			/* This is the definition for a previously referenced
802 			 * symbol. Just return the ZOMBIE we made.
803 			 */
804 			break;
805 
806 		default:
807 			/* Parameter, workspace, etc.
808 			 */
809 			nip2yyerror( _( "Can't redefine %s \"%s\"." ),
810 				decode_SymbolType_user( sym->type ), name );
811 			/*NOTREACHED*/
812 		}
813 
814 		/* This is the defining occurence ... move to the end of the
815 		 * traverse order.
816 		 */
817 		icontainer_child_move( ICONTAINER( sym ), -1 );
818 	}
819 
820 	/* Get it ready.
821 	 */
822 	sym = symbol_new( compile, name );
823 
824 	return( sym );
825 }
826 
827 /* Make a reference to a symbol. Look on the local table for the name - if
828  * it's not there, make a ZOMBIE. Note that ZOMBIEs etc. need patch lists
829  * attached to them for all pointers to them we make. Responsibility of
830  * caller!
831  */
832 Symbol *
symbol_new_reference(Compile * compile,const char * name)833 symbol_new_reference( Compile *compile, const char *name )
834 {
835 	Symbol *sym = compile_lookup( compile, name );
836 
837 	if( !sym )
838 		sym = symbol_new( compile, name );
839 
840 	/* Note the new dependency.
841 	 */
842 	compile_link_make( compile, sym );
843 
844 	return( sym );
845 }
846 
847 /* Compile refers to child ... break link.
848  */
849 void *
symbol_link_break(Symbol * child,Compile * compile)850 symbol_link_break( Symbol *child, Compile *compile )
851 {
852 	compile_link_break( compile, child );
853 
854 	return( NULL );
855 }
856 
857 /* Specialise into a user definition.
858  */
859 gboolean
symbol_user_init(Symbol * sym)860 symbol_user_init( Symbol *sym )
861 {
862 	g_assert( sym->type == SYM_ZOMBIE );
863 
864 	sym->type = SYM_VALUE;
865 	reduce_register( sym );
866 	if( !sym->expr )
867 		sym->expr = expr_new( sym );
868 
869 	/* We don't symbol_made() yet, wait until we have finished building
870 	 * sym->expr.
871 	 */
872 
873 	return( TRUE );
874 }
875 
876 /* Specialise into a parameter on an expression.
877  */
878 gboolean
symbol_parameter_init(Symbol * sym)879 symbol_parameter_init( Symbol *sym )
880 {
881 	Compile *parent = COMPILE( ICONTAINER( sym )->parent );
882 
883 	g_assert( sym->type == SYM_ZOMBIE );
884 
885 	sym->type = SYM_PARAM;
886 	parent->param = g_slist_append( parent->param, sym );
887 	parent->nparam = g_slist_length( parent->param );
888 	symbol_made( sym );
889 
890 	return( TRUE );
891 }
892 
893 /* Specialise into a builtin parameter (eg. "this").
894  */
895 gboolean
symbol_parameter_builtin_init(Symbol * sym)896 symbol_parameter_builtin_init( Symbol *sym )
897 {
898 	g_assert( sym->type == SYM_ZOMBIE );
899 
900 	sym->type = SYM_PARAM;
901 	symbol_made( sym );
902 
903 	return( TRUE );
904 }
905 
906 /* Get the next dirty leaf symbol.
907  */
908 static Symbol *
symbol_leaf_next(void)909 symbol_leaf_next( void )
910 {
911 	if( symbol_leaf_set )
912 		return( (Symbol *) symbol_leaf_set->data );
913 	else
914 		return( NULL );
915 }
916 
917 /* Are there symbols we can recalculate? Used to display "Calculating ..."
918  * status.
919  */
920 gboolean
symbol_busy(void)921 symbol_busy( void )
922 {
923 	return( symbol_leaf_set != NULL );
924 }
925 
926 /* Set leaf state.
927  */
928 static void
symbol_set_leaf(Symbol * sym,gboolean leaf)929 symbol_set_leaf( Symbol *sym, gboolean leaf )
930 {
931 	if( sym->leaf != leaf ) {
932 		gboolean changed;
933 
934 		sym->leaf = leaf;
935 
936 		changed = FALSE;
937 		if( leaf ) {
938 			if( !symbol_leaf_set )
939 				changed = TRUE;
940 
941 			symbol_leaf_set =
942 				g_slist_prepend( symbol_leaf_set, sym );
943 		}
944 		else {
945 			g_assert( symbol_leaf_set );
946 
947 			symbol_leaf_set =
948 				g_slist_remove( symbol_leaf_set, sym );
949 
950 			if( !symbol_leaf_set )
951 				changed = TRUE;
952 		}
953 
954 		if( changed )
955 			iobject_changed( IOBJECT( reduce_context->heap ) );
956 
957 		if( sym->expr && sym->expr->row )
958 			iobject_changed( IOBJECT( sym->expr->row ) );
959 	}
960 }
961 
962 /* State of a symbol has changed ... update!
963  */
964 void
symbol_state_change(Symbol * sym)965 symbol_state_change( Symbol *sym )
966 {
967 	g_assert( sym->ndirtychildren >= 0 );
968 
969 	/* Used to do more ... now we just set leaf.
970 	 */
971 	symbol_set_leaf( sym, symbol_is_leafable( sym ) );
972 }
973 
974 /* Recalculate a symbol. We know we are dirty and have no dirty ancestors.
975  */
976 static gboolean
symbol_recalculate_sub(Symbol * sym)977 symbol_recalculate_sub( Symbol *sym )
978 {
979 	gboolean result = TRUE;
980 
981 #ifdef DEBUG_TIME
982 	static GTimer *timer = NULL;
983 
984 	if( !timer )
985 		timer = g_timer_new();
986 	g_timer_reset( timer );
987 #endif /*DEBUG_TIME*/
988 
989 	g_assert( is_value( sym ) );
990 
991 	if( sym->expr->row ) {
992 		/* This is the root of a display ... use that recomp
993 		 * mechanism.
994 		 */
995 		row_recomp( sym->expr->row );
996 
997 		/* Stuff may have been removed.
998 		 */
999 		if( sym->expr &&
1000 			sym->expr->row &&
1001 			sym->expr->row->err )
1002 			result = FALSE;
1003 	}
1004 	else if( sym->expr->compile->nparam == 0 ) {
1005 		/* No params: this ought to have a value.
1006 		 */
1007 		if( !reduce_regenerate( sym->expr, &sym->expr->root ) )
1008 			result = FALSE;
1009 	}
1010 
1011 #ifdef DEBUG_TIME
1012 	printf( "symbol_recalculate_sub: " );
1013 	symbol_name_scope_print( sym );
1014 	printf( " %g\n", g_timer_elapsed( timer, NULL ) );
1015 #endif /*DEBUG_TIME*/
1016 
1017 	return( result );
1018 }
1019 
1020 /* Note the name of the last thing we calced here, for progress to display.
1021  */
1022 static char symbol_last_calc_txt[256];
1023 static VipsBuf symbol_last_calc_buf = VIPS_BUF_STATIC( symbol_last_calc_txt );
1024 
1025 static void
symbol_note_calc_name(Symbol * sym)1026 symbol_note_calc_name( Symbol *sym )
1027 {
1028 	Symbol *scope = symbol_get_scope( sym );
1029 	VipsBuf *buf = &symbol_last_calc_buf;
1030 
1031 	vips_buf_rewind( buf );
1032 	vips_buf_appends( buf, NN( IOBJECT( scope )->name ) );
1033 	vips_buf_appends( buf, "." );
1034 	symbol_qualified_name_relative( scope, sym, buf );
1035 }
1036 
1037 const char *
symbol_get_last_calc(void)1038 symbol_get_last_calc( void )
1039 {
1040 	return( vips_buf_all( &symbol_last_calc_buf ) );
1041 }
1042 
1043 /* We can get called recursively .. eg. we do an im_tiff2vips(), that
1044  * pops a progress box, that triggers idle, that tries to recalc a
1045  * leaf again.
1046  */
1047 static gboolean symbol_running = FALSE;
1048 
1049 /* Recalc a symbol ... with error checks.
1050  */
1051 static void *
symbol_recalculate_leaf_sub(Symbol * sym)1052 symbol_recalculate_leaf_sub( Symbol *sym )
1053 {
1054 #ifdef DEBUG_RECALC
1055 	printf( "symbol_recalculate_leaf_sub: %s\n", symbol_name_scope( sym ) );
1056 
1057 	/* We can symbol_recalculate_leaf_sub() syms which are not dirty.
1058 	 */
1059 	g_assert( !sym->dirty || symbol_is_leafable( sym ) );
1060 
1061 	g_assert( symbol_ndirty( sym ) == 0 );
1062 #endif /*DEBUG_RECALC*/
1063 
1064 	error_clear();
1065 	if( sym->expr->err ) {
1066 		expr_error_get( sym->expr );
1067 
1068 #ifdef DEBUG_RECALC
1069 		printf( "\t(error: previous error)\n" );
1070 #endif /*DEBUG_RECALC*/
1071 
1072 		return( sym );
1073 	}
1074 	if( !sym->dirty )
1075 		return( NULL );
1076 	if( !is_value( sym ) ) {
1077 		symbol_dirty_clear( sym );
1078 		return( NULL );
1079 	}
1080 	if( symbol_running )
1081 		return( NULL );
1082 
1083 	reduce_context->heap->filled = FALSE;
1084 	symbol_running = TRUE;
1085 	progress_begin();
1086 	symbol_note_calc_name( sym );
1087 	if( !symbol_recalculate_sub( sym ) ||
1088 		reduce_context->heap->filled ) {
1089 		expr_error_set( sym->expr );
1090 		symbol_running = FALSE;
1091 		progress_end();
1092 
1093 #ifdef DEBUG_RECALC
1094 		printf( "\t(error: %s %s)\n",
1095 			sym->expr->error_top, sym->expr->error_sub );
1096 #endif /*DEBUG_RECALC*/
1097 
1098 		return( sym );
1099 	}
1100 	symbol_running = FALSE;
1101 	progress_end();
1102 
1103 	/* Have we discovered any dirty children? If not, we've cleaned this
1104 	 * sym.
1105 	 */
1106 	if( !sym->ndirtychildren ) {
1107 		symbol_dirty_clear( sym );
1108 		if( sym->expr ) {
1109 			expr_new_value( sym->expr );
1110 
1111 #ifdef DEBUG_RECALC
1112 			printf( "\tsuccess: " );
1113 			graph_pointer( &sym->expr->root );
1114 #endif /*DEBUG_RECALC*/
1115 		}
1116 	}
1117 #ifdef DEBUG_RECALC
1118 	else {
1119 		printf( "\t(found dirty children)\n" );
1120 	}
1121 #endif /*DEBUG_RECALC*/
1122 
1123 	return( NULL );
1124 }
1125 
1126 /* Recalculate a symbol. FALSE if no symbols can be recalced.
1127  */
1128 static gboolean
symbol_recalculate_leaf(void)1129 symbol_recalculate_leaf( void )
1130 {
1131 	gboolean recalculated;
1132 	Symbol *sym;
1133 
1134 	recalculated = FALSE;
1135 
1136 #ifdef DEBUG
1137 	printf( "symbol_recalculate_leaves: Leaf set: " );
1138 	slist_map( symbol_leaf_set, (SListMapFn) dump_tiny, NULL );
1139 	printf( "\n" );
1140 #endif /*DEBUG*/
1141 
1142 	/* Grab stuff off the leaf set.
1143 	 */
1144 	if( (sym = symbol_leaf_next()) ) {
1145 		/* Should be dirty with no dirty children. Unless it's a
1146 		 * function, in which case dirty kids are OK.
1147 		 */
1148 		g_assert( sym->dirty );
1149 		g_assert( !sym->expr->err );
1150 		g_assert( is_top( sym ) );
1151 		g_assert( symbol_ndirty( sym ) == 0 || is_value( sym ) );
1152 
1153 		/* Found a symbol!
1154 		 */
1155 		(void) symbol_recalculate_leaf_sub( sym );
1156 
1157 		/* Note a pending GC.
1158 		 */
1159 		(void) heap_gc_request( reduce_context->heap );
1160 
1161 		/* We have recalculated a symbol.
1162 		 */
1163 		recalculated = TRUE;
1164 	}
1165 
1166 	return( recalculated );
1167 }
1168 
1169 /* Our idle recomp callback.
1170  */
1171 static gint symbol_idle_id = 0;
1172 
1173 static gboolean
symbol_recalculate_idle_cb(void)1174 symbol_recalculate_idle_cb( void )
1175 {
1176 	static GTimer *timer = NULL;
1177 
1178 	gboolean run_again;
1179 
1180 #ifdef DEBUG_RECALC
1181 	printf( "symbol_recalculate_idle_cb:\n" );
1182 #endif /*DEBUG_RECALC*/
1183 
1184 	if( symbol_running )
1185 		/* We've been run from a nested main loop, perhaps from the
1186 		 * progress bar. Just run again and perhaps next time we'll be
1187 		 * back in the top-level main loop.
1188 		 */
1189 		return( TRUE );
1190 
1191 	if( !timer )
1192 		timer = g_timer_new();
1193 
1194 	g_timer_reset( timer );
1195 
1196 	run_again = TRUE;
1197 
1198 	if( !mainw_auto_recalc )
1199 		/* Auto-calc has been turned off during a recomp.
1200 		 */
1201 		run_again = FALSE;
1202 	else
1203 		while( g_timer_elapsed( timer, NULL ) < 0.1 )
1204 			if( !symbol_recalculate_leaf() ) {
1205 				run_again = FALSE;
1206 				break;
1207 			}
1208 
1209 	if( !run_again ) {
1210 #ifdef DEBUG_RECALC
1211 		printf( "symbol_recalculate_idle_cb: bg recalc done\n" );
1212 #endif /*DEBUG_RECALC*/
1213 
1214 		symbol_idle_id = 0;
1215 		progress_end();
1216 	}
1217 
1218 	return( run_again );
1219 }
1220 
1221 /* Recalculate ... either nudge the idle recomp, or in batch mode, do a recomp
1222  * right now.
1223  */
1224 void
symbol_recalculate_all_force(gboolean now)1225 symbol_recalculate_all_force( gboolean now )
1226 {
1227 #ifdef DEBUG
1228 	icontainer_map( ICONTAINER( symbol_root->expr->compile ),
1229 		(icontainer_map_fn) symbol_sanity, NULL, NULL );
1230 #endif /*DEBUG*/
1231 
1232 	/* In case we're called directly.
1233 	 */
1234 	(void) view_scan_all();
1235 
1236 	if( symbol_running )
1237 		/* Do nothing.
1238 		 */
1239 		;
1240 	else if( main_option_batch ||
1241 		now ) {
1242 		progress_begin();
1243 
1244 		while( symbol_recalculate_leaf() )
1245 			;
1246 
1247 		progress_end();
1248 	}
1249 	else if( !symbol_idle_id ) {
1250 #ifdef DEBUG_RECALC
1251 		printf( "symbol_recalculate_all_force: "
1252 			"starting bg recalc ...\n" );
1253 #endif /*DEBUG_RECALC*/
1254 
1255 		progress_begin();
1256 		symbol_idle_id = g_idle_add(
1257 			(GSourceFunc) symbol_recalculate_idle_cb, NULL );
1258 	}
1259 }
1260 
1261 /* Recalculate the symbol table.
1262  */
1263 void
symbol_recalculate_all(void)1264 symbol_recalculate_all( void )
1265 {
1266 	/* Do a scan, even if we don't recomp. We need to pick up edits before
1267 	 * views get refreshed.
1268 	 */
1269 	(void) view_scan_all();
1270 
1271 	if( mainw_auto_recalc )
1272 		symbol_recalculate_all_force( FALSE );
1273 }
1274 
1275 /* Recalc a symbol ... with error checks.
1276  */
1277 gboolean
symbol_recalculate_check(Symbol * sym)1278 symbol_recalculate_check( Symbol *sym )
1279 {
1280 	gboolean result;
1281 
1282 	result = symbol_recalculate_leaf_sub( sym ) == NULL;
1283 
1284 	return( result );
1285 }
1286