;+ ; NAME: ; www_help_files ; PURPOSE: ; Extract headers from source code files. Locations of source code can ; be specified as regular files or directories, or (vms only) as text libraries. ; CATEGORY: ; www_help ; CALLING SEQUENCE: FUNCTION www_help_files, style, section, files, header, paths=paths, $ add_corpses=add_corpses, nosort=nosort, _extra=_extra ; INPUTS: ; style array[1]; type: structure ; One of the structures returned from the procedure ; href=www_help_style=. The structure content is described ; there. Defaults are available for several types of source ; code (e.g. IDL and Fortran) with several options for ; changing defaults. ; section array; type; string ; list of valid section headings ; ; files array; type: string ; list of files. These may include directory specification ; and a wildcard in the file name. On VMS text libraries ; are permitted. ; paths=paths array; type: string ; list of directories to be searched ; ; The 'files' and 'paths' arguments are passed unmodified to FindAllFiles. ; Several other arguments are permitted to modify file selection. ; These are explained in href=FindAllFiles=: ; ; /recursive ; /symlink ; excl_files=excl_files ; excl_paths=excl_paths ; excl_recursive=excl_recursive ; ; header array; type: structure ; if this array exists on input (from previous calls to this ; function) then new headers will be added at the end of the array. ; OPTIONAL INPUT PARAMETERS: ; /add_corpses if set then files containing no headers are added with a dummy header ; (this only makes sense if the cgi-script www_help.cgi is working to ; provide access to the source code). ; /nosort by default the headers are sorted using header.name and header.version ; The sorting can be suppressed with the /nosort keyword (useful mainly when ; this function is used to accumulate headers with several calls in sequence. ; OUTPUTS: ; nhdr scalar; type: integer ; # headers (= n_elements(header)) ; header array; type: structure ; all the header information ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; FindAllFiles, SetFileSpec, GetFileSpec, www_help_section ; www_help_get_header, InitVar, hide_env ; RESTRICTIONS: ; Has not been tested on VMS ; On VMS text libraries are processed by extracting modules into SYS$TEMP. ; After processing these files are deleted. ; PROCEDURE: ; > The start of a new section is in general defined by an uppercase word with a trailing ; colon (no whitespace). Only section headings read from the template file are ; recognized. For SSW the rules for detecting section headings are more relaxed. ; > All lines in the header start with the string style.commentchar. ; Headers start with the line style.start_char and end with style.stop_char. ; Files may contain more than one header. ; > For more information see the file sections_ssw.txt (should be located in the ; same directory as this file). ; MODIFICATION HISTORY: ; JAN-2001, Paul Hick (UCSD/CASS) ; JAN-2002, Paul Hick (UCSD/CASS) ; JUN-2003, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ; Fixed bug for case where no files are found (would return nhdr=0 ; instead of n_elements(header)). ; Fixed bug with use of keyword /nosort (sorting would be skipped if ; no files are found). ;- InitVar, nosort, /key ; First run through the list of input names, and collect all files to be ; checked for headers. print, '=============================' print, 'files checked:' FOR i=0,n_elements(files)-1 DO print, ' ', hide_env(files[i],/silent) print print, 'paths checked:' FOR i=0,n_elements(paths)-1 DO print, ' ', hide_env(paths[i],/silent) print, '=============================' code_file = FindAllFiles(files, paths=paths, _extra=_extra, count=nhdr) CASE nhdr OF 0 : BEGIN message, /info, 'No source code files' nhdr = n_elements(header) END ELSE: BEGIN ; Array 'files' now contains fully qualified names of regular ; files and text libraries SetFileSpec, code_file istlb = strupcase(GetFileSpec(part='type')) EQ '.TLB' names = GetFileSpec(part='name') ifile = 0 in_lib = 0 src_count = 0 nhdr_old = n_elements(header) REPEAT BEGIN IF istlb[ifile] THEN BEGIN ; Text library IF NOT in_lib THEN BEGIN ; Get list of modules spawn, 'LIBRARY/LIST '+code_file[ifile], module in_lib = 1 ; The output of the library/list command contains a list of ; modules following the first blank line. empty_line = (where(modules EQ ''))[0] last_line = n_elements(module)-1 nmodule = last_line-empty_line ; # modules ; List of modules IF nmodule NE 0 THEN module = module[empty_line+1:*] imodule = -1 ENDIF imodule = imodule+1 ; Next module IF imodule LT nmodule THEN BEGIN ; Extract module from library source = 'SYS$TEMP:'+module[imodule]+'.tmp' origin = [code_file[ifile],module[imodule]] spawn, 'LIBRARY/EXTRACT='+module[imodule]+'/OUTPUT='+source+' '+code_file[ifile] ENDIF ELSE BEGIN ; No more modules left in_lib = 0 source = '' origin = '' ENDELSE ENDIF ELSE BEGIN ; Regular source file source = code_file[ifile] origin = [source,''] ENDELSE ; www_help_get_header deletes the source file if extracted from library ; (origin[1] ne '') IF source NE '' THEN src_count = src_count+1 www_help_get_header, source, header, origin, style, section, add_corpses=add_corpses ; Don't increment the counter if there are more modules in the library IF NOT (istlb[ifile] AND in_lib) THEN ifile = ifile+1 ENDREP UNTIL ifile EQ nhdr nhdr = n_elements(header) message, /info, style.title+' help ('+strcompress(src_count,/rem)+' files,'+ $ strcompress(nhdr-nhdr_old)+' headers)' END ENDCASE ; Sort the headers. When accumulating headers with several calls to this ; function in sequence this is rather wasteful. So the sorting can be ; suppressed with the nosort keyword. IF nhdr GT 0 AND NOT nosort THEN BEGIN ; How is this for a really dumb trick? ; IDL truncates formatted output with the string function at 1024 lines. ; Bad dog! Bad dog! tmp = strarr(nhdr) FOR i=0,nhdr-1,1024 DO tmp[i: (i+1023) < (nhdr-1)] = string(header[i: (i+1023) < (nhdr-1) ].version,format='(I5.5)') tmp = sort(strlowcase(header.name)+tmp) header = header[tmp] ENDIF RETURN, nhdr & END