; $Id: resolve_all.pro,v 1.15 2001/01/15 22:28:11 scottm Exp $ ; ; Copyright (c) 1995-2001, Research Systems, Inc. All rights reserved. ; Unauthorized reproduction prohibited. ;+ ; NAME: ; RESOLVE_ALL ; ; PURPOSE: ; Resolve (by compiling) all procedures and functions. ; This is useful when preparing .sav files containing all the IDL ; routines required for an application. ; CATEGORY: ; Programming. ; CALLING SEQUENCE: ; RESOLVE_ALL ; INPUTS: ; None. ; KEYWORD PARAMETERS: ; CONTINUE_ON_ERROR = if set, continue when a routine fails to ; resolve, otherwise throw an error and stop. ; RESOLVE_EITHER = A scalar or array of routine names to resolve. ; Use this keyword instead of RESOLVE_FUNCTION or RESOLVE_PROCEDURE ; if you do not know the type of the routine being resolved. ; If the routines are already compiled, they are not recompiled. ; QUIET = if set, produce no messages. ; RESOLVE_FUNCTION = a scalar or array of function names to resolve. ; If the routines are already compiled, they are not recompiled. ; RESOLVE_PROCEDURE = a scalar or array of procedure names to resolve. ; If the routines are already compiled, they are not recompiled. ; SKIP_ROUTINES = an optional string array containing the names ; of routines to NOT resolve. This is useful when a library ; file containing the designated routines will be later included. ; UNRESOLVED = if CONTINUE_ON_ERROR is set, this output parameter will ; contain the names of the unresolved procedures and functions ; in a string array. Routines in the SKIP_ROUTINES list are ; also included in this result. ; OUTPUTS: ; No explicit outputs. ; COMMON BLOCKS: ; None. ; SIDE EFFECTS: ; RESTRICTIONS: ; Will not resolve procedures or functions that are called via ; CALL_PROCEDURE, CALL_FUNCTION, or EXECUTE, or object methods. ; Only explicit calls are resolved. ; ; If an unresolved procedure or function is not in the IDL ; search path, an error occurs, and no additional routines ; are resolved unless CONTINUE_ON_ERROR is specified. ; ; This routine does not support the idea of a function and procedure ; both having the same name, and does not handle that case. This is ; generally not a good idea anyway, as it is confusing. ; ; PROCEDURE: ; This routine iteratively determines the names of unresolved calls ; to user-written or library procedures and functions, and then ; compiles them. The process stops when there are no unresolved ; routines. ; EXAMPLE: ; RESOLVE_ALL. ; MODIFICATION HISTORY: ; Written by: ; DMS, RSI, January, 1995. ; DMS, RSI, April, 1997, Added SKIP_ROUTINES keyword. ; AB, RSI, April 1998, Added CONTINUE_ON_ERROR keyword. Reorganized ; the body of the resolving code. ; DMS, Aug, 1998. Added UNRESOLVED keyword. ; AB, 13 January 1999, Added RESOLVE_EITHER keyword. Removed the old ; restriction that only one of the RESOLVE_ keywords are ; processed in a single call. ;- function resolve_all_body, quiet, cont, do_func, skipr ; ; Resolve all unresolved procedures or functions if possible. ; ; entry: ; quiet - Quiet keyword from main routine. ; cont - TRUE if should keep going when a routine fails to resolve, ; FALSE to throw an error and stop. ; do_func - TRUE to process functions, FALSE to process procedures. ; skipr - Uppercase names of routines to skip resolving. This argument ; can be undefined, scalar, or array. ; ; exit: ; All routines of the specified type have been resolved if possible. ; Returns the number of routines for which an attempt to resolve was ; made. ; ; If cont is TRUE, any routines that fail to resolve are concatenated ; to skipr so that subsequent calls won't try again. COMPILE_OPT hidden on_error, 2 ; Return to caller if error not caught n_unresolved = 0 num_skipr = n_elements(skipr) a = ROUTINE_INFO(FUNCTIONS=do_func, /UNRESOLVED) if num_skipr gt 0 then begin ; Remove skip routines from the unresolved list. j = 0L for i=0, n_elements(a)-1 do if total(a[i] eq skipr) eq 0 then begin a[j] = a[i] j = j + 1 endif if j gt 0 then a = a[0:j-1] else a = '' endif if strlen(a[0]) gt 0 then begin num = n_elements(a) n_unresolved = n_unresolved + num for i=0, num-1 do begin name = a[i] if (cont) then catch, error else error = 0 if error eq 0 then begin resolve_routine, name, IS_FUNCTION=do_func endif else begin ; Current routine was not found. Let the user see the ; error, and then add it to the skip list. if quiet eq 0 then help,/last_message skipr = num_skipr gt 0 ? [skipr, name] : [name]; num_skipr = num_skipr + 1 endelse endfor endif return, n_unresolved end PRO resolve_all, QUIET = quiet, SKIP_ROUTINES = skip_routines, $ RESOLVE_EITHER=resolve_either, $ RESOLVE_PROCEDURE=resolve_procedure, $ RESOLVE_FUNCTION=resolve_function, CONTINUE_ON_ERROR=cont, $ UNRESOLVED=skipr on_error, 2 ; Return to caller if error not caught if n_elements(quiet) ne 0 then begin quiet_save=!quiet !quiet = quiet endif else quiet = 0 local_cont = keyword_set(cont) if keyword_set(resolve_either) then $ resolve_routine, /NO_RECOMPILE, /EITHER, resolve_either if keyword_set(resolve_procedure) then $ resolve_routine, /NO_RECOMPILE, resolve_procedure if keyword_set(resolve_function) then $ resolve_routine, /NO_RECOMPILE, /IS_FUNCTION, resolve_procedure if n_elements(skip_routines) gt 0 then skipr = strupcase(skip_routines) repeat begin cnt = 0 cnt = cnt + resolve_all_body(quiet, local_cont, 0, skipr) cnt = cnt + resolve_all_body(quiet, local_cont, 1, skipr) endrep until cnt le 0 done: if n_elements(quiet_save) ne 0 then !quiet = quiet_save end