source: trunk/src/netlabs/macros/recompile.e@ 3396

Last change on this file since 3396 was 3396, checked in by Andreas Schnellbacher, 6 years ago
  • Recompile: Added deletion of .log file if corresponding .ex file is deleted.
  • Property svn:keywords set to Date Revision Author HeadURL Id
File size: 61.8 KB
Line 
1/****************************** Module Header *******************************
2*
3* Module Name: recompile.e
4*
5* Copyright (c) Netlabs EPM Distribution Project 2002
6*
7* $Id: recompile.e 3396 2019-01-06 18:12:32Z aschn $
8*
9* ===========================================================================
10*
11* This file is part of the Netlabs EPM Distribution package and is free
12* software. You can redistribute it and/or modify it under the terms of the
13* GNU General Public License as published by the Free Software
14* Foundation, in version 2 as it comes in the "COPYING" file of the
15* Netlabs EPM Distribution. This library is distributed in the hope that it
16* will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
17* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18* General Public License for more details.
19*
20****************************************************************************/
21
22compile if not defined( SMALL) -- If compiled separately
23 EA_comment 'Linkable commands for macro compilation'
24
25define
26 INCLUDING_FILE = 'RECOMPILE.E'
27
28 include 'stdconst.e'
29const
30 tryinclude 'mycnf.e'
31const
32 compile if not defined( NLS_LANGUAGE)
33 NLS_LANGUAGE = 'ENGLISH'
34 compile endif
35 include NLS_LANGUAGE'.e'
36compile endif
37
38; ---------------------------------------------------------------------------
39const
40compile if not defined( RECOMPILE_RESTART_NAMES)
41 -- These basenames require restart of EPM:
42 -- EPM: obviously
43 -- RECOMPILE: as tests showed
44 RECOMPILE_RESTART_NAMES = 'EPM RECOMPILE'
45compile endif
46
47; ---------------------------------------------------------------------------
48defc PostRelink
49 parse arg BaseName
50 --dprintf( 'PostRelink called')
51
52 -- Refresh menu if module is linked and defines a menu
53 if upcase( rightstr( BaseName, 4)) = 'MENU' & length( BaseName) > 4 then
54 'RefreshMenu'
55 endif
56
57 -- Refresh keyset if module is linked and defines keys
58 if upcase( rightstr( BaseName, 4)) = 'KEYS' & length( BaseName) > 4 then
59 'ReloadKeyset'
60 endif
61
62 -- Refresh coding style definitions if modecfg.ex is linked
63 if upcase( BaseName) = 'MODECFG' then
64 'InitModeConfig'
65 endif
66
67; ---------------------------------------------------------------------------
68; Syntax: relink [IFLINKED] [[<path>]<modulename>[.e]]
69;
70; Compiles the module, unlinks it and links it again. A fast way to
71; recompile/reload a macro under development without leaving the editor.
72; Note that the unlink is necessary in case the module is already linked,
73; else the link will merely reinitialize the previous version.
74;
75; standard: link module, even if it was not linked before
76; IFLINKED: link module only, if it was linked before
77;
78; If modulename is omitted, the current filename is assumed.
79; New: Path and extension for modulename are not required.
80defc Relink
81 args = arg(1)
82 wp = wordpos( 'IFLINKED', upcase( args))
83 fIfLinked = (wp > 0)
84 if wp then
85 args = delword( args, wp, 1) -- remove 'IFLINKED' from args
86 endif
87 Modulename = args -- new: path and ext optional
88
89 if IsNum( Modulename) then
90 n = Modulename
91 FullPathName = GetAVar( 'linkfilename.'n)
92 lp1 = lastpos( '\', FullPathName)
93 Name = substr( FullPathName, lp1 + 1)
94 lp2 = lastpos( '.', Name)
95 if lp2 > 1 then
96 Basename = substr( Name, 1, lp2 - 1)
97 else
98 Basename = Name
99 endif
100 Modulename = BaseName'.e'
101 else
102 call parse_filename( Modulename)
103 endif
104
105 if Modulename = '' then -- If no name given,
106 p = lastpos( '.', .filename)
107 if upcase( substr( .filename, p)) <> '.E' then
108 sayerror '"'.filename'" is not an .E file'
109 return
110 endif
111 Modulename = substr( .filename, 1, p - 1) -- use current file.
112 if .modify then
113 'Save' -- Save it if changed.
114 if rc then
115 return
116 endif
117 endif
118 endif
119
120 -- Check if basename of module was linked before
121 lp1 = lastpos( '\', Modulename)
122 Name = substr( Modulename, lp1 + 1)
123 lp2 = lastpos( '.', Name)
124 if lp2 > 1 then
125 Basename = substr( Name, 1, lp2 - 1)
126 else
127 Basename = Name
128 endif
129
130 UnlinkName = Basename
131 linkedrc = linked( Basename)
132 if linkedrc < 0 then
133 Next = Get_Env( 'NEPMD_ROOTDIR')'\netlabs\ex\'Basename'.ex'
134 rc2 = linked( Next)
135 if rc2 < 0 then
136 Next = Get_Env( 'NEPMD_ROOTDIR')'\epmbbs\ex\'Basename'.ex'
137 rc3 = linked( Next)
138 if rc3 < 0 then
139 else
140 linkedrc = rc3
141 UnlinkName = Next
142 endif
143 else
144 linkedrc = rc2
145 UnlinkName = Next
146 endif
147 endif
148
149 'etpm' Modulename -- This is the macro ETPM command
150 if rc then
151 return
152 endif
153
154 -- Unlink and link module if linked
155 if linkedrc >= 0 then -- if linked
156 'unlink' UnlinkName -- 'unlink' gets full pathname now
157 if rc < 0 then
158 return
159 endif
160 endif
161 if linkedrc >= 0 | fIfLinked = 0 then
162 'link' Basename
163
164 if rc >= 0 then
165 'PostRelink' Basename
166 endif
167 endif
168
169; ---------------------------------------------------------------------------
170; Syntax: etpm [[<path>]<e_file> [[<path>]<ex_file>]
171;
172; etpm compiles EPM.E to EPM.EX in <UserDir>\ex
173; etpm tree.e compiles TREE.E to TREE.EX in <UserDir>\ex
174; etpm tree compiles TREE.E to TREE.EX in <UserDir>\ex
175; etpm = compiles current file to an .ex file in <UserDir>\ex
176; etpm = = compiles current file to an .ex file in the same dir
177;
178; Does use the /v option now.
179; Doesn't respect options from the commandline, like /v or /e <logfile>.
180defc et, etpm
181
182 rest = strip( arg(1))
183 if leftstr( rest, 1) = '"' then
184 parse value rest with '"'InFile'"' rest
185 else
186 parse value rest with InFile rest
187 endif
188 if leftstr( rest, 1) = '"' then
189 parse value rest with '"'ExFile'"' .
190 else
191 parse value rest with ExFile .
192 endif
193 if InFile = '' then
194 InFile = 'epm.e'
195 else
196 call parse_filename( InFile, .filename)
197 endif
198 call parse_filename( ExFile, .filename)
199 lp = lastpos( '.', ExFile)
200 if lp > 0 then
201 if translate( substr( ExFile, lp + 1)) = 'E' then
202 ExFile = substr( ExFile, 1, lp - 1)'.ex'
203 else
204 ExFile = ExFile'.ex'
205 endif
206 endif
207
208 lp1 = lastpos( '\', InFile)
209 Name = substr( InFile, lp1 + 1)
210 lp2 = lastpos( '.', Name)
211 if lp2 > 1 then
212 BaseName = substr( Name, 1, lp2 - 1)
213 else
214 BaseName = Name
215 endif
216 NepmdUserDir = Get_Env('NEPMD_USERDIR')
217 AutolinkDir = NepmdUserDir'\autolink' -- search in <UserDir>\autolink first
218 ProjectDir = NepmdUserDir'\project' -- search in <UserDir>\project second
219 if exist( AutolinkDir'\'BaseName'.ex') then
220 DestDir = AutolinkDir
221 elseif exist( ProjectDir'\'BaseName'.ex') then
222 DestDir = ProjectDir
223 else
224 DestDir = NepmdUserDir'\ex'
225 endif
226 If ExFile = '' then
227 ExFile = DestDir'\'BaseName'.ex'
228 endif
229
230compile if defined(ETPM_CMD) -- let user specify fully-qualified name
231 EtpmCmd = ETPM_CMD
232compile else
233 EtpmCmd = 'etpm'
234compile endif
235
236 TempFile = DestDir'\'strip( leftstr( BaseName, 16))'.log'
237
238 Params = '/v 'InFile ExFile' /e 'TempFile
239
240 Os2Cmd = EtpmCmd Params
241
242 -- Must check length here!
243 deltalen = length( Os2Cmd) - 224
244 if deltalen > 0 then
245 sayerror 'Command: 'Os2Cmd
246 sayerror 'Error: command is 'deltalen' chars too long. Shorten filename or use an OS/2 or EPM shell window.'
247 return
248 endif
249
250 sayerror COMPILING__MSG infile
251 quietshell 'xcom' Os2Cmd
252 etpmrc = rc
253
254 rc = etpmrc
255 if rc = 0 then
256 refresh
257 sayerror COMP_COMPLETED__MSG': 'BaseName
258 elseif rc = -2 then
259 sayerror CANT_FIND_PROG__MSG EtpmCmd
260 stop
261 elseif rc = 41 then
262 sayerror 'ETPM.EXE:' CANT_OPEN_TEMP__MSG '"'TempFile'"'
263 stop
264 elseif exist( TempFile) then
265 call ec_position_on_error( TempFile)
266 rc = etpmrc
267 else
268 sayerror 'ETPM.EXE returned rc = 'etpmrc' for "'Os2Cmd'"'
269 rc = etpmrc
270 endif
271; call erasetemp( TempFile)
272
273; ---------------------------------------------------------------------------
274; Load file containing error, called by etpm.
275; This handles the /v output of etpm as well.
276defproc ec_position_on_error( tempfile)
277 'xcom e 'tempfile
278 if rc then -- Unexpected error.
279 sayerror ERROR_LOADING__MSG tempfile
280 if rc = -282 then -- sayerror( 'New file')
281 'xcom q'
282 endif
283 return
284 endif
285 msgl = 4
286 do l = 4 to .last
287 next = textline(l)
288 if substr( next, 1, 10) = 'compiling ' then
289 -- ignore
290 else
291 msg = next
292 msgl = l
293 leave
294 endif
295 enddo
296 if msgl < .last then
297 parse value textline( .last) with 'col= ' col
298 parse value textline( .last - 1) with 'line= ' line
299 parse value textline( .last - 2) with 'filename=' filename
300 'xcom q'
301 'e 'filename -- not xcom here, respect user's window style
302 if line <> '' and col <> '' then
303 .cursory = min( .windowheight % 2, .last)
304 if col > 0 then
305 'postme goto' line col
306 else
307 line = line - 1
308 col = length( textline( line))
309 'postme goto' line col
310 endif
311 endif
312 endif
313 sayerror msg
314
315; ---------------------------------------------------------------------------
316; Check for a modified file in ring. If not, compile EPM.E, position cursor
317; on errorline or restart on success. Quite fast!
318; Will only restart topmost EPM window.
319; Because of defc Etpm is used, EPM.EX is created in <UserDir>\ex.
320; Because of defc Restart is used, current directory will be kept.
321defc RecompileEpm
322 'RingCheckModify'
323 'Etpm epm'
324 if rc = 0 then
325 'Restart closeother'
326 endif
327
328; ---------------------------------------------------------------------------
329; Recompile all files, whose names found in .lst files in EPMEXPATH.
330;
331; Maybe to be changed: compile only those files, whose (.EX files exist) names
332; are listed in ex\*.lst and whose E files found in <UserDir>\macros.
333; Define a new command RecompileReallyAll to replace the current RecompileAll.
334;
335; Maybe another command: RecompileNew, checks filestamps and compiles
336; everything, for that the E source files have changed.
337defc RecompileAll
338
339 'RingCheckModify'
340
341 Path = NepmdScanEnv('EPMEXPATH')
342 ListFiles = ''
343 rest = Path
344 do while rest <> ''
345 parse value rest with next';'rest
346 -- Search in every piece of Path for .lst files
347 FileMask = next'\*.lst'
348 Handle = '' -- always create a new handle!
349 ListFile = ''
350 do while NepmdGetNextFile( FileMask, Handle, ListFile)
351 -- Append if not already in list
352 if pos( upcase(ListFile)';', upcase(ListFiles)';') = 0 then
353 ListFiles = ListFiles''ListFile';'
354 endif
355 enddo
356 enddo
357
358 ExFiles = ''
359 rest = ListFiles
360 do while rest <> ''
361 parse value rest with ListFile';'rest
362 -- Load ListFile
363 'xcom e /d' ListFile
364 if rc <> 0 then
365 iterate
366 endif
367 getfileid fid
368 .visible = 0
369 -- Read lines
370 do l = 1 to .last
371 Line = textline(l)
372 StrippedLine = strip(Line)
373
374 -- Ignore comments, lines starting with ';' at column 1 are comments
375 if substr( Line, 1, 1) = ';' then
376 iterate
377 -- Ignore empty lines
378 elseif StrippedLine = '' then
379 iterate
380 endif
381
382 ExFile = StrippedLine
383 -- Strip extension
384 if rightstr( upcase(ExFile), 3) = '.EX' then
385 ExFile = substr( ExFile, 1, length(ExFile) - 3)
386 endif
387 -- Ignore epm (this time)
388 if upcase(ExFile) = 'EPM' then
389 -- nop
390 -- Append ExFile to list
391 elseif pos( upcase(ExFile)';', upcase(ExFiles)';') = 0 then
392 ExFiles = ExFiles''ExFile';'
393 endif
394 enddo -- l
395 -- Quit ListFile
396 activatefile fid
397 .modify = 0
398 'xcom q'
399 enddo
400
401 rest = ExFiles
402 do while rest <> ''
403 parse value rest with ExFile';'rest
404 -- Compile ExFile and position cursor on errorline
405 'etpm' ExFile
406 -- Return if error
407 if rc <> 0 then
408 return
409 endif
410 enddo
411
412 -- Compile epm and restart (if no error)
413 'RecompileEpm'
414
415; ---------------------------------------------------------------------------
416; Walk through all files in .LST files (like RecompileAll). Recompile all
417; files, whose E sources are newer than their EX files.
418; Could become a problem: the ini entry for epm\EFileTimes has currently
419; 1101 byte. In ETK every string is limited to 1599 byte.
420;
421; Syntax: RecompileNew [RESET] | [CHECKONLY] [NOMSG] [NOMSGBOX]
422;
423defc RecompileNew
424 universal vepm_pointer
425 universal epmrestartpending
426 universal appendrecompilelog
427
428 -- Following E files are tryincluded. When the user has added one of these
429 -- since last check, that one is not listed in
430 -- \NEPMD\User\ExFiles\<basename>\EFiles. Therefore it has to be checked
431 -- additionally.
432 -- Optional E files for every E file listed in a .LST file:
433 OptEFiles = ''
434 -- Optional E files tryincluded in EPM.E only:
435 OptEpmEFiles = 'mystuff.e;mykeyset.e;'
436
437 -- Determine CheckOnly or Reset mode: disable file operations then
438 fCheckOnly = (wordpos( 'CHECKONLY', upcase( arg(1))) > 0)
439 fReset = (wordpos( 'RESET' , upcase( arg(1))) > 0)
440 fNoMsgBox = (wordpos( 'NOMSGBOX' , upcase( arg(1))) > 0)
441 fNoMsg = (wordpos( 'NOMSG' , upcase( arg(1))) > 0)
442 if fNoMsgBox = 0 & fReset = 0 then
443 fNoMsg = 1 -- no output on the MsgLine, if MsgBox will pop up
444 endif
445
446
447 parse value DateTime() with Date Time
448
449 if not fCheckOnly & not fReset then
450 'RingCheckModify'
451 endif
452
453 mouse_setpointer WAIT_POINTER
454 NepmdRootDir = Get_Env('NEPMD_ROOTDIR')
455 NepmdUserDir = Get_Env('NEPMD_USERDIR')
456 UserDirName = substr( NepmdUserDir, lastpos( '\', NepmdUserDir) + 1)
457 call MakeTree( NepmdUserDir)
458 call MakeTree( NepmdUserDir'\ex')
459 CompileDir = NepmdUserDir'\ex\tmp'
460 LogFile = NepmdUserDir'\ex\recompilenew.log'
461
462 fRestartEpm = 0
463 fFoundMd5Exe = '?'
464 Md5Exe = ''
465 cError = 0
466 cWarning = 0
467 cRecompile = 0
468 cDelete = 0
469 cRelink = 0
470
471 -- Handle case when an .E file that needs a restart (EPM.E or RECOMPILE.E)
472 -- was successfully compiled, but a previous restart wasn't executed, because
473 -- the E compiler found an error.
474 if epmrestartpending = 1 then
475 -- Restart EPM and reset universal
476 fRestartEpm = 1
477 epmrestartpending = 0
478 endif
479 -- When the E compiler found an error, the RECOMPILENEW.LOG file should
480 -- not be deleted before the next run. Then the logs will be appended.
481 -- Note that this won't have an effect after an EPM restart.
482 if appendrecompilelog = 1 then
483 -- Append to log and reset universal
484 WriteLog( LogFile, '')
485 WriteLog( LogFile, copies( '=', 71))
486 appendrecompilelog = 0
487 else
488 -- Write new log
489 if Exist( LogFile) then
490 call EraseTemp( LogFile)
491 endif
492 endif
493
494 if not fReset then
495 if fCheckOnly then
496 WriteLog( LogFile, '"RecompileNew CheckOnly" started at' Date Time', no .EX file will be replaced.')
497 else
498 WriteLog( LogFile, '"RecompileNew" started at' Date Time'.')
499 endif
500 endif
501
502 Path = Get_Env('EPMEXPATH')
503 ListFiles = ''
504 BaseNames = ReadMacroLstFiles( Path, ListFiles)
505 -- Auto-add currently linked files to MYEXFILES.LST, if not already added
506 AddBaseNames = AutoAddToMacroLstFile()
507 if AddBaseNames <> '' then
508 WriteLog( LogFile, '')
509 WriteLog( LogFile, 'Added the following basenames to 'NepmdUserDir'\ex\myexfiles.lst:')
510 Rest = AddBaseNames
511 do while Rest <> ''
512 parse value Rest with Next';'Rest
513 WriteLog( LogFile, ' 'Next)
514 enddo
515 endif
516
517 BaseNames = BaseNames''AddBaseNames
518
519 if not fReset then
520 WriteLog( LogFile, '')
521 WriteLog( LogFile, 'Checking existing user .EX files and included .E files...')
522 WriteLog( LogFile, 'W = warning')
523 WriteLog( LogFile, 'R = relinked/recompiled/new')
524 WriteLog( LogFile, 'D = deleted')
525 WriteLog( LogFile, 'E = error')
526 endif
527 if not fReset & fFoundMd5Exe = '?' then
528 -- Search for MD5.EXE only once to give an error message
529 next = FindTool( 'md5sum')
530 Basename = '(General tool)'
531 fHeaderWritten = 0
532 if next = '' then
533 fFoundMd5Exe = 0
534 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E MD5SUM.EXE, MD5SUML.EXE or MD5.EXE not found in PATH or EPMTOOLSPATH')
535 cError = cError + 1
536 else
537 fFoundMd5Exe = 1
538 Md5Exe = next
539 endif
540 endif
541
542 -- Find new source files
543 rest = BaseNames
544 BaseNames = ''
545 do while rest <> ''
546
547 -- For every ExFile...
548 parse value rest with BaseName';'rest
549 fCompCurExFile = 0
550 fCompExFile = 0
551 fReplaceExFile = 0
552 fDeleteExFile = 0
553 fCopiedExFile = 0
554 fCurExFileEqual = 0
555 fHeaderWritten = 0
556 fRelinkUnlinked = 0
557 fEFileExists = 0
558 CurEFiles = ''
559 CurEFileTimes = ''
560 CurExFileTime = ''
561 CurExFile = ''
562 AddEFiles = ''
563 NewEFiles = ''
564 NewEFileTimes = ''
565 NewExFileTime = ''
566 NetlabsExFileTime = ''
567 LastCheckTime = ''
568 KeyPath = '\NEPMD\Var\ExFiles\'lowcase(BaseName)
569 KeyPath1 = KeyPath'\LastCheckTime'
570 KeyPath2 = KeyPath'\Time' -- Time = date time of the active .ex file
571 KeyPath3 = KeyPath'\EFiles' -- EFiles = base.ext;...
572 KeyPath4 = KeyPath'\EFileTimes' -- EFileTimes = date time;...
573
574 if fReset then
575 call DeleteConfigKey( KeyPath1)
576 call DeleteConfigKey( KeyPath2)
577 call DeleteConfigKey( KeyPath3)
578 call DeleteConfigKey( KeyPath4)
579 iterate
580 endif
581
582 -- 1) Check if .E file exists
583 do once = 1 to 1
584 FullEFile = FindEFile( BaseName'.e')
585 if FullEFile = '' then
586 fEFileExists = 0
587 cWarning = cWarning + 1
588 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .E file "'BaseName'.e"')
589 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' not found in EPMMACROPATH')
590 leave
591 else
592 fEFileExists = 1
593 endif
594 enddo
595
596 -- 2) Compare current .EX file with Netlabs .EX file and delete it if equal
597 do once = 1 to 1
598 if fEFileExists <> 1 then
599 leave
600 endif
601
602 -- Check if Netlabs .EX file exists
603 NetlabsExFile = NepmdRootDir'\netlabs\ex\'BaseName'.ex'
604 if not Exist( NetlabsExFile) then
605 leave
606 endif
607
608 -- Get ExFileTime of last check from NEPMD.INI
609 -- (Saving LastCheckTime avoids a possible ETPM call, if nothing has changed)
610 LastCheckTime = QueryConfigKey( KeyPath1)
611
612 -- Get full pathname, also used for linked() and unlink
613 CurExFile = FindExFile( BaseName)
614 if CurExFile = '' then
615 CurExFile = BaseName
616 fReplaceExFile = 1
617 leave
618 endif
619
620 -- Get time of ExFile
621 CurExFileTime = NepmdQueryPathInfo( CurExFile, 'MTIME')
622 if not rc then
623 next = QueryConfigKey( KeyPath2)
624 if next <> CurExFileTime then
625 fCompExFile = 1
626 endif
627 endif
628
629 -- Compare (maybe user's) ExFile with netlabs ExFile to delete it or to give a warning if older
630 NetlabsExFileTime = NepmdQueryPathInfo( NetlabsExFile, 'MTIME')
631 if rc then
632 leave
633 endif
634
635 if upcase(CurExFile) <> upcase(NetlabsExFile) then -- if different pathnames
636 fCompCurExFile = 1
637 endif
638
639 if fCompCurExFile <> 1 then
640 leave
641 endif
642
643 if fFoundMd5Exe <> 1 then
644 leave
645 endif
646
647 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' comparing current .EX file "'CurExFile'"')
648 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' with Netlabs .EX file')
649 next = Md5Comp( CurExFile, NetlabsExFile, Md5Exe)
650 md5rc = rc
651 delrc = ''
652
653 -- If CurExFile = NetlabsExFile
654 if next = 0 then -- equal
655 fCurExFileEqual = 1 -- Required to avoid an additional Md5Comp call later
656 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' current .EX file "'CurExFile'"')
657 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is equal to Netlabs .EX file')
658 if not fCheckOnly then
659 -- linked() and unlink won't work if a full filename was specified
660 -- and if that linked file doesn't exist anymore.
661 fCurExFileWasLinked = 0
662 if linked( CurExFile) >= 0 then
663 --WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' linked before deletion: "'CurExFile'"')
664 fCurExFileWasLinked = 1
665 endif
666
667 if wordpos( upcase( BaseName), RECOMPILE_RESTART_NAMES) then
668 -- These EX files are in use, they can't be unlinked,
669 -- therefore EPM must be restarted
670 fRestartEpm = 1
671 endif
672
673 -- Unlink works only for an existing .ex file. Therefore unlink
674 -- must come before delete.
675 if fRestartEpm = 0 then
676 if fCurExFileWasLinked >= 0 then
677 -- unlink works only if EX file exists
678 'unlink' CurExFile
679 fRelinkUnlinked = 1
680 endif
681 endif
682 -- After unlinking file.ex, EraseTemp is not available at this time
683 CurLogFile = ChangeStr( '.ex', CurExFile, '.log')
684 if isadefproc( 'EraseTemp') then
685 call EraseTemp( CurExFile)
686 call EraseTemp( CurLogFile)
687 else
688 quietshell 'del' CurExFile
689 quietshell 'del' CurLogFile
690 endif
691 if rc then
692 cError = cError + 1
693 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E cannot delete current .EX file "'CurExFile'", rc = 'rc)
694 fCompExFile = 0
695 else
696 cDelete = cDelete + 1
697 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'D deleted current .EX file "'CurExFile'"')
698 fCompExFile = 0
699 endif
700
701 if fRestartEpm = 0 then
702 -- Check if old file is linked. Using BaseName here would check
703 -- for the wrong file when it didn't exist before
704 if fCurExFileWasLinked >= 0 | fRelinkUnlinked then -- <0 means error or not linked
705 if not fRelinkUnlinked then -- maybe already unlinked
706 'unlink' CurExFile
707 if rc then
708 cError = cError + 1
709 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E current .EX file not unlinked')
710 endif
711 endif
712 'link' BaseName
713 if rc >= 0 then
714 cRelink = cRelink + 1
715 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' relinked .EX file')
716 'PostRelink' BaseName
717 endif
718 endif
719 endif
720
721 endif -- not fCheckOnly
722 endif
723
724 -- If CurExFile <> NetlabsExFile or if error from deletion
725 if next <> 0 | (next = 0 & delrc) then
726 if LastCheckTime < max( CurExFileTime, NetlabsExFileTime) then
727 fCompExFile = 1
728 endif
729 if CurExFileTime < NetlabsExFileTime then
730 cWarning = cWarning + 1
731 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W current .EX file "'CurExFile'"')
732 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is older than Netlabs .EX file')
733 endif
734 endif
735
736 enddo
737
738 -- 3) Compare current .EX file with myepm .EX file if Netlabs .EX file doesn't exist
739 do once = 1 to 1
740 if fEFileExists <> 1 then
741 leave
742 endif
743
744 -- Ensure that Netlabs .EX file doesn't exists
745 NetlabsExFile = NepmdRootDir'\netlabs\ex\'BaseName'.ex'
746 if Exist( NetlabsExFile) then
747 leave
748 endif
749
750 -- Get ExFileTime of last check from NEPMD.INI
751 -- (Saving LastCheckTime avoids a possible ETPM call, if nothing has changed)
752 LastCheckTime = QueryConfigKey( KeyPath1)
753
754 -- Get full pathname, also used for linked() and unlink
755 CurExFile = FindExFile( BaseName)
756 if CurExFile = '' then
757 CurExFile = BaseName
758 fReplaceExFile = 1
759 leave
760 endif
761
762 -- Get time of ExFile
763 CurExFileTime = NepmdQueryPathInfo( CurExFile, 'MTIME')
764 if not rc then
765 next = QueryConfigKey( KeyPath2)
766 if next <> CurExFileTime then
767 fCompExFile = 1
768 endif
769 endif
770
771 enddo
772
773 -- 4) Check .E files and compare current .E files with Netlabs .E files or with last check
774 do once = 1 to 1
775 if fEFileExists <> 1 then
776 leave
777 endif
778 -- Omit this if ETPM should not be called already
779 if fReplaceExFile = 1 then
780 leave
781 endif
782
783 -- Get list of EFiles from NEPMD.INI
784 CurEFiles = QueryConfigKey( KeyPath3)
785 -- Get list of times for EFiles from NEPMD.INI
786 CurEFileTimes = QueryConfigKey( KeyPath4)
787
788 if CurEFiles = '' then
789 fCompExFile = 1
790 leave
791 endif
792
793 -- Append optional E files (user may have added them since last check)
794 orest = OptEFiles
795 do while orest <> ''
796 parse value orest with next';'orest
797 if pos( ';'upcase( next)';', ';'upcase( CurEFiles''AddEFiles)) = 0 then
798 AddEFiles = AddEFiles''next';'
799 endif
800 enddo
801 if upcase( BaseName) = 'EPM' then
802 orest = OptEpmEFiles
803 do while orest <> ''
804 parse value orest with next';'orest
805 if pos( ';'upcase( next)';', ';'upcase( CurEFiles''AddEFiles)) = 0 then
806 AddEFiles = AddEFiles''next';'
807 endif
808 enddo
809 endif
810
811 erest = CurEFiles''AddEFiles
812 trest = CurEFileTimes
813 do while erest <> ''
814 -- For every EFile of CurEFiles...
815
816 parse value erest with EFile';'erest
817 parse value trest with CurEFileTime';'trest
818 EFileTime = ''
819 NetlabsEFileTime = ''
820 -- Get full pathname
821 FullEFile = NepmdSearchPath( EFile, 'EPMMACROPATH')
822
823 if FullEFile = '' then
824 -- EFile doesn't exist
825 if pos( ';'upcase( EFile)';', ';'upcase( CurEFiles)) > 0 then
826 -- EFile was deleted and previously added to EFiles
827 fCompExFile = 1
828 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .E file "'EFile'"')
829 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' was deleted since last check')
830 endif
831 iterate
832 endif
833
834 -- Get time of EFile
835 EFileTime = NepmdQueryPathInfo( FullEFile, 'MTIME')
836 if rc then
837 iterate
838 endif
839
840 -- Compare time of EFile with LastCheckTime and CurExFileTime
841 if not fCheckOnly then
842 if EFileTime > max( LastCheckTime, CurExFileTime) then
843 fCompExFile = 1
844 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .E file "'FullEFile'"')
845 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is newer than last check')
846 --leave -- don't leave to enable further warnings
847 elseif (CurEFileTime = '') & (pos( ';'upcase( EFile)';', ';'upcase( OptEFiles)) > 0) then
848 --WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' 'BaseName' - .E file "'FullEFile'" is an optional file and probably not included')
849 elseif EFileTime <> CurEFileTime then
850 fCompExFile = 1
851 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .E file "'FullEFile'"')
852 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is newer or older compared to last check of this .E file')
853 --leave -- don't leave to enable further warnings
854 endif
855 endif
856 -- Compare time of (maybe user's) EFile with netlabs EFile to give a warning if older
857 NetlabsEFile = NepmdRootDir'\netlabs\macros\'EFile
858 NetlabsEFileTime = NepmdQueryPathInfo( NetlabsEFile, 'MTIME')
859 if not rc then
860 if EFileTime < NetlabsEFileTime then
861 cWarning = cWarning + 1
862 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .E file "'FullEFile'"')
863 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is older than Netlabs .E file')
864 endif
865 endif
866
867 enddo -- while erest <> ''
868
869 enddo
870
871 -- 5) Run Etpm and compare compiled .E files with Netlabs .E files
872 do once = 1 to 1
873
874 if fEFileExists <> 1 then
875 leave
876 endif
877
878 if (fReplaceExFile <> 1 & fCompExFile <> 1) then
879 leave
880 endif
881
882 ExFile = '' -- init for CallEtpm
883 EtpmLogFile = '' -- init for CallEtpm
884 etpmrc = CallEtpm( BaseName, CompileDir, ExFile, EtpmLogFile)
885
886 if etpmrc <> 0 then
887 rc = etpmrc
888 cError = cError + 1
889 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E ETPM returned rc =' rc)
890
891 -- Handle the case when an .E file that needs a restart (EPM.E or RECOMPILE.E)
892 -- was successfully compiled, but a restart won't be executed, because
893 -- the E compiler found an error.
894 if fRestartEpm then
895 epmrestartpending = 1
896 endif
897 -- When the E compiler found an error, the RECOMPILENEW.LOG file should
898 -- not be deleted before the next run. Then the logs will be appended.
899 -- Note that this won't have an effect after an EPM restart.
900 appendrecompilelog = 1
901
902 mouse_setpointer vepm_pointer
903 return rc
904 endif
905
906 NewEFiles = GetEtpmFilesFromLog( EtpmLogFile)
907 erest = NewEFiles
908 NewEFileTimes = ''
909 do while erest <> ''
910 -- For every EFile...
911 parse value erest with EFile';'erest
912
913 EFileTime = ''
914 -- Get full pathname
915 FullEFile = NepmdSearchPath( EFile, 'EPMMACROPATH')
916 -- Get time of EFile
917 EFileTime = NepmdQueryPathInfo( FullEFile, 'MTIME')
918 NewEFileTimes = NewEFileTimes''EFileTime';'
919
920 -- Check E files here (after etpm) if not already done above
921 if CurEFiles <> '' then
922 iterate
923 endif
924
925 -- Compare time of (maybe user's) EFile with netlabs EFile to give a warning if older
926 NetlabsEFile = NepmdRootDir'\netlabs\macros\'EFile
927 if upcase( NetlabsEFile) = upcase( EFile) then
928 iterate
929 endif
930
931 NetlabsEFileTime = NepmdQueryPathInfo( NetlabsEFile, 'MTIME')
932 if rc then
933 iterate
934 endif
935
936 if EFileTime < NetlabsEFileTime then
937 cWarning = cWarning + 1
938 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .E file "'FullEFile'"')
939 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is older than Netlabs .E file')
940 endif
941 enddo
942
943 -- Get time of new ExFile
944 NewExFileTime = NepmdQueryPathInfo( ExFile, 'MTIME')
945
946 enddo
947
948 -- 6) Compare .EX files
949 do once = 1 to 1
950 if fEFileExists <> 1 then
951 leave
952 endif
953 if fCompExFile <> 1 then
954 leave
955 endif
956 if fCurExFileEqual = 1 then
957 leave
958 endif
959 if fFoundMd5Exe <> 1 then
960 leave
961 endif
962
963 next = Md5Comp( ExFile, CurExFile, Md5Exe)
964 md5rc = rc
965 if next = 1 then -- different
966 fReplaceExFile = 1
967 if NetlabsExFileTime > '' then
968 next2 = Md5Comp( ExFile, NetlabsExFile, Md5Exe)
969 md5rc = rc
970 if next2 = 0 then
971 if upcase( CurExFile) <> upcase( NetlabsExFile) then
972 if not fCheckOnly then
973 fDeleteExFile = 1
974 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .EX file "'ExFile'"')
975 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current but equal to Netlabs .EX file')
976 else
977 cWarning = cWarning + 1
978 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .EX file "'ExFile'"')
979 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current but equal to Netlabs .EX file')
980 endif
981 endif
982 else
983 if not fCheckOnly then
984 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .EX file "'ExFile'"')
985 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current and Netlabs .EX file')
986 else
987 cWarning = cWarning + 1
988 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .EX file "'ExFile'"')
989 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current and Netlabs .EX file')
990 endif
991 endif
992 else
993 if not fCheckOnly then
994 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .EX file "'ExFile'"')
995 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current .EX file')
996 else
997 cWarning = cWarning + 1
998 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'W .EX file "'ExFile'"')
999 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is different from current .EX file')
1000 endif
1001 endif
1002
1003 elseif next = 0 then -- equal
1004 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' .EX file "'ExFile'"')
1005 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' is equal to current .EX file')
1006
1007 else -- error
1008 cError = cError + 1
1009 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E MD5Comp returned rc = 'md5rc' on comparing "'ExFile'"')
1010 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' with current .EX file "'CurExFile'"')
1011 endif
1012
1013 enddo
1014
1015 -- Don't unlink, delete or copy if Checkonly is active
1016 if fReplaceExFile = 1 & not fCheckOnly then
1017 DestDir = GetExFileDestDir( ExFile)
1018 if fDeleteExFile = 1 then
1019
1020 -- Unlink works only for an existing .ex file. Therefore unlink
1021 -- must come before delete.
1022 if fRestartEpm = 0 then
1023 if linked( CurExFile) >= 0 then
1024 -- unlink works only if EX file exists
1025 'unlink' CurExFile
1026 fRelinkUnlinked = 1
1027 endif
1028 endif
1029 -- After unlinking file.ex, EraseTemp is not available at this time
1030 CurLogFile = ChangeStr( '.ex', CurExFile, '.log')
1031 if isadefproc( 'EraseTemp') then
1032 call EraseTemp( CurExFile)
1033 call EraseTemp( CurLogFile)
1034 else
1035 quietshell 'del' CurExFile
1036 quietshell 'del' CurLogFile
1037 endif
1038 if rc then
1039 cError = cError + 1
1040 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E cannot delete .EX file "'CurExFile'", rc = 'rc)
1041 else
1042 cDelete = cDelete + 1
1043 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'D deleted .EX file "'CurExFile'"')
1044 endif
1045
1046 else
1047 quietshell 'copy' ExFile DestDir
1048 if rc then
1049 cError = cError + 1
1050 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'E cannot copy .EX file to "'DestDir'", rc = 'rc)
1051 else
1052 fCopiedExFile = 1
1053 WriteBasenameLog( LogFile, Basename, fHeaderWritten, 'R copied .EX file to "'DestDir'"')
1054 endif
1055 quietshell 'copy' EtpmLogFile DestDir
1056 cRecompile = cRecompile + 1
1057 endif
1058 if wordpos( upcase( BaseName), RECOMPILE_RESTART_NAMES) then
1059 -- These EX files are in use, they can't be unlinked,
1060 -- therefore EPM must be restarted
1061 fRestartEpm = 1
1062 endif
1063 if fRestartEpm = 0 then
1064 -- Check if old file is linked. Using BaseName here would check
1065 -- for the wrong file when it didn't exist before
1066 if linked( CurExFile) >= 0 | fRelinkUnlinked then -- <0 means error or not linked
1067 if not fRelinkUnlinked then -- maybe already unlinked
1068 'unlink' CurExFile
1069 endif
1070 'link' BaseName
1071 if rc >= 0 then
1072 cRelink = cRelink + 1
1073 WriteBasenameLog( LogFile, Basename, fHeaderWritten, ' relinked .EX file')
1074 'PostRelink' BaseName
1075 endif
1076 endif
1077 endif
1078 endif
1079
1080 -- Don't write new times and files if ExFile needs to be replaced,
1081 -- but Checkonly is active
1082 if not fCheckOnly | not fReplaceExFile then
1083 if NewExFileTime <> '' then
1084 DeleteConfigKey( KeyPath1)
1085 WriteConfigKey( KeyPath1, NewExFileTime)
1086 if fCheckOnly then
1087 -- nop
1088 elseif fCopiedExFile = 1 then
1089 DeleteConfigKey( KeyPath2)
1090 WriteConfigKey( KeyPath2, NewExFileTime)
1091 elseif fDeleteExFile = 1 then
1092 DeleteConfigKey( KeyPath2)
1093 WriteConfigKey( KeyPath2, NetlabsExFileTime)
1094 elseif fCompExFile = 1 then
1095 DeleteConfigKey( KeyPath2)
1096 WriteConfigKey( KeyPath2, CurExFileTime)
1097 endif
1098 endif
1099 if NewEFiles <> '' then
1100 DeleteConfigKey( KeyPath3)
1101 DeleteConfigKey( KeyPath4)
1102 WriteConfigKey( KeyPath3, NewEFiles)
1103 WriteConfigKey( KeyPath4, NewEFileTimes)
1104 endif
1105 endif
1106
1107 enddo -- while rest <> ''
1108
1109 WriteLog( LogFile, copies( '-', 71))
1110
1111 if fReset then
1112 if not fNoMsg then
1113 sayerror 'All RecompileNew entries deleted from NEPMD.INI'
1114 endif
1115 mouse_setpointer vepm_pointer
1116 return 0
1117 endif
1118
1119 WriteLog( LogFile, 'SUMMARY:')
1120 WriteLog( LogFile, ' 'cRecompile' file(s) recompiled')
1121 WriteLog( LogFile, ' 'cDelete' file(s) deleted')
1122 WriteLog( LogFile, ' therefrom')
1123 WriteLog( LogFile, ' 'cRelink' file(s) relinked')
1124 WriteLog( LogFile, ' 'cError' error(s)')
1125 WriteLog( LogFile, ' 'cWarning' warning(s)')
1126 if fRestartEpm = 1 then
1127 WriteLog( LogFile, ' restart')
1128 endif
1129 WriteLog( LogFile, '')
1130
1131 if fCheckOnly then
1132 if cWarning > 0 then
1133 Text = cWarning 'warning(s), no file replaced. Correct that before the next EPM start!'
1134 else
1135 Text = 'No warnings, everything looks ok.'
1136 endif
1137 else
1138 if fRestartEpm = 1 then
1139 Text = cRecompile 'file(s) recompiled and' cDelete 'file(s) deleted,' cWarning 'warning(s), restart'
1140 else
1141 Text = cRecompile 'file(s) recompiled and' cDelete 'file(s) deleted, therefrom' cRelink' file(s) relinked,' cWarning 'warning(s)'
1142 endif
1143 endif
1144 if not fNoMsg then
1145 sayerror Text' - see "'LogFile'"'
1146 endif
1147
1148 WriteLog( LogFile, '.LST FILES:')
1149 WriteLog( LogFile, ' .E/.EX files from the following .LST files were checked:')
1150 rest = ListFiles
1151 do while rest <> ''
1152 parse value rest with next';'rest
1153 WriteLog( LogFile, ' 'next)
1154 enddo
1155 WriteLog( LogFile, '')
1156
1157 WriteLog( LogFile, 'OTHER .E/.EX FILES:')
1158/*
1159 WriteLog( LogFile, ' The following .EX files were found:')
1160 WriteLog( LogFile, ' -> Todo: list other EX files here.')
1161*/
1162 WriteLog( LogFile, ' To include them here, append the .EX file basenames to')
1163 WriteLog( LogFile, ' 'upcase(UserDirName)'\EX\MYEXFILES.LST. See also the (re)link documentation.')
1164 WriteLog( LogFile, '')
1165
1166 if cWarning > 0 then
1167 -- Check if LogFile already loaded
1168 getfileid logfid, LogFile
1169 if logfid <> '' then
1170 -- Quit LogFile
1171 getfileid fid
1172 activatefile logfid
1173 .modify = 0
1174 'xcom q'
1175 if fid <> logfid then
1176 activatefile fid
1177 endif
1178 endif
1179 endif
1180 if cWarning > 0 then
1181 ret = 1
1182 else
1183 ret = 0
1184 endif
1185 quietshell 'del' CompileDir'\* /n & rmdir' CompileDir -- must come before restart
1186
1187 if (not fCheckOnly) & (fRestartEpm = 1) then
1188 Cmd = 'postme postme Restart closeother'
1189 else
1190 Cmd = ''
1191 endif
1192 if not fNoMsgBox then
1193 args = cError cWarning cRecompile cDelete cRelink fRestartEpm fCheckOnly
1194 Cmd = Cmd 'RecompileNewMsgBox' args
1195 endif
1196 Cmd = strip( Cmd)
1197 Cmd
1198 mouse_setpointer vepm_pointer
1199
1200 rc = ret
1201
1202; ---------------------------------------------------------------------------
1203; Extract basenames for compilable macro files from all LST files
1204defproc ReadMacroLstFiles( Path, var ListFiles)
1205 ListFiles = ''
1206 rest = Path
1207 do while rest <> ''
1208 parse value rest with next';'rest
1209 -- Search in every piece of Path for .lst files
1210 FileMask = next'\*.lst'
1211 Handle = '' -- always create a new handle!
1212 ListFile = ''
1213 do while NepmdGetNextFile( FileMask, Handle, ListFile)
1214 -- Append if not already in list
1215 -- Ignore if filename (without path) exists in list
1216 lp = lastpos( '\', ListFile)
1217 Name = substr( ListFile, lp + 1)
1218 if pos( '\'upcase( Name)';', upcase( ListFiles)) = 0 then
1219 ListFiles = ListFiles''ListFile';'
1220 endif
1221 enddo
1222 enddo
1223
1224 fPrependEpm = 0
1225 BaseNames = '' -- ';'-separated list with basenames
1226 rest = ListFiles
1227 do while rest <> ''
1228 parse value rest with ListFile';'rest
1229
1230 -- Load ListFile
1231 'xcom e /d' ListFile
1232 if rc <> 0 then
1233 iterate
1234 endif
1235 getfileid fid
1236 .visible = 0
1237 -- Read lines
1238 do l = 1 to .last
1239 Line = textline(l)
1240 StrippedLine = strip(Line)
1241
1242 -- Ignore comments, lines starting with ';' at column 1 are comments
1243 if substr( Line, 1, 1) = ';' then
1244 iterate
1245 -- Ignore empty lines
1246 elseif StrippedLine = '' then
1247 iterate
1248 endif
1249
1250 BaseName = StrippedLine
1251 -- Strip extension
1252 if rightstr( upcase( BaseName), 3) = '.EX' then
1253 BaseName = substr( BaseName, 1, length( BaseName) - 3)
1254 endif
1255 -- Ignore epm (this time)
1256 if upcase( BaseName) = 'EPM' then
1257 fPrependEpm = 1
1258 -- Append ExFile to list
1259 elseif pos( ';'upcase(BaseName)';', ';'upcase(BaseNames)';') = 0 then
1260 BaseNames = BaseNames''BaseName';'
1261 endif
1262 enddo -- l
1263 -- Quit ListFile
1264 activatefile fid
1265 .modify = 0
1266 'xcom q'
1267
1268 enddo
1269
1270 -- Prepend 'epm;'
1271 -- 'epm;' should be the first entry, because it will restart EPM and
1272 -- unlinking/linking of other .EX files can be avoided then.
1273 if fPrependEpm = 1 then
1274 BaseNames = 'epm;'BaseNames -- ';'-separated list with basenames
1275 endif
1276 return BaseNames
1277
1278; ---------------------------------------------------------------------------
1279; Basenames can be a ;-separated list. A trailing ; is optional.
1280; Example: Filename1;Filename2 or Filename1
1281defc EditMacroLstFile
1282 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1283 ListFile = NepmdUserDir'\ex\myexfiles.lst'
1284
1285 'xcom e /d' ListFile
1286 if rc <> 0 & rc <> -282 then -- if error, -282 = sayerror("New file")
1287 return
1288 endif
1289 if rc = -282 then
1290 insertline '; This file contains compilable user macro files. It is read by RecompileNew'
1291 insertline '; and ensures that an EX file is compiled automatically when its E file has'
1292 insertline '; changed. Add one basename per line. A semicolon in column 1 marks a comment.'
1293 endif
1294 fAppendEmptyLine = 0
1295 if .last = 0 then
1296 fAppendEmptyLine = 1
1297 elseif textline( .last) <> '' then
1298 fAppendEmptyLine = 1
1299 endif
1300 if fAppendEmptyLine then
1301 insertline '', .last + 1
1302 endif
1303 bottom
1304 .col = 1
1305
1306; ---------------------------------------------------------------------------
1307; Basenames can be a ;-separated list. A trailing ; is optional.
1308; Example: Filename1;Filename2 or Filename1
1309defproc AddToMacroLstFile( Basenames)
1310 rc = 0
1311 'EditMacroLstFile'
1312 if rc <> 0 & rc <> -282 then -- if error, -282 = sayerror("New file")
1313 return
1314 endif
1315
1316 rc = 0
1317 getfileid fid
1318 .visible = 0
1319 .autosave = 0
1320
1321 bottom
1322 .col = 1
1323 Rest = Basenames
1324 do while Rest <> ''
1325 parse value Rest with Basename';'Rest
1326 Rest = strip( Rest)
1327 insertline Basename
1328 enddo
1329 -- Quit ListFile
1330 activatefile fid
1331 .modify = 0
1332 'xcom s'
1333 'xcom q'
1334 return
1335
1336; ---------------------------------------------------------------------------
1337; Basenames can be a ;-separated list. A trailing ; is optional.
1338; Example: Filename1;Filename2 or Filename1
1339defproc DeleteFromMacroLstFile( Basenames)
1340 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1341 ListFile = NepmdUserDir'\ex\myexfiles.lst'
1342
1343 'xcom e /d' ListFile
1344 if rc = -282 then -- if error, -282 = sayerror("New file")
1345 .modify = 0
1346 'xcom q'
1347 rc = -282
1348 endif
1349 if rc <> 0 then
1350 return
1351 endif
1352 getfileid fid
1353 .visible = 0
1354 getsearch savedsearch
1355 Rest = Basenames
1356 rcx = 0
1357 lrc = 0
1358 do while Rest <> ''
1359 parse value Rest with Basename';'Rest
1360 Rest = strip( Rest)
1361 display -14
1362 'xcom l '\1'^'Basename'$'\1'f+tcx'
1363 display 14
1364 lrc = rc
1365 if lrc then
1366 rcx = lrc
1367 iterate
1368 endif
1369 deleteline
1370 enddo
1371 setsearch savedsearch
1372 -- Quit ListFile
1373 activatefile fid
1374 .modify = 0
1375 'xcom s'
1376 'xcom q'
1377 rc = rcx
1378 return
1379
1380; ---------------------------------------------------------------------------
1381; Returns a ;-separated list of linked user .ex files.
1382; Adds them to myexfiles.lst.
1383defproc AutoAddToMacroLstFile
1384 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1385 AutolinkDir = NepmdUserDir'\autolink' -- search in <UserDir>\autolink first
1386 ProjectDir = NepmdUserDir'\project' -- search in <UserDir>\project second
1387 UserExDir = NepmdUserDir'\ex'
1388 UserExDirs = AutoLinkDir';'ProjectDir';'UserExDir
1389
1390 Path = Get_Env('EPMEXPATH')
1391 ListFiles = ''
1392 BaseNames = ReadMacroLstFiles( Path, ListFiles)
1393
1394 -- Search all *.ex files in UserExDirs
1395 NewUserBasenames = ''
1396 Rest = UserExDirs
1397 do while Rest <> ''
1398 parse value Rest with NextDir';'Rest
1399
1400 Handle = '' -- always create a new handle!
1401 next = ''
1402 do while NepmdGetNextFile( NextDir'\*.ex', Handle, next)
1403 -- Strip path and extension
1404 lp1 = lastpos( '\', next)
1405 next = substr( next, lp1 + 1)
1406 lp2 = lastpos( '.', next)
1407 Basename = substr( next, 1, lp2 - 1)
1408
1409 -- Check if module is linked
1410 linkedrc = linked( Basename)
1411 if linkedrc < 0 then
1412 iterate
1413 -- Check if module is already added to a .lst file
1414 elseif pos( ';'upcase( BaseName)';', ';'upcase( BaseNames)';') <> 0 then
1415 iterate
1416 endif
1417
1418 -- Append Basename
1419 NewUserBasenames = NewUserBasenames''Basename';'
1420 enddo
1421
1422 enddo
1423
1424 -- Add it to myexfiles.lst
1425 if NewUserBasenames <> '' then
1426 call AddToMacroLstFile( NewUserBasenames)
1427 endif
1428
1429 return NewUserBasenames
1430
1431; ---------------------------------------------------------------------------
1432; Returns rc of the ETPM.EXE call and sets ExFile, EtpmLogFile.
1433; MacroFile may be specified without .e extension.
1434; Uses 'md' to create a maybe non-existing CompileDir, therefore its parent
1435; must exist.
1436defproc CallEtpm( MacroFile, CompileDir, var ExFile, var EtpmLogFile)
1437 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1438 etpmrc = -1
1439 CompileDir = NepmdUserDir'\ex\tmp'
1440 if not exist( CompileDir) then
1441 call MakeTree( CompileDir)
1442 if not exist( CompileDir) then
1443 sayerror 'CallEtpm: Cannot find or create CompileDir "'CompileDir'"'
1444 stop
1445 endif
1446 endif
1447 lp1 = lastpos( '\', MacroFile)
1448 next = substr( MacroFile, lp1 + 1)
1449 lp2 = lastpos( '.E', upcase( next))
1450 if rightstr( upcase( next), 2) = '.E' then
1451 BaseName = substr( next, 1, length( next) - 2)
1452 else
1453 BaseName = next
1454 endif
1455
1456 ExFile = CompileDir'\'BaseName'.ex'
1457 EtpmLogFile = CompileDir'\'BaseName'.log'
1458
1459 Params = '/v 'MacroFile '/e 'EtpmLogFile
1460 --dprintf( '', ' compiling 'ExFileBaseName)
1461
1462 CurDir = directory()
1463 call directory( '\')
1464 call directory( CompileDir)
1465
1466 Os2Cmd = 'etpm' Params
1467 quietshell 'xcom' Os2Cmd
1468 etpmrc = rc
1469
1470 call directory( '\')
1471 call directory( CurDir)
1472
1473 if not etpmrc then
1474 --dprintf( 'CallEtpm', ' 'BaseName' compiled successfully to 'ExFile)
1475 elseif etpmrc = -2 then
1476 sayerror CANT_FIND_PROG__MSG 'ETPM.EXE'
1477 elseif etpmrc = 41 then
1478 sayerror 'ETPM.EXE:' CANT_OPEN_TEMP__MSG '"'
1479 elseif exist( EtpmLogFile) then
1480 call ec_position_on_error( EtpmLogFile)
1481 else
1482 sayerror 'ETPM.EXE returned rc = 'etpmrc' for "'Os2Cmd'"'
1483 endif
1484 return etpmrc
1485
1486; ---------------------------------------------------------------------------
1487; Returns a ';'-separated list of all used macro files from an ETPM /v log.
1488; Each macro file is appended by a ';' for easy parsing.
1489; ETPM won't list a macro file's path, when it founds that file in the
1490; current path. Therefore macro files are maybe listed without path.
1491defproc GetEtpmFilesFromLog( EtpmLogFile)
1492 EFiles = ''
1493 'xcom e 'EtpmLogFile
1494 if rc then -- Unexpected error or new .Untitled file
1495 sayerror ERROR_LOADING__MSG EtpmLogFile
1496 else
1497 do l = 4 to .last -- start at line 4 to omit the ' compiling ...' line
1498 parse value textline(l) with 'compiling 'EFile
1499 if EFile > '' then
1500 -- strip path
1501 lp = lastpos( '\', EFile)
1502 EFile = substr( EFile, lp + 1)
1503 EFiles = EFiles''EFile';'
1504 endif
1505 enddo
1506 endif
1507 'xcom q'
1508 return EFiles
1509
1510; ---------------------------------------------------------------------------
1511; Returns FullName of ExFile when found, else nothing.
1512; Doesn't search in current dir. The path of ExFile is stripped to get its
1513; name.
1514defproc FindExFile( ExFile)
1515 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1516 AutolinkDir = NepmdUserDir'\autolink' -- search in <UserDir>\autolink first
1517 ProjectDir = NepmdUserDir'\project' -- search in <UserDir>\project second
1518 FullExFile = ''
1519 -- strip path
1520 lp = lastpos( '\', ExFile)
1521 ExFile = substr( ExFile, lp + 1)
1522 if rightstr( upcase( ExFile), 3) <> '.EX' then
1523 ExFile = ExFile'.ex'
1524 endif
1525 if Exist( AutolinkDir'\'ExFile) then
1526 FullExFile = AutolinkDir'\'ExFile
1527 elseif Exist( ProjectDir'\'ExFile) then
1528 FullExFile = ProjectDir'\'ExFile
1529 else
1530 FullExFile = NepmdSearchPath( ExFile, 'EPMEXPATH')
1531 endif
1532 FullExFile = NepmdQueryFullName( FullExFile)
1533 return FullExFile
1534
1535; ---------------------------------------------------------------------------
1536; Returns FullName of EFile when found, else nothing.
1537; Doesn't search in current dir. The path of EFile is stripped to get its
1538; name.
1539defproc FindEFile( EFile)
1540 FullEFile = ''
1541 -- strip path
1542 lp = lastpos( '\', EFile)
1543 EFile = substr( EFile, lp + 1)
1544 if rightstr( upcase( EFile), 2) <> '.E' then
1545 EFile = EFile'.e'
1546 endif
1547 FullEFile = NepmdSearchPath( EFile, 'EPMMACROPATH')
1548 return FullEFile
1549
1550; ---------------------------------------------------------------------------
1551; Determine destination dir for an ExFile recompilation.
1552; Doesn't search in current dir. The path of ExFile is stripped to get its
1553; name.
1554defproc GetExFileDestDir( ExFile)
1555 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1556 AutolinkDir = NepmdUserDir'\autolink' -- search in <UserDir>\autolink first
1557 ProjectDir = NepmdUserDir'\project' -- search in <UserDir>\project second
1558 DestDir = ''
1559 -- strip path
1560 lp = lastpos( '\', ExFile)
1561 ExFile = substr( ExFile, lp + 1)
1562 if rightstr( upcase( ExFile), 3) <> '.EX' then
1563 ExFile = ExFile'.ex'
1564 endif
1565 if exist( AutolinkDir'\'ExFile) then
1566 DestDir = AutolinkDir
1567 elseif exist( ProjectDir'\'ExFile) then
1568 DestDir = ProjectDir
1569 else
1570 DestDir = NepmdUserDir'\ex'
1571 endif
1572 return DestDir
1573
1574; ---------------------------------------------------------------------------
1575compile if not defined( EPM_EDIT_LOGAPPEND)
1576const
1577 EPM_EDIT_LOGAPPEND = 5496
1578compile endif
1579
1580defproc WriteLog( LogFile, Msg)
1581 LogFile = LogFile\0
1582 Msg = Msg\13\10\0
1583 call windowmessage( 1, getpminfo(EPMINFO_EDITFRAME),
1584 EPM_EDIT_LOGAPPEND,
1585 ltoa( offset( LogFile)''selector( LogFile), 10),
1586 ltoa( offset( Msg)''selector( Msg), 10))
1587 return
1588
1589; ---------------------------------------------------------------------------
1590defproc WriteBasenameLog( LogFile, Basename, var fHeaderWritten, Msg)
1591 if fHeaderWritten = 0 then
1592 WriteLog( LogFile, copies( '-', 71))
1593 WriteLog( LogFile, BaseName)
1594 fHeaderWritten = 1
1595 endif
1596 WriteLog( LogFile, Msg)
1597 return
1598
1599; ---------------------------------------------------------------------------
1600; Compare .EX and .E macro files from <UserDir> with those from the NETLABS
1601; tree.
1602defc CheckEpmMacros
1603
1604 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1605 call MakeTree( NepmdUserDir)
1606 call MakeTree( NepmdUserDir'\ex')
1607 call MakeTree( NepmdUserDir'\macros')
1608 call MakeTree( NepmdUserDir'\autolink')
1609
1610 'RecompileNew CheckOnly'
1611
1612; ---------------------------------------------------------------------------
1613; Show a MsgBox with the result of RecompileNew, submitted as arg(1).
1614; Syntax: RecompileNewMsgBox cError cWarning cRecompile cDelete cRelink fRestart fCheckOnly
1615; Todo: use different text for fCheckOnly = 1, cRecompile > 0, cRelink > 0
1616defc RecompileNewMsgBox
1617 NepmdUserDir = Get_Env('NEPMD_USERDIR')
1618 UserDirName = substr( NepmdUserDir, lastpos( '\', NepmdUserDir) + 1)
1619 LogFile = NepmdUserDir'\ex\recompilenew.log'
1620 parse arg cError cWarning cRecompile cDelete cRelink fRestart fCheckOnly
1621
1622 -- Build RestartList for fRestart
1623 RestartList = 'EPM.EX'
1624 do w = 1 to words( RECOMPILE_RESTART_NAMES)
1625 next = upcase( word( RECOMPILE_RESTART_NAMES, w))
1626 parse value next with next'.'ext
1627 next = next'.EX'
1628 if wordpos( next, RestartList) > 0 then
1629 iterate
1630 endif
1631 if w = words( RECOMPILE_RESTART_NAMES) then
1632 RestartList = RestartList\n\9'or' next
1633 else
1634 RestartList = RestartList','\n\9''next
1635 endif
1636 enddo
1637
1638 Bul = \7
1639 Text = ''
1640 if fCheckOnly then
1641 Text = Text || 'RecompileNew CHECKONLY:'\n\n
1642 else
1643 Text = Text || 'RecompileNew:'\n\n
1644 Text = Text || ' 'Bul\9''cRecompile' file(s) recompiled'\n
1645 Text = Text || ' 'Bul\9''cDelete' file(s) deleted'\n
1646 if fRestart then
1647 Text = Text || ' 'Bul\9'EPM restarted because'\n
1648 Text = Text || \9'recompilation of 'RestartList\n\n
1649 else
1650 -- EPM/PM? bug: the doubled \n at the end adds 1 additional space after cRelink:
1651 Text = Text || ' 'Bul\9''cRelink' file(s) relinked'\n\n
1652 endif
1653 endif
1654 if cError > 0 then
1655 Text = Text || 'Errors(s) occurred during comparison of 'upcase(UserDirName)' files'
1656 Text = Text || ' with NETLABS files. See log file'
1657 Text = Text || ' 'upcase(UserDirName)'\EX\RECOMPILENEW.LOG'\n\n
1658 Text = Text || 'Do you want to load the log file now?'
1659 Style = MB_OKCANCEL + MB_ERROR + MB_DEFBUTTON1 + MB_MOVEABLE
1660 elseif cWarning > 0 then
1661 Text = Text || 'Warning(s) occurred during comparison of 'upcase(UserDirName)' files'
1662 Text = Text || ' with NETLABS files. See log file'
1663 Text = Text || ' 'upcase(UserDirName)'\EX\RECOMPILENEW.LOG'\n\n
1664 Text = Text || 'In order to use all the newly installed NETLABS files,'
1665 Text = Text || ' delete or rename the listed 'upcase(UserDirName)' files, that produced'
1666 Text = Text || ' a warning. A good idea would be to rename'
1667 Text = Text || ' your 'upcase(UserDirName)'\MACROS and 'upcase(UserDirName)'\EX'
1668 Text = Text || ' directories before the next EPM start.'\n\n
1669 Text = Text || 'Only when you have added your own macros:'\n
1670 Text = Text || 'After that, merge your own additions with the new'
1671 Text = Text || ' versions of the macros in NETLABS\MACROS.'
1672 Text = Text || ' (They can be left in your 'upcase(UserDirName)'\MACROS dir, if there''s'
1673 Text = Text || ' no name clash.) Then Recompile your macros. This can be'
1674 Text = Text || ' done easily with NEPMD''s RecompileNew command.'\n\n
1675 Text = Text || 'Do you want to load the log file now?'
1676 Style = MB_OKCANCEL + MB_WARNING + MB_DEFBUTTON1 + MB_MOVEABLE
1677 else
1678 Text = Text || 'No warning(s) occurred during comparison of 'upcase(UserDirName)' files'
1679 Text = Text || ' with NETLABS files.'\n\n
1680 Text = Text || 'If you have added own macro files to your MYEPM tree,'
1681 Text = Text || ' then they are newer than the files in the NETLABS tree.'
1682 Text = Text || ' Apparently no old MYEPM files are used.'\n\n
1683 Text = Text || 'Do you want to load the log file now?'
1684 Style = MB_OKCANCEL + MB_INFORMATION + MB_DEFBUTTON1 + MB_MOVEABLE
1685 endif
1686
1687 Title = 'Checked .E and .EX files from 'upcase(UserDirName)' tree'
1688 rcx = winmessagebox( Title,
1689 Text,
1690 Style)
1691 if rcx = MBID_OK then
1692 -- check if old LogFile already in ring
1693 getfileid logfid, LogFile
1694 if logfid <> '' then
1695 -- discard previously loaded LogFile from ring
1696 getfileid curfid
1697 if curfid = logfid then
1698 -- quit current file
1699 'xcom quit'
1700 else
1701 -- temporarily switch to old LogFile and quit it
1702 activatefile logfid
1703 'xcom quit'
1704 activatefile curfid
1705 endif
1706 endif
1707 'e 'LogFile
1708 endif
1709
1710; ---------------------------------------------------------------------------
1711; Calls ReadMacroLstFiles to get all basenames of all .lst files. If current
1712; basename is not found, it asks to add it. If yes, RecompileNew is executed.
1713; If no, Relink is exectued.
1714; This can be used as universal command by Run.
1715defc Recompile
1716 FileName = arg( 1)
1717 if FileName = '' then
1718 FileName = .filename
1719 endif
1720
1721 lp1 = lastpos( '\', FileName)
1722 lp2 = lastpos( '.', FileName)
1723 if upcase( substr( FileName, lp2)) <> '.E' then
1724 sayerror '"'FileName'" is not an .E file'
1725 return
1726 endif
1727 BaseName = lowcase( substr( FileName, lp1 + 1, Max( 0, lp2 - lp1 - 1)))
1728
1729 Path = Get_Env('EPMEXPATH')
1730 ListFiles = ''
1731 BaseNames = ReadMacroLstFiles( Path, ListFiles)
1732
1733 do once = 1 to 1
1734 fBaseNamePresent = 0
1735
1736 if pos( ';'BaseName';', ';'BaseNames';') then
1737 fBaseNamePresent = 1
1738 leave
1739 endif
1740
1741 -- Search BaseName'.e' in netlabs\macros
1742 NepmdRootDir = Get_Env('NEPMD_ROOTDIR')
1743 if Exist( NepmdRootDir'\netlabs\macros\'BaseName'.e') then
1744 fBaseNamePresent = 1
1745 leave
1746 endif
1747
1748 -- Ask to add BaseName to myexfiles.lst
1749 Title = 'Recompile'
1750 Text = ''
1751 Text = Text || BaseName\n\n
1752 Text = Text || 'The current file was not found in a .LST file.'\n\n
1753 Text = Text || 'Should it be added to MYEXFILES.LST?'
1754 rcx = WinMessageBox( Title, Text,
1755 MB_YESNOCANCEL + MB_QUERY + MB_DEFBUTTON1 + MB_MOVEABLE)
1756 if rcx = MBID_YES then
1757 AddToMacroLstFile( BaseName)
1758 if not rc then
1759 fBaseNamePresent = 1
1760 endif
1761 elseif rcx = MBID_NO then
1762 -- nop
1763 else
1764 return
1765 endif
1766 enddo
1767
1768 if fBaseNamePresent then
1769 'RecompileNew'
1770 else
1771 'Relink'
1772 endif
1773
Note: See TracBrowser for help on using the repository browser.