PmProject.icl 37.4 KB
Newer Older
Diederik van Arkel's avatar
Diederik van Arkel committed
1
2
implementation module PmProject

3
import StdClass,StdBool,StdInt,StdString,StdArray,StdFunc,StdTuple,StdList,StdStrictLists
Diederik van Arkel's avatar
Diederik van Arkel committed
4
import StdMaybe
5
from StdOverloadedList import ++|,Hd
Diederik van Arkel's avatar
Diederik van Arkel committed
6
import PmPath, UtilStrictLists
7
from UtilDate import NoDate, :: DATE
Diederik van Arkel's avatar
Diederik van Arkel committed
8
9
10
import UtilNewlinesFile
import PmTypes
import Platform
11
import UtilOptions, PmFiles
Diederik van Arkel's avatar
Diederik van Arkel committed
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

::	Def_and_Imp				:== Bool;
DclMod					:== True;
IclMod					:== False;

::	WindowOpen_and_Closed	:== Bool;
WinOpen					:== True;
WinClosed				:== False;
	
::	Modification			:== Bool;
Modified				:== True;
Unmodified				:== False;

//	The Project: A list of constituent modules and their mutual dependencies

::	Project	=
	{ built						:: !Bool					// Was dependency list generated?
	, saved						:: !Bool
	, exec						:: !Bool					// exe linked ok?
	, inflist					:: !InfList					// list with constituent modules
	, codegenopt				:: !CodeGenOptions			// code generator options
	, code_gen_options_unchanged :: !Bool
	, applicationopt			:: !ApplicationOptions		// application options
	, linkOptions				:: !LinkOptions
	, prjpaths					:: !List String				// project paths
	, staticLibInfo				:: !StaticLibInfo
	, target					:: !String					// environment

	, dynamic_info				:: !ProjectDynamicInfo

42
43
	, relative_root_directory	:: !String			// string of '.'s, relative to .prj file
	, root_directory			:: !String
Diederik van Arkel's avatar
Diederik van Arkel committed
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
	, execpath					:: !String			// move to app_opts
	, prec						:: !Maybe String	// " (precompile command)
	, posl						:: !Maybe String	// " (postlink command)
	}

//	First element of InfList (if any) is the root module.

::	InfList		:==	List InfListItem
	
::	InfListItem	=
	{ mn	:: !Modulename		// module name
	, info	:: !ModInfo			// module info
	, src	:: !Bool			// src up to date?
	, abc	:: !Bool 			// abc up to date?
	}

60
::	InfUpdate 	:== InfListItem -> (!InfListItem, Bool)
Diederik van Arkel's avatar
Diederik van Arkel committed
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

PR_InitProject :: Project;
PR_InitProject =
	{ built				= True
	, saved				= True
	, exec				= True
	, execpath			= EmptyPathname
	, inflist			= Nil
	, codegenopt		= DefCodeGenOptions
	, code_gen_options_unchanged	= True
	, applicationopt	= DefApplicationOptions
	, linkOptions		= DefaultLinkOptions
	, prjpaths			= Nil
	, staticLibInfo		= DefStaticLibInfo
	, target			= ""
	, dynamic_info		= EmptyDynamicInfo
77
78
	, relative_root_directory = "."
	, root_directory = ""
Diederik van Arkel's avatar
Diederik van Arkel committed
79
80
81
82
	, prec = Nothing
	, posl = Nothing
	}

83
PR_GetExecPath	:: !Project -> String
Diederik van Arkel's avatar
Diederik van Arkel committed
84
85
PR_GetExecPath {execpath} = execpath

86
PR_SetExecPath	:: !String !Project -> Project
Diederik van Arkel's avatar
Diederik van Arkel committed
87
88
89
90
91
92
93
94
95
96
97
98
99
100
PR_SetExecPath pth prj = {prj & execpath = pth}

DefStaticLibInfo =
	{ sLibs = Nil
	, sDcls = Nil
	, sDeps = Nil
	}

PR_ProjectSet :: !Project -> Bool;
PR_ProjectSet project=:{inflist=Nil}	=  False;
PR_ProjectSet project=:{inflist}		=  True;

PR_NewProject :: !String !EditWdOptions !CompilerOptions !CodeGenOptions !ApplicationOptions
				!(List String) !LinkOptions -> Project;
101
102
103
104
PR_NewProject main_module_file_name eo compilerOptions cgo ao prjpaths linkOptions
	# modname	= GetModuleName main_module_file_name;
	  dirname	= RemoveFilename main_module_file_name;
	= { PR_InitProject
Diederik van Arkel's avatar
Diederik van Arkel committed
105
106
107
108
	& built			= False
	, saved			= False
	, exec			= False
	, execpath		= PlatformDependant	//MakeExecPathname main_module_file_name
109
110
						("{Project}"+++DirSeparatorString+++modname+++".exe")		// Win
						("{Project}"+++DirSeparatorString+++modname)				// Mac
Diederik van Arkel's avatar
Diederik van Arkel committed
111
112
113
114
	, inflist		=
		{ mn		= modname
		, info		=	{ dir		= "{Project}"//dirname
						, compilerOptions		= compilerOptions
115
						, mod_edit_options = {defeo=eo,impeo=eo,defopen=False,impopen=True}
Diederik van Arkel's avatar
Diederik van Arkel committed
116
117
118
119
120
121
122
123
124
125
126
127
						, abcLinkInfo = {linkObjFileNames = Nil, linkLibraryNames = Nil}
						}
		, src		= True
		, abc		= True
		} :! Nil
	, codegenopt	= cgo
	, code_gen_options_unchanged	= True
	, applicationopt= ao
	, prjpaths		= if (StringOccurs dirname prjpaths) prjpaths (dirname:!prjpaths)
	, linkOptions	= linkOptions
	, staticLibInfo = DefStaticLibInfo
	, target		= "StdEnv"
128
	, root_directory = dirname
Diederik van Arkel's avatar
Diederik van Arkel committed
129
130
131
	}

PR_SetBuilt	:: !(List Modulename) !.Project -> .Project;
132
133
PR_SetBuilt used project=:{inflist=Nil}
	= {Project | project & built = True};
Diederik van Arkel's avatar
Diederik van Arkel committed
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
PR_SetBuilt used prj=:{inflist=infl=:(root:!rest),saved}
	#! len		= LLength rest
	# used		= Map GetModuleName used
	# rest		= RemoveUnusedModules used rest
	# len`		= LLength rest
	# unchanged	= len == len`
	= {prj & built=True,saved=saved && unchanged,inflist= root:!rest}
where	
	{mn=rootmn,info} = root
	RemoveUnusedModules used list = FilterR member list
	where
		member {mn}	= StringOccurs mn used && rootmn <> mn

PR_AddABCInfo :: !String !(List LinkObjFileName) !(List LinkLibraryName) !CompilerOptions !EditWdOptions !EditWdOptions !Project -> Project
PR_AddABCInfo mod_path dep_objects dep_libraries compilerOptions defeo impeo project=:{inflist=Nil}
	= project
PR_AddABCInfo mod_path dep_objects dep_libraries compilerOptions defeo impeo project=:{inflist}
	# inflist		= TryInsertInList mod_name mod_dir inflist
	# (inflist,_)	= UpdateList mod_name update inflist;
	= {project & saved=False,inflist=inflist, built=False}
where
	mod_name			= GetModuleName mod_path
	mod_dir				= RemoveFilename mod_path

	update infListItem=:{InfListItem | info}
		= (	{ InfListItem | infListItem
			& info.abcLinkInfo.linkObjFileNames		= dep_objects
			, info.abcLinkInfo.linkLibraryNames		= dep_libraries
			, info.dir								= mod_dir
			, info.compilerOptions					= compilerOptions
			}, True)

166
	TryInsertInList :: !String !String !InfList -> InfList
Diederik van Arkel's avatar
Diederik van Arkel committed
167
168
169
170
171
172
173
174
175
	TryInsertInList importermn importerdir Nil	// no root module...
		= Nil
	TryInsertInList importermn importerdir ((root=:{mn,info}):!rest)
		| importermn == mn	// updating root module...
			# root	= {InfListItem | root & info = {ModInfo | info & dir = importerdir}}
			= root :! rest
		# rest		= TryInsertImporter rest rest
		= root :! rest
	where
176
		TryInsertImporter ::	!InfList !InfList -> InfList
Diederik van Arkel's avatar
Diederik van Arkel committed
177
		TryInsertImporter Nil list
178
			# default_edit_options = {pos_size = NoWindowPosAndSize, eo = {newlines= HostNativeNewlineConvention}}
Diederik van Arkel's avatar
Diederik van Arkel committed
179
180
181
			# item =
				  {	mn		= importermn, 
					info	= { dir		= importerdir,
182
183
184
								compilerOptions = compilerOptions,
								mod_edit_options = {defeo = default_edit_options,impeo = default_edit_options,
													defopen = False, impopen = False},
Diederik van Arkel's avatar
Diederik van Arkel committed
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
								abcLinkInfo = {linkObjFileNames = Nil, linkLibraryNames = Nil} },
					src		= True,
					abc		= True }
			= item :! list
		TryInsertImporter (({mn}):!rest) list
			| importermn<>mn
				= TryInsertImporter rest list
				= list

PR_ClearDependencies :: !Project -> Project
PR_ClearDependencies project=:{inflist=Nil}
	= {project & saved = False, inflist = Nil, built = False}
PR_ClearDependencies project=:{inflist=il=:(root :! rest)}
	= {project & saved = False, inflist = root` :! Nil, built = False}
where
200
201
	root` = {InfListItem | root & info.abcLinkInfo = {linkObjFileNames = Nil, linkLibraryNames = Nil}}

Diederik van Arkel's avatar
Diederik van Arkel committed
202
203
204
205
206
207
208
209
210
211
PR_SetRoot :: !String !EditWdOptions !CompilerOptions !Project -> Project;
PR_SetRoot root eo co project=:{inflist=Nil}
	= project;
PR_SetRoot newroot eo compilerOptions project=:{prjpaths}
	=	{project &	saved	= False,
					built	= False,
					exec	= False,
					inflist	= {	mn		= modname,
								info	= {	dir		= dirname,
											compilerOptions		= compilerOptions,
212
213
214
215
											mod_edit_options = {defeo = eo,impeo = eo,
																impopen = True,
																defopen = False	/* nonsense, we don't know this! */
															   },
Diederik van Arkel's avatar
Diederik van Arkel committed
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
											abcLinkInfo = {linkObjFileNames = Nil, linkLibraryNames = Nil} },
								src		= True,
								abc		= True
								} :! Nil,
					prjpaths= if (StringOccurs dirname prjpaths) prjpaths (dirname:!prjpaths) /* a bit iffy */
		  };
where 
	modname	= GetModuleName newroot;
	dirname	= RemoveFilename newroot;

PR_SetCompiled	:: !Modulename !Project -> Project;
PR_SetCompiled modname project=:{inflist}
	=  {project & inflist = inf`}
where 
	(inf`, _)	= UpdateList modname setcompiled inflist;
	
	setcompiled	:: !InfListItem -> (!InfListItem,!Bool);
	setcompiled itm=:{src,abc}
		= ({itm & src = True},True);
	
		
PR_SetCodeGenerated	:: !Modulename !Project -> Project;
PR_SetCodeGenerated modname project=:{inflist}
	= {project & inflist = inf`};
where 
	(inf`,_)	= UpdateList modname setcode inflist;
	
	setcode :: !InfListItem -> (!InfListItem, !Bool);
	setcode itm=:{InfListItem | src}
		= ({InfListItem | itm & abc = True}, True);
	
	
PR_SetSysCodeGenerated :: !Project -> Project;
PR_SetSysCodeGenerated project = {project & code_gen_options_unchanged = True};
	
PR_SetLinked	:: !Project -> Project;
PR_SetLinked project=:{inflist}
	=  {project & exec = True};
	
PR_SetSaved	:: !Project -> Project;
PR_SetSaved project = {Project | project & saved = True};
		
PR_SetCodeGenOptions	:: !CodeGenOptions !Project -> Project;
PR_SetCodeGenOptions options project=:{inflist,saved,codegenopt,code_gen_options_unchanged} =
	{ project
	& inflist						= infl`
	, saved							= saved && unchanged
	, code_gen_options_unchanged	= code_gen_options_unchanged && cg_unchanged
	, codegenopt					= options
	}
where 
	(infl`,_)				= infl`_;
	infl`_ | cg_unchanged	= (inflist,True);
							= P_MapR setcode inflist;
	unchanged				= cg_unchanged;
	cg_unchanged			= options == codegenopt;
	
	setcode :: !InfListItem -> (!InfListItem, !Bool);
	setcode itm=:{InfListItem | src}
		= ({InfListItem | itm & abc = False}, True);
	
	
PR_SetApplicationOptions :: !ApplicationOptions !Project -> Project;
PR_SetApplicationOptions options project=:{saved,exec,applicationopt}
	= {project & applicationopt = options, exec = exec && unchanged,saved=saved && unchanged};
	where 
		unchanged	= eqAppOpts options applicationopt;

eqAppOpts :: !ApplicationOptions !ApplicationOptions -> Bool
eqAppOpts ao1 ao2
	=	ao1.hs == ao2.hs &&
		ao1.ss == ao2.ss &&
		ao1.em == ao2.em &&
		ao1.heap_size_multiple == ao2.heap_size_multiple &&
		ao1.initial_heap_size == ao2.initial_heap_size &&
		ao1.set == ao2.set &&
		ao1.sgc == ao2.sgc &&
		ao1.pss == ao2.pss &&
		ao1.marking_collection == ao2.marking_collection &&
		ao1.o == ao2.o &&
		ao1.fn == ao2.fn &&
		ao1.fs == ao2.fs &&
		ao1.write_stderr_to_file == ao2.write_stderr_to_file &&
		ao1.memoryProfiling == ao2.memoryProfiling &&
		ao1.memoryProfilingMinimumHeapSize == ao2.memoryProfilingMinimumHeapSize &&
		ao1.profiling == ao2.profiling &&
		ao1.stack_traces == ao2.stack_traces &&
		ao1.standard_rte == ao2.standard_rte

// do we need to check resource linking flags???
eqLinkOpts :: !LinkOptions !LinkOptions -> Bool
eqLinkOpts lo1 lo2 =
	lo1.method == lo2.method &&
	lo1.generate_relocations == lo2.generate_relocations &&
	lo1.generate_link_map == lo2.generate_link_map &&
	lo1.link_resources == lo2.link_resources &&
	(if lo1.link_resources (lo1.resource_source == lo2.resource_source) True) &&
	EQStrings (SortStrings lo1.extraObjectModules) (SortStrings lo2.extraObjectModules) &&
	EQStrings (SortStrings lo1.libraries) (SortStrings lo2.libraries) &&
	lo1.generate_dll == lo2.generate_dll &&
Diederik van Arkel's avatar
Diederik van Arkel committed
316
	lo1.dll_export_list_name == lo2.dll_export_list_name
Diederik van Arkel's avatar
Diederik van Arkel committed
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331

	
PR_SetLinkOptions	:: !Project !LinkOptions -> Project;
PR_SetLinkOptions project linkOptions
	| eqLinkOpts linkOptions project.Project.linkOptions
		=	{Project | project & linkOptions = linkOptions, saved = False};
	| otherwise
		=	{Project | project & linkOptions = linkOptions, exec = False, saved = False};

PR_GetLinkOptions	:: !Project -> LinkOptions;
PR_GetLinkOptions project
	=  project.Project.linkOptions;

PR_SetPaths	:: !Bool !(List String) !(List String) !Project -> Project;
PR_SetPaths def defs new project=:{Project | inflist=Nil} = project;
Diederik van Arkel's avatar
Diederik van Arkel committed
332
333
334
PR_SetPaths def defs new project=:{Project | built,inflist=infl=:((root=:{InfListItem | info={dir}}):!rest),prjpaths,saved}
	| def	= {Project | project &
							built				= built && olddirs,
Diederik van Arkel's avatar
Diederik van Arkel committed
335
336
							saved				= saved && olddirs,
							inflist				= inflist1 };
Diederik van Arkel's avatar
Diederik van Arkel committed
337
338
			= {Project | project &
							built 				= built && olddirs,
Diederik van Arkel's avatar
Diederik van Arkel committed
339
340
341
342
343
344
345
346
347
348
349
350
351
352
							saved				= saved && unchanged && olddirs,
							inflist				= inflist1,
							prjpaths			= prjpaths1 };
	where 
		(inflist1,olddirs)	= P_MapR SetDcl_and_Icl_and_ABCModified infl;
		unchanged			= EQStrings (SortStrings prjpaths) (SortStrings prjpaths1);
		prjpaths1 	| def	= prjpaths;
					| StringOccurs dir new
							= new;
							= dir:!new;
						
		SetDcl_and_Icl_and_ABCModified :: !InfListItem -> (!InfListItem,!Bool);
		SetDcl_and_Icl_and_ABCModified itm=:{InfListItem | info=minfo=:{dir}}
		| unchanged	= ({itm & src=False}, True);
353
					= ({itm & info = {minfo & dir=""}, src=False},False);
Diederik van Arkel's avatar
Diederik van Arkel committed
354
355
356
357
358
359
			where 
				unchanged	= StringOccurs dir defs || StringOccurs dir prjpaths1;
			
		
		
PR_GetCodeGenOptions :: !Project -> CodeGenOptions;
360
PR_GetCodeGenOptions {codegenopt} =  codegenopt;
Diederik van Arkel's avatar
Diederik van Arkel committed
361

362
363
//PR_GetProcessor :: !Project -> Processor;
//PR_GetProcessor project=:{codegenopt={tp}} = tp;
Diederik van Arkel's avatar
Diederik van Arkel committed
364
365
	
PR_GetApplicationOptions :: !Project -> ApplicationOptions;
366
367
PR_GetApplicationOptions {applicationopt} =  applicationopt;

Diederik van Arkel's avatar
Diederik van Arkel committed
368
PR_GetPaths	:: !Project -> List String;
369
PR_GetPaths {Project | prjpaths} = prjpaths;
Diederik van Arkel's avatar
Diederik van Arkel committed
370
371

PR_GetRootModuleName :: !Project -> String
372
PR_GetRootModuleName {inflist=Nil}
Diederik van Arkel's avatar
Diederik van Arkel committed
373
	= EmptyPathname
374
PR_GetRootModuleName {inflist={mn}:!rest}
Diederik van Arkel's avatar
Diederik van Arkel committed
375
376
	= mn

377
PR_GetRootPathName	:: !Project -> (!String,!Project)
Diederik van Arkel's avatar
Diederik van Arkel committed
378
379
380
381
382
383
384
PR_GetRootPathName p=:{inflist=Nil}
	= (EmptyPathname,p)
PR_GetRootPathName p=:{inflist={mn,info={dir}}:!rest}
	| size dir==0
		= (EmptyPathname,p)
		= (MakeFullPathname dir (MakeImpPathname mn),p)

385
386
PR_GetRootModuleDir	:: !Project -> String
PR_GetRootModuleDir {inflist=Nil}
Diederik van Arkel's avatar
Diederik van Arkel committed
387
	= EmptyPathname;
388
PR_GetRootModuleDir {inflist={mn,info={dir}}:!rest}
Diederik van Arkel's avatar
Diederik van Arkel committed
389
390
391
392
	| size dir==0
		= EmptyPathname;
		= dir;

393
394
395
396
397
398
399
400
PR_GetRootDir :: !Project -> String
PR_GetRootDir {root_directory}
	= root_directory;

PR_GetRelativeRootDir :: !Project -> String
PR_GetRelativeRootDir {relative_root_directory}	
	= relative_root_directory

Diederik van Arkel's avatar
Diederik van Arkel committed
401
402
403
404
PR_GetModulenames	:: !Bool !Def_and_Imp !Project -> (List String,Project)
PR_GetModulenames full def project=:{inflist}
	= (modnames,project)
where 
405
	modnames	= MapR GetModulenames inflist
Diederik van Arkel's avatar
Diederik van Arkel committed
406
	
407
	GetModulenames :: !InfListItem -> String
Diederik van Arkel's avatar
Diederik van Arkel committed
408
	GetModulenames {mn,info={dir}}
409
410
411
		| full && def	= MakeFullPathname dir (MakeDefPathname mn)
		| full			= MakeFullPathname dir (MakeImpPathname mn)
						= mn
Diederik van Arkel's avatar
Diederik van Arkel committed
412
413
414
415
416

PR_GetOpenModulenames	:: !Project -> List String
PR_GetOpenModulenames project=:{inflist}
	= FlattenList modnames
where 
417
418
419
	modnames = MapR GetModulenames inflist

	GetModulenames :: !InfListItem -> List String
420
	GetModulenames {mn,info={dir,mod_edit_options={defopen,impopen}}}
421
422
423
424
		| defopen && impopen	= defname :! impname :! Nil
		| defopen				= defname :! Nil
		| impopen				= impname :! Nil
								= Nil
Diederik van Arkel's avatar
Diederik van Arkel committed
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
	where
		defname = MakeFullPathname dir (MakeDefPathname mn)
		impname = MakeFullPathname dir (MakeImpPathname mn)

PR_GetModuleStuff :: !Project -> List (Modulename,String,Modulename,String)
PR_GetModuleStuff project=:{inflist}
	= stuff
where 
	(stuff,_)	= P_MapR GetModulenames inflist
	
	GetModulenames :: !InfListItem -> ((!Modulename,!String,!Modulename,!String),!Bool)
	GetModulenames {mn,info={dir}}
						= ((MakeDefPathname mn,dir,MakeImpPathname mn,dir),True)

PR_Built :: !Project -> Bool;
PR_Built project=:{Project | built} =  built;
		
PR_SrcUpToDate :: !Modulename !Project -> Bool;
PR_SrcUpToDate modname project=:{inflist}
	# item = FindInList modname inflist
	| isNothing item
		= False
	# item = fromJust item
	= item.src
449

Diederik van Arkel's avatar
Diederik van Arkel committed
450
451
452
453
454
455
456
PR_ABCUpToDate	:: !Modulename !Project -> Bool;
PR_ABCUpToDate modname project=:{inflist}
	# item = FindInList modname inflist
	| isNothing item
		= False
	# item = fromJust item
	= item.abc
457

Diederik van Arkel's avatar
Diederik van Arkel committed
458
459
460
461
462
463
464
465
466
467
468
469
470
471
PR_SysUptoDate :: !Project -> Bool;
PR_SysUptoDate project=:{code_gen_options_unchanged} = code_gen_options_unchanged;
	
PR_ExecUpToDate	:: !Project -> Bool;		
PR_ExecUpToDate project=:{exec} = exec;

PR_Saved :: !Project -> Bool;
PR_Saved {Project | saved} = saved;

PR_AddRootModule ::	!Bool !CodeGenOptions !ApplicationOptions !(List String) !LinkOptions
					!Modulename !ModInfo -> Project;
PR_AddRootModule built cg ao prjs linkOptions mn info=:{dir}
  = { PR_InitProject
  	& built			= built && dir <> ""
472
	, saved			= False
Diederik van Arkel's avatar
Diederik van Arkel committed
473
	, exec			= True
474
	, execpath		= ""
Diederik van Arkel's avatar
Diederik van Arkel committed
475
476
477
478
479
480
481
482
483
484
485
486
	, code_gen_options_unchanged
						= True
	, inflist			= root:!Nil
	, codegenopt		= cg
	, applicationopt	= ao
	, prjpaths		= prjs
	, linkOptions	= linkOptions
	, staticLibInfo = DefStaticLibInfo
	, target = ""
	};
where 
	root	= {	mn		= mn,info	= info,src		= True,abc		= True };
487

Diederik van Arkel's avatar
Diederik van Arkel committed
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
PR_AddModule :: !Modulename !ModInfo !Project -> Project;
PR_AddModule mn info=:{dir} project=:{built,inflist=root:!rest}
	= {project & built = built && dir<>"", inflist = root:!new:!rest};
where 
	new	= {	mn		= mn,
			info	= info,
			src		= True,
			abc		= True };
PR_AddModule mn info=:{dir} project=:{built,inflist=Nil}
	= {project & built = built && dir<>"", inflist = new:!Nil};
where 
	new	= {	mn		= mn,
			info	= info,
			src		= True,
			abc		= True };
	
504
PR_GetModuleInfo :: !Modulename !Project -> Maybe ModInfo
Diederik van Arkel's avatar
Diederik van Arkel committed
505
506
507
508
509
510
PR_GetModuleInfo mn {Project | inflist}
	# item = FindInList mn inflist
	| isNothing item
		= Nothing
	= Just (fromJust item).InfListItem.info
	
511
PR_UpdateModule :: !Modulename !(ModInfo -> ModInfo) !Project -> Project;
Diederik van Arkel's avatar
Diederik van Arkel committed
512
513
514
515
516
517
518
519
520
521
PR_UpdateModule mn update project=:{inflist,saved}
	= {project & inflist = infl`,saved = saved && unchanged};
where 
	(infl`,unchanged)	= UpdateList mn update` inflist;
	update` itm=:{InfListItem | info}	= ({InfListItem | itm & info = info`}, unchanged);
	where 
		info`		= update info;
		unchanged	= eqInfo info info`;

eqInfo :: !ModInfo !ModInfo -> Bool
522
523
524
eqInfo info1=:{mod_edit_options=mod_edit_options1} info2=:{mod_edit_options=mod_edit_options2}
	=	mod_edit_options1.defeo.eo == mod_edit_options2.defeo.eo &&
		mod_edit_options1.impeo.eo == mod_edit_options2.impeo.eo &&
Diederik van Arkel's avatar
Diederik van Arkel committed
525
		eqCO info1.compilerOptions info2.compilerOptions &&
526
527
528
529
		mod_edit_options1.defeo.pos_size == mod_edit_options2.defeo.pos_size && 
		mod_edit_options1.impeo.pos_size == mod_edit_options2.impeo.pos_size &&
		mod_edit_options1.defopen == mod_edit_options2.defopen &&
		mod_edit_options1.impopen == mod_edit_options2.impopen
Diederik van Arkel's avatar
Diederik van Arkel committed
530
531
532
533
534
535
536
537
538
539
540

eqCO :: !CompilerOptions !CompilerOptions -> Bool
eqCO co1 co2
	=	co1.neverTimeProfile == co2.neverTimeProfile &&
		co1.neverMemoryProfile == co2.neverMemoryProfile &&
		co1.sa == co2.sa &&
		co1.CompilerOptions.listTypes == co2.CompilerOptions.listTypes &&
		co1.gw == co2.gw &&
		co1.bv == co2.bv &&
		co1.gc == co2.gc
							
541
PR_UpdateModules :: ![Modulename] !(ModInfo -> ModInfo) !Project -> Project
Diederik van Arkel's avatar
Diederik van Arkel committed
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
PR_UpdateModules mn update project
	= seq [(PR_UpdateModule m update) \\ m <- mn] project	// DvA quick hack, not very efficient!

//	Operations on tables

UpdateList :: !String InfUpdate !InfList -> (!InfList,!Bool)
UpdateList key update list = UpdateList2 key update list Nil
where
	UpdateList2 :: !String InfUpdate !InfList !InfList -> (!InfList,!Bool)
	UpdateList2 key update Nil acc
		=  (Reverse2 acc Nil,True)
	UpdateList2 key update ((first=:{mn,info}):!rest) acc
		| mn <> key
			= UpdateList2 key update rest (first:!acc)
		# (first,changed)	= update first
		= (Reverse2 acc (first :! rest), changed)

559
FindInList	:: !String !InfList -> Maybe InfListItem
Diederik van Arkel's avatar
Diederik van Arkel committed
560
561
562
563
564
FindInList key Nil									= Nothing
FindInList key ((itm=:{mn,info}):!rest)	| mn <> key	= FindInList key rest
													= Just itm

SetProject :: !{#Char} !{#Char} !ProjectGlobalOptions -> Project
565
566
567
568
569
SetProject applicationDir project_file_dir
		{ pg_built, pg_codegen, pg_application
		, pg_projectPaths, pg_link, pg_mainModuleInfo={name, info}, pg_otherModules
		, pg_target, pg_staticLibInfo, pg_execpath, pg_dynamic
		, pg_root_directory, pg_precompile, pg_postlink
Diederik van Arkel's avatar
Diederik van Arkel committed
570
		}
571
572
573
574
575
576
577
	# project_dir = make_project_dir (size pg_root_directory) project_file_dir

	# paths = ExpandPaths applicationDir project_dir pg_projectPaths
	# linkOptions = ExpandLinkOptionsPaths applicationDir project_dir pg_link
	# project = PR_AddRootModule pg_built pg_codegen pg_application paths linkOptions name (ExpandModuleInfoPaths applicationDir project_dir info)
	# project		= addModules pg_otherModules project_dir project
	# staticLibInfo = ExpandStaticLibPaths applicationDir project_dir pg_staticLibInfo
Diederik van Arkel's avatar
Diederik van Arkel committed
578
579
	# project		= PR_SetStaticLibsInfo staticLibInfo project
	# project		= PR_SetTarget pg_target project
580
	# exepath		= ExpandPath applicationDir project_dir pg_execpath
Diederik van Arkel's avatar
Diederik van Arkel committed
581
582
	# project		= PR_SetExecPath exepath project
	// default of used appopts in exe are ok isn't right :-(
583
	# pg_postlink	= case pg_postlink of
584
							Just post_link -> Just (ExpandPath applicationDir project_dir post_link)
585
							Nothing -> Nothing
586
587
	= {project & relative_root_directory = pg_root_directory, root_directory = project_dir, dynamic_info = pg_dynamic,
				 prec = pg_precompile, posl = pg_postlink}
Diederik van Arkel's avatar
Diederik van Arkel committed
588
where
589
	addModules Nil project_dir project
Diederik van Arkel's avatar
Diederik van Arkel committed
590
		=	project
591
592
593
594
595
596
597
598
	addModules ({name, info} :! t) project_dir project
		=	addModules t project_dir (PR_AddModule name (ExpandModuleInfoPaths applicationDir project_dir info) project)

GetProject :: !{#Char} !Project -> ProjectGlobalOptions
GetProject applicationDir project
	# project_dir = project.root_directory
	  post_link = case project.posl of
					Just post_link -> Just (SubstitutePath applicationDir project_dir post_link)
599
					Nothing -> Nothing 
600
601
602
603
604
	  mainModuleInfo = getModule project_dir mainModuleName
	  otherModules = Map (getModule project_dir) (Filter ((<>) mainModuleName) otherModuleNames)
	  linkOptions = SubstituteLinkOptionsPaths applicationDir project_dir (PR_GetLinkOptions project)
	  projectPaths = SubstitutePaths applicationDir project_dir (PR_GetPaths project)
	  staticLibInfo = SubstituteStaticLibPaths applicationDir project_dir (PR_GetStaticLibsInfo project)
Diederik van Arkel's avatar
Diederik van Arkel committed
605
606
607
608
609
610
611
612
613
	=	{ pg_built				= PR_Built project
		, pg_codegen			= PR_GetCodeGenOptions project
		, pg_application		= PR_GetApplicationOptions project
		, pg_projectPaths		= projectPaths
		, pg_link				= linkOptions
		, pg_mainModuleInfo		= mainModuleInfo
		, pg_otherModules		= otherModules
		, pg_staticLibInfo		= staticLibInfo
		, pg_target				= target
614
		, pg_execpath			= exepath project_dir
Diederik van Arkel's avatar
Diederik van Arkel committed
615
		, pg_dynamic			= project.dynamic_info
616
		, pg_root_directory		= project.relative_root_directory
Diederik van Arkel's avatar
Diederik van Arkel committed
617
		, pg_precompile			= project.prec
618
		, pg_postlink			= post_link
Diederik van Arkel's avatar
Diederik van Arkel committed
619
620
		}
where
621
	exepath project_dir
Diederik van Arkel's avatar
Diederik van Arkel committed
622
		# xp	= PR_GetExecPath project
623
		= symPath applicationDir project_dir xp
624

Diederik van Arkel's avatar
Diederik van Arkel committed
625
626
	mainModuleName		=	PR_GetRootModuleName project
	(otherModuleNames,project`)	=	PR_GetModulenames False IclMod project
627
628

	getModule project_dir name
Diederik van Arkel's avatar
Diederik van Arkel committed
629
630
		# info = PR_GetModuleInfo name project
		# info = if (isJust info) (fromJust info) defaultModInfo
631
		# info = SubstituteModuleInfoPaths applicationDir project_dir info
Diederik van Arkel's avatar
Diederik van Arkel committed
632
		= {name = name, info = info}
633

Diederik van Arkel's avatar
Diederik van Arkel committed
634
635
636
637
	target				=	PR_GetTarget project

	defaultModInfo :: ModInfo
	defaultModInfo	=
638
639
640
641
		{ dir = EmptyPathname
		, compilerOptions = DefaultCompilerOptions
		, mod_edit_options = {	defeo = defaultEditWdOptions,impeo = defaultEditWdOptions,
								defopen = False,impopen = False}
Diederik van Arkel's avatar
Diederik van Arkel committed
642
643
644
		, abcLinkInfo = {linkObjFileNames = Nil, linkLibraryNames = Nil} 
		}
	where
645
		defaultEditWdOptions = {eo=DefaultEditOptions,pos_size=NoWindowPosAndSize}
Diederik van Arkel's avatar
Diederik van Arkel committed
646
647
648
649
650
651
652
653
654
655
656
657
		DefaultEditOptions =
			{ newlines = HostNativeNewlineConvention}
/*			{ tabs = 4
			, fontname = "Courier New"	//NonProportionalFontDef.fName
			, fontsize = 10				//NonProportionalFontDef.fSize
			, autoi = True
			, newlines = HostNativeNewlineConvention
			, showtabs = False
			, showlins = False
			, showsync = True
			} 
*/
658

659
660
661
662
663
664
665
666
667
make_project_dir :: !Int !{#Char} -> {#Char}
make_project_dir n_dots project_directory
	| n_dots>1
		# parent_of_project_directory = RemoveFilename project_directory
		| size parent_of_project_directory==size project_directory || size parent_of_project_directory==0
			= project_directory // error, not enough directories
			= make_project_dir (n_dots-1) parent_of_project_directory
		= project_directory

Diederik van Arkel's avatar
Diederik van Arkel committed
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
ExpandModuleInfoPaths :: {#Char} {#Char} ModInfo -> ModInfo
ExpandModuleInfoPaths applicationDir projectDir moduleInfo=:{dir}
	= {moduleInfo & dir = ExpandPath applicationDir projectDir dir}

ExpandLinkOptionsPaths :: {#Char} {#Char} LinkOptions -> LinkOptions
ExpandLinkOptionsPaths applicationDir projectDir linkOptions=:{extraObjectModules, libraries}
	=	{ linkOptions
		& extraObjectModules	= ExpandPaths applicationDir projectDir extraObjectModules
		, libraries				= ExpandPaths applicationDir projectDir libraries
		}

ExpandStaticLibPaths :: {#Char} {#Char} StaticLibInfo -> StaticLibInfo
ExpandStaticLibPaths applicationDir projectDir staticLibs=:{sLibs}
	=	{ staticLibs
		& sLibs = ExpandPaths applicationDir projectDir sLibs
		}

//ExpandPaths :: {#Char} {#Char} (List {#Char}) -> List {#Char}
ExpandPaths applicationDir projectDir list
	:== fulPaths applicationDir projectDir list

ExpandPath applicationDir projectDir path
	:== fulPath applicationDir projectDir path

SubstituteModuleInfoPaths :: {#Char} {#Char} ModInfo -> ModInfo
SubstituteModuleInfoPaths applicationDir projectDir info
	=	{info & dir = SubstitutePath applicationDir projectDir info.dir}

SubstituteLinkOptionsPaths :: {#Char} {#Char} LinkOptions -> LinkOptions
SubstituteLinkOptionsPaths applicationDir projectDir linkOptions=:{extraObjectModules, libraries}
	=	{linkOptions
		& extraObjectModules = SubstitutePaths applicationDir projectDir extraObjectModules
		, libraries = SubstitutePaths applicationDir projectDir libraries
		}

SubstituteStaticLibPaths :: {#Char} {#Char} StaticLibInfo -> StaticLibInfo
SubstituteStaticLibPaths applicationDir projectDir staticLibs=:{sLibs}
	=	{ staticLibs
		& sLibs = SubstitutePaths applicationDir projectDir sLibs
		}

//SubstitutePaths :: {#Char} {#Char} (List {#Char}) -> List {#Char}
SubstitutePaths applicationDir projectDir list
	:== symPaths applicationDir projectDir list

SubstitutePath applicationDir projectDir path
	:== symPath applicationDir projectDir path

716
PR_GetABCLinkInfo	:: !Project -> ABCLinkInfo;
Diederik van Arkel's avatar
Diederik van Arkel committed
717
718
719
720
721
722
723
724
725
726
727
728
PR_GetABCLinkInfo project=:{inflist}
	#	allLinkInfoRecords	= map (\{InfListItem | info={abcLinkInfo}} -> abcLinkInfo) (StrictListToList inflist);
		oneLinkInfoRecord	= foldl mergeTwoRecords emptyRecord allLinkInfoRecords;
	= oneLinkInfoRecord;
where
		mergeTwoRecords { linkObjFileNames=linkObjFileNames1, linkLibraryNames=linkLibraryNames1}
						{ linkObjFileNames=linkObjFileNames2, linkLibraryNames=linkLibraryNames2}
			= { linkObjFileNames	= UnionStringList linkObjFileNames2 linkObjFileNames1,
				linkLibraryNames	= UnionStringList linkLibraryNames2 linkLibraryNames1};
		emptyRecord
			= { linkObjFileNames = Nil, linkLibraryNames	= Nil};

729
PR_GetStaticLibsInfo :: !Project -> StaticLibInfo
Diederik van Arkel's avatar
Diederik van Arkel committed
730
731
732
733
734
735
PR_GetStaticLibsInfo {Project | staticLibInfo} = staticLibInfo

PR_SetStaticLibsInfo :: !StaticLibInfo !Project -> Project
PR_SetStaticLibsInfo staticLibInfo project
	= {Project | project & staticLibInfo = staticLibInfo}

736
PR_GetTarget :: !Project -> String
Diederik van Arkel's avatar
Diederik van Arkel committed
737
738
739
PR_GetTarget {Project | target} = target

PR_SetTarget :: !String !Project -> Project
Diederik van Arkel's avatar
Diederik van Arkel committed
740
741
742
743
PR_SetTarget target project
	| target == project.Project.target
		= project
		= {Project | project & target = target, exec = False, saved = False}
Diederik van Arkel's avatar
Diederik van Arkel committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778

SL_Add :: !String !StaticLibInfo -> StaticLibInfo
SL_Add pathname sl
	// load sDcls and sDeps info...
	// read some kind of libdef file...
	= {sl & sLibs = Append sl.sLibs pathname}

SL_Rem :: ![String] !String !String !StaticLibInfo -> StaticLibInfo
SL_Rem pathsel ap pp sl
	// remove sDcls and sDeps...
	= {sl & sLibs = seq
		[ RemoveStringFromList (fulPath ap pp s)
		\\ s <- pathsel
		] sl.sLibs}

SL_Libs :: !StaticLibInfo -> List String
SL_Libs sl=:{sLibs} = sLibs

SL_Dcls :: !StaticLibInfo -> List String
SL_Dcls sl=:{sDcls} = sDcls

SL_Deps :: !StaticLibInfo -> List String
SL_Deps sl=:{sDeps} = sDeps

SL_SetLibs :: !(List String) !StaticLibInfo -> StaticLibInfo
SL_SetLibs lp sl = {sl & sLibs = lp}

SL_SetDcls :: !(List String) !StaticLibInfo -> StaticLibInfo
SL_SetDcls lp sl = {sl & sDcls = lp}

SL_SetDeps :: !(List String) !StaticLibInfo -> StaticLibInfo
SL_SetDeps lp sl = {sl & sDeps = lp}

SaveProjectFile	:: !String !Project !String !*Files -> (!Bool, !*Files);
SaveProjectFile	projectPath project applicationDir files
779
	# (opened, prj_file, files) = fopen projectPath FWriteText files
Diederik van Arkel's avatar
Diederik van Arkel committed
780
781
	| not opened
		=	(False, files)
782
783
784
785
786
787
788
789
790
791
792
793
794
	# prp_path = RemoveSuffix` projectPath +++ ".prp"
	# (opened, prp_file, files) = fopen prp_path FWriteText files
	| not opened
		# (_,files) = fclose prj_file files
		=	(False, files)
	#! projectGO				= GetProject applicationDir project
	# projectGO = sort_modules projectGO
	# prj_file = WriteOptionsFile ProjectFileVersion (PutOptions project_table projectGO) prj_file
	# prp_file = WriteOptionsFile ProjectFileVersion (PutOptions edit_options_table projectGO) prp_file
	#! (prj_ok, files) = fclose prj_file files
	#! (prp_ok, files) = fclose prp_file files
	= (prj_ok && prp_ok, files)

795
796
797
798
799
800
801
802
803
804
805
save_project_template_file :: !String !Project !String !*Files -> (!Bool, !*Files);
save_project_template_file projectPath project applicationDir files
	# (opened, prt_file, files) = fopen projectPath FWriteText files
	| not opened
		=	(False, files)
	#! projectGO = GetProject applicationDir project
	#! main_module_dir_path = projectGO.pg_mainModuleInfo.ModInfoAndName.info.dir
	# projectGO = {projectGO & pg_projectPaths = [|p \\ p<|-projectGO.pg_projectPaths | p<>main_module_dir_path]}
	# prt_file = WriteOptionsFile ProjectFileVersion (PutOptions project_template_table projectGO) prt_file
	= fclose prt_file files

806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
sort_modules :: !ProjectGlobalOptions -> ProjectGlobalOptions
sort_modules projectGO=:{pg_projectPaths,pg_otherModules}
	# project_paths = {project_path \\ project_path<|-pg_projectPaths}
	# n_project_paths = size project_paths
	# (project_modules,other_modules) = collect_project_modules pg_otherModules (createArray n_project_paths [!!]) project_paths
	# pg_otherModules = append_project_modules 0 project_modules other_modules
	= {projectGO & pg_otherModules=pg_otherModules}
  where
	collect_project_modules :: ![!ModInfoAndName!] !*{![!ModInfoAndName!]} !{#Pathname} -> (!*{![!ModInfoAndName!]},![!ModInfoAndName!])
	collect_project_modules [!mod=:{ModInfoAndName|info={dir}}:mods!] project_modules project_paths
		# path_index = find_path dir 0 project_paths
		| path_index>=0
			# (modules_in_dir,project_modules) = project_modules![path_index]
			# project_modules = {project_modules & [path_index] = [!mod:modules_in_dir!]}
			= collect_project_modules mods project_modules project_paths
			# (project_modules,other_modules) = collect_project_modules mods project_modules project_paths
			= (project_modules,[!mod:other_modules!])
	collect_project_modules [!!] project_modules project_paths
		= (project_modules,[!!])

	find_path :: !{#Char} !Int !{#{#Char}} -> Int
	find_path dir i project_paths
		| i<size project_paths
			| project_paths.[i]==dir
				= i
				= find_path dir (i+1) project_paths
			= -1

	append_project_modules :: !Int !{![!ModInfoAndName!]} [!ModInfoAndName!] -> [!ModInfoAndName!]
	append_project_modules i project_modules other_modules
		| i<size project_modules
			= sort_by_name project_modules.[i] ++| append_project_modules (i+1) project_modules other_modules
			= sort_by_dir_and_name other_modules

	sort_by_name :: !u:[!ModInfoAndName!] -> u:[!ModInfoAndName!]
	sort_by_name l = Hd (msort (pair l)) // mergesort
	  where
		pair [|x1,x2:xs]
			| x2.name < x1.name
				= [[|x2,x1]:pair xs];
				= [[|x1,x2]:pair xs];
		pair x = [|x];

		msort [|x1,x2:xs] = msort (merge_stage [|x1,x2:xs]);
		msort x	= x;

		merge_stage [|xs1,xs2:xxs] = [|merge xs1 xs2 : merge_stage xxs];
		merge_stage x = x;
	
		merge :: !u:[!ModInfoAndName!] !v:[!ModInfoAndName!] -> w:[!ModInfoAndName!], [u v <= w];
		merge [|] y = y
		merge f=:[|x:xs] [|] = f
		merge f=:[|x:xs] s=:[|y:ys]
			| y.name < x.name
				= [|y:merge f ys]
				= [|x:merge xs s]

	sort_by_dir_and_name :: !u:[!ModInfoAndName!] -> u:[!ModInfoAndName!]
	sort_by_dir_and_name l = Hd (msort (pair l)) // mergesort
	  where
		pair [|x1,x2:xs]
			| x2.ModInfoAndName.info.dir == x1.ModInfoAndName.info.dir
				| x2.name < x1.name
					= [[|x2,x1]:pair xs];
					= [[|x1,x2]:pair xs];
				| x2.ModInfoAndName.info.dir < x1.ModInfoAndName.info.dir
					= [[|x2,x1]:pair xs];
					= [[|x1,x2]:pair xs];
		pair x = [|x];

		msort [|x1,x2:xs] = msort (merge_stage [|x1,x2:xs]);
		msort x	= x;

		merge_stage [|xs1,xs2:xxs] = [|merge xs1 xs2 : merge_stage xxs];
		merge_stage x = x;
	
		merge :: !u:[!ModInfoAndName!] !v:[!ModInfoAndName!] -> w:[!ModInfoAndName!], [u v <= w];
		merge [|] y = y
		merge f=:[|x:xs] [|] = f
		merge f=:[|x:xs] s=:[|y:ys]
			| y.ModInfoAndName.info.dir == x.ModInfoAndName.info.dir
				| y.name < x.name
					= [|y:merge f ys]
					= [|x:merge xs s]
				| y.ModInfoAndName.info.dir < x.ModInfoAndName.info.dir
					= [|y:merge f ys]
					= [|x:merge xs s]
Diederik van Arkel's avatar
Diederik van Arkel committed
893

894
895
896
ReadProjectFile	:: !String !String !*Files -> (!(!Project, !Bool, !{#Char}),!*Files)
ReadProjectFile projectPath applicationDir files
	#	(opened, file, files)	= fopen projectPath FReadData files
Diederik van Arkel's avatar
Diederik van Arkel committed
897
898
899
900
		emptyProject			= PR_InitProject
		projectName				= RemovePath projectPath
		projectDir				= RemoveFilename projectPath
	| not opened
901
		= ((emptyProject,False,"The file \"" +++  projectName +++ "\" could not be opened."),files)
Diederik van Arkel's avatar
Diederik van Arkel committed
902
903
	#	(version, file)			= ReadVersion file
	| version == ""
904
905
		#	(_, files)			= fclose file files
		=	((emptyProject,False,"The file \"" +++  projectName +++ "\" is an old project and could not be opened."),files)
Diederik van Arkel's avatar
Diederik van Arkel committed
906
	#!	(options, file)			= ReadOptionsFile file
907
908
909
910
		empty_projectGO			= GetProject applicationDir emptyProject
		projectGO				= GetOptions ProjectTable options empty_projectGO
		(projectGO,files)
			= add_edit_options_from_prp_file (RemoveSuffix` projectPath +++ ".prp") projectGO empty_projectGO files
911
		projectGO				= (if (version == "1.3")
Diederik van Arkel's avatar
Diederik van Arkel committed
912
913
									(\p->{p&pg_target="StdEnv"})
									(id)
914
915
916
								) projectGO	// DvA: need to set needs save flag for project;
		unexpanded_exec_path	= projectGO.pg_execpath
		project					= SetProject applicationDir projectDir projectGO
Diederik van Arkel's avatar
Diederik van Arkel committed
917
918
		execpath				= PR_GetExecPath project
		(rootpath,project)		= PR_GetRootPathName project
919
		project					= PR_SetExecPath (if (size unexpanded_exec_path==0) (MakeExecPathname rootpath) execpath) project
920
		(closed, files)			= fclose file files
Diederik van Arkel's avatar
Diederik van Arkel committed
921
922
	| not closed
		// generate warning?
923
924
925
		=	((project, True,"The file \"" +++ projectName +++ "\" could not be closed."), files)
	=	((project, True,""), files)

926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
read_project_template_file :: !String !String !*Files -> (!(!Bool, !Project, !{#Char}),!*Files)
read_project_template_file template_file_path applicationDir files
	# (opened, file, files)	= fopen template_file_path FReadData files
	  empty_project = PR_InitProject
	  template_file_name = RemovePath template_file_path
	  template_file_dir = RemoveFilename template_file_path
	| not opened
		= ((False,empty_project,"The file \"" +++  template_file_name +++ "\" could not be opened."),files)
	# (version, file) = ReadVersion file
	| size version==0
		# (_, files) = fclose file files
		= ((False,empty_project,"The file \"" +++  template_file_name +++ "\" is not a project template and could not be opened."),files)
	# (options, file) = ReadOptionsFile file
	  empty_projectGO = GetProject applicationDir empty_project
	  projectGO = GetOptions project_template_table options empty_projectGO
	  project = SetProject applicationDir template_file_dir projectGO
	  (closed, files) = fclose file files
	| not closed
		= ((False,empty_project,"Could not read the file \"" +++ template_file_name +++ "\"."), files)
	= ((True,project,""), files)

947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
add_edit_options_from_prp_file :: !String !ProjectGlobalOptions !ProjectGlobalOptions !*Files -> (!ProjectGlobalOptions, !*Files)
add_edit_options_from_prp_file prp_path projectGO empty_projectGO files
	# (opened, prp_file, files) = fopen prp_path FReadData files
	| not opened
		= (projectGO, files)
	# (version, prp_file) = ReadVersion prp_file
	| size version==0
		= (projectGO, files)
	# (options,prp_file) = ReadOptionsFile prp_file
	#! edit_projectGO = GetOptions ProjectTable options empty_projectGO
	# (closed, files) = fclose prp_file files
	| not closed
		= (projectGO, files)
		# projectGO = add_edit_options edit_projectGO projectGO
		= (projectGO, files)

add_edit_options :: !ProjectGlobalOptions !ProjectGlobalOptions -> ProjectGlobalOptions
add_edit_options {pg_mainModuleInfo,pg_otherModules} projectGO
	#! edit_options = pg_mainModuleInfo.ModInfoAndName.info.mod_edit_options
	# other_modules = add_edit_options_of_other_modules pg_otherModules projectGO.pg_otherModules
	= {projectGO & pg_mainModuleInfo.ModInfoAndName.info.mod_edit_options = edit_options, pg_otherModules = other_modules}
  where
	add_edit_options_of_other_modules (m=:{name,info}:!mods_edit_options) (mod:!mods)
		// the IDE saves the modules in the .prj and .prp files in the same order
		| mod.ModInfoAndName.name==name && mod.ModInfoAndName.info.dir==info.dir
			# mod = {mod & ModInfoAndName.info.mod_edit_options = info.mod_edit_options}
			  mods = add_edit_options_of_other_modules mods_edit_options mods
			= mod:!mods
			// slow version in case the .prj and .prp file were not saved together 
			# mods = add_edit_options_of_other_module m mods
			= add_edit_options_of_other_modules mods_edit_options (mod:!mods)
	add_edit_options_of_other_modules mods_edit_options Nil
		= mods_edit_options
	add_edit_options_of_other_modules Nil mods
		= mods

	add_edit_options_of_other_module m=:{name,info} (mod:!mods)
		| mod.ModInfoAndName.name==name && mod.ModInfoAndName.info.dir==info.dir
			= {mod & ModInfoAndName.info.mod_edit_options = info.mod_edit_options} :! mods
			= mod :! add_edit_options_of_other_module m mods
	add_edit_options_of_other_module m Nil
	 	= m:!Nil

990
991
992
change_root_directory_of_project :: !{#Char} !{#Char} !Project -> Project 
change_root_directory_of_project relative_root_dir root_dir project
	= {project & relative_root_directory=relative_root_dir, root_directory=root_dir}
Diederik van Arkel's avatar
Diederik van Arkel committed
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010

getDynamicInfo :: !Project -> (ProjectDynamicInfo,Project)
getDynamicInfo prj=:{dynamic_info} = (dynamic_info,prj)

setDynamicInfo :: !.ProjectDynamicInfo !.Project -> .Project
setDynamicInfo inf prj = {prj & dynamic_info = inf}

PR_SetPrecompile	:: !(Maybe String) !Project -> Project
PR_SetPrecompile prec prj = {prj & prec = prec}

PR_GetPrecompile	:: !Project -> (!Maybe String, !Project)
PR_GetPrecompile prj=:{prec} = (prec,prj)

PR_SetPostlink		:: !(Maybe String) !Project -> Project
PR_SetPostlink posl prj = {prj & posl = posl}

PR_GetPostlink		:: !Project -> (!Maybe String, !Project)
PR_GetPostlink prj=:{posl} = (posl,prj)