]> git.zerfleddert.de Git - micropolis/blame - src/tclx/tclsrc/install.tcl
don't wreck ships when disasters are disabled
[micropolis] / src / tclx / tclsrc / install.tcl
CommitLineData
6a5fa4e0
MG
1#
2# installTcl.tcl --
3#
4# Tcl program to install Tcl onto the system.
5#
6#------------------------------------------------------------------------------
7# Copyright 1992 Karl Lehenbauer and Mark Diekhans.
8#
9# Permission to use, copy, modify, and distribute this software and its
10# documentation for any purpose and without fee is hereby granted, provided
11# that the above copyright notice appear in all copies. Karl Lehenbauer and
12# Mark Diekhans make no representations about the suitability of this
13# software for any purpose. It is provided "as is" without express or
14# implied warranty.
15#------------------------------------------------------------------------------
16# $Id: installTcl.tcl,v 2.0 1992/10/16 04:52:08 markd Rel $
17#------------------------------------------------------------------------------
18#
19# It is run in the following manner:
20#
21# tcl installTcl.tcl
22#
23# This script reads the Extended Tcl Makefile confiugation file (Config.mk)
24# and converts the Makefile macros in Tcl variables that control the
25# installation. The following variables are currently used:
26#
27# TCL_UCB_DIR TCL_DEFAULT TCL_OWNER
28# TCL_GROUP TCL_BINDIR TCL_LIBDIR
29# TCL_INCLUDEDIR TCL_TCLDIR TCL_MAN_INSTALL
30# TCL_MAN_BASEDIR TCL_MAN_CMD_SECTION TCL_MAN_FUNC_SECTION
31# TK_MAN_CMD_SECTION TK_MAN_FUNC_SECTION TCL_MAN_STYLE*
32# TCL_MAN_INDEX* TCL_TK_SHELL*
33#
34# (ones marked with * are optional)
35#
36# Notes:
37# o Must be run in the Extended Tcl top level directory.
38# o The routine InstallManPages has code to determine if a manual page
39# belongs to a command or function. For Tcl the commands are assumed
40# to be in "Tcl.man", for TclX functions are in TclX.man. All others
41# are assumed to be functions. For Tk, all manuals starting with Tk_
42# are assumed to be functions, all others are assumed to be commands.
43#::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
44
45#------------------------------------------------------------------------------
46# ParseConfigFile --
47#
48# Parse a configure file in the current directory and convert all make
49# macros to global Tcl variables.
50
51proc ParseConfigFile {configFile} {
52 set cfgFH [open $configFile]
53
54 while {[gets $cfgFH line] >= 0} {
55 if {[string match {[A-Za-z]*} $line]} {
56 set idx [string first "=" $line]
57 if {$idx < 0} {
58 error "no `=' in: $line"}
59 set name [string trim [csubstr $line 0 $idx]]
60 set value [string trim [crange $line [expr $idx+1] end]]
61 global $name
62 set $name $value
63 }
64 }
65 close $cfgFH
66
67}
68
69#------------------------------------------------------------------------------
70# GiveAwayFile --
71# Give away a file to the Tcl owner and group and set its permissions.
72#
73# Globals:
74# TCL_OWNER - Owner name for Tcl files.
75# TCL_GROUP - Group nmae for Tcl file.
76#------------------------------------------------------------------------------
77
78proc GiveAwayFile {file} {
79 global TCL_OWNER TCL_GROUP
80
81 if {[file isdirectory $file]} {
82 chmod a+rx,go-w $file
83 } else {
84 chmod a+r,go-w $file
85 }
86 chown [list $TCL_OWNER $TCL_GROUP] $file
87
88} ;# GiveAwayFile
89
90#------------------------------------------------------------------------------
91# MakePath --
92#
93# Make sure all directories in a directory path exists, if not, create them.
94#------------------------------------------------------------------------------
95proc MakePath {pathlist} {
96 foreach path $pathlist {
97 set exploded_path [split $path /]
98 set thisdir {}
99 foreach element $exploded_path {
100 append thisdir $element
101 if {![file isdirectory $thisdir]} {
102 mkdir $thisdir
103 GiveAwayFile $thisdir
104 }
105 append thisdir /
106 }
107 }
108}
109
110#------------------------------------------------------------------------------
111# CopyFile --
112#
113# Copy the specified file and change the ownership. If target is a directory,
114# then the file is copied to it, otherwise target is a new file name.
115#------------------------------------------------------------------------------
116
117proc CopyFile {sourceFile target} {
118
119 if {[file isdirectory $target]} {
120 set targetFile "$target/[file tail $sourceFile]"
121 } else {
122 set targetFile $target
123 }
124
125 unlink -nocomplain $targetFile
126 set sourceFH [open $sourceFile r]
127 set targetFH [open $targetFile w]
128 copyfile $sourceFH $targetFH
129 close $sourceFH
130 close $targetFH
131 GiveAwayFile $targetFile
132
133} ;# CopyFile
134
135#------------------------------------------------------------------------------
136# CopyManPage --
137#
138# Copy the specified manual page and change the ownership. The manual page
139# is edited to remove change bars (.VS and .VE macros). If target is a
140# directory, then the file is copied to it, otherwise target is a new file
141# name.
142#------------------------------------------------------------------------------
143
144proc CopyManPage {sourceFile target} {
145
146 if {[file isdirectory $target]} {
147 set targetFile "$target/[file tail $sourceFile]"
148 } else {
149 set targetFile $target
150 }
151
152 unlink -nocomplain $targetFile
153 set sourceFH [open $sourceFile r]
154 set targetFH [open $targetFile w]
155 while {[gets $sourceFH line] >= 0} {
156 if [string match {.V[SE]*} $line] continue
157 puts $targetFH $line
158 }
159 close $sourceFH
160 close $targetFH
161 GiveAwayFile $targetFile
162
163} ;# CopyManPage
164
165#------------------------------------------------------------------------------
166# CopySubDir --
167#
168# Recursively copy part of a directory tree, changing ownership and
169# permissions. This is a utility routine that actually does the copying.
170#------------------------------------------------------------------------------
171
172proc CopySubDir {sourceDir destDir} {
173 foreach sourceFile [glob -nocomplain $sourceDir/*] {
174
175 if [file isdirectory $sourceFile] {
176 set destFile $destDir/[file tail $sourceFile]
177 if {![file exists $destFile]} {
178 mkdir $destFile}
179 GiveAwayFile $destFile
180 CopySubDir $sourceFile $destFile
181 } else {
182 CopyFile $sourceFile $destDir
183 }
184 }
185} ;# CopySubDir
186
187#------------------------------------------------------------------------------
188# CopyDir --
189#
190# Recurisvely copy a directory tree.
191#------------------------------------------------------------------------------
192
193proc CopyDir {sourceDir destDir} {
194
195 set cwd [pwd]
196 if ![file exists $sourceDir] {
197 error "\"$sourceDir\" does not exist"
198 }
199 if ![file isdirectory $sourceDir] {
200 error "\"$sourceDir\" isn't a directory"
201 }
202 if {![file exists $destDir]} {
203 mkdir $destDir
204 GiveAwayFile $destDir
205 }
206 if ![file isdirectory $destDir] {
207 error "\"$destDir\" isn't a directory"
208 }
209 cd $sourceDir
210 set status [catch {CopySubDir . $destDir} msg]
211 cd $cwd
212 if {$status != 0} {
213 global errorInfo errorCode
214 error $msg $errorInfo $errorCode
215 }
216}
217
218#------------------------------------------------------------------------------
219# GenDefaultFile --
220#
221# Generate the tcl defaults file.
222#------------------------------------------------------------------------------
223
224proc GenDefaultFile {defaultFileBase sourceDir} {
225
226 set defaultFile "$defaultFileBase[infox version]"
227
228 if ![file writable [file dirname $defaultFile]] {
229 puts stderr "Can't create $defaultFile -- directory is not writable"
230 puts stderr "Please reinstall with correct permissions or rebuild"
231 puts stderr "Tcl to select a default file where the directory path"
232 puts stderr "you specify is writable by you."
233 puts stderr ""
234 exit 1
235 }
236
237 set fp [open $defaultFile w]
238
239 puts $fp "# Extended Tcl [infox version] default file"
240 puts $fp ""
241 puts $fp "set TCLINIT $sourceDir/TclInit.tcl"
242 puts $fp ""
243 puts $fp "set TCLPATH $sourceDir"
244
245 close $fp
246 GiveAwayFile $defaultFile
247
248} ;# GenDefaultFile
249
250#------------------------------------------------------------------------------
251# GetManNames --
252#
253# Search a manual page (nroff source) for the name line. Parse the name
254# line into all of the functions or commands that it references. This isn't
255# comprehensive, but it works for all of the Tcl, TclX and Tk man pages.
256#
257# Parameters:
258# o manFile (I) - The path to the manual page file.
259# Returns:
260# A list contain the functions or commands or {} if the name line can't be
261# found or parsed.
262#------------------------------------------------------------------------------
263
264proc GetManNames {manFile} {
265
266 set manFH [open $manFile]
267
268 #
269 # Search for name line. Once found, grab the next line that is not a
270 # nroff macro. If we end up with a blank line, we didn't find it.
271 #
272 while {[gets $manFH line] >= 0} {
273 if [regexp {^.SH NAME.*$} $line] {
274 break
275 }
276 }
277 while {[gets $manFH line] >= 0} {
278 if {![string match ".*" $line]} break
279 }
280 close $manFH
281
282 set line [string trim $line]
283 if {$line == ""} return
284
285 #
286 # Lets try and parse the name list out of the line
287 #
288 if {![regexp {^(.*)(\\-)} $line {} namePart]} {
289 if {![regexp {^(.*)(-)} $line {} namePart]} return
290 }
291
292 #
293 # This magic converts the name line into a list
294 #
295
296 if {[catch {join [split $namePart ,] " "} namePart] != 0} return
297
298 return $namePart
299
300}
301
302#------------------------------------------------------------------------------
303# SetUpManIndex --
304# Setup generation of manual page index for short manual pages, if required.
305# Globals:
306# o TCL_MAN_INDEX - Boolean indicating if a manual page is to be created.
307# If it does not exists, false is assumed.
308# o TCL_MAN_BASEDIR - Base manual directory where all of the man.* and cat.*
309# directories live.
310# Returns:
311# The manual index file handle, or {} if the manual index is not to be
312# generated.
313#------------------------------------------------------------------------------
314
315proc SetUpManIndex {} {
316 global TCL_MAN_BASEDIR TCL_MAN_INDEX
317
318 if {!([info exists TCL_MAN_INDEX] && [set TCL_MAN_INDEX])} {
319 return {}
320 }
321 set tclIndexFile $TCL_MAN_BASEDIR/index.TCL
322 return [open $tclIndexFile w]
323}
324
325#------------------------------------------------------------------------------
326# FinishUpManIndex --
327# Finish generation of manual page index for short manual pages, if required.
328# Parameters:
329# o indexFileHdl - The file handle returned by SetUpManIndex, maybe {}.
330# Globals:
331# o TCL_MAN_BASEDIR - Base manual directory where all of the man.* and cat.*
332# directories live.
333#------------------------------------------------------------------------------
334
335proc FinishUpManIndex {indexFileHdl} {
336 global TCL_MAN_BASEDIR TCL_MAN_INDEX_MERGE
337
338 if [lempty $indexFileHdl] return
339
340 set tclIndexFile $TCL_MAN_BASEDIR/index.TCL
341 close $indexFileHdl
342 GiveAwayFile $tclIndexFile
343
344}
345
346#------------------------------------------------------------------------------
347# InstallShortMan --
348# Install a manual page on a system that does not have long file names,
349# optionally adding an entry to the man index.
350#
351# Parameters:
352# o sourceFile - Manual page source file path.
353# o section - Section to install the manual page in.
354# o indexFileHdl - File handle of the current index file being created, or
355# empty if no index is to be created.
356# Globals:
357# o TCL_MAN_BASEDIR - Base manual directory where all of the man.* and cat.*
358# directories live.
359# o TCL_MAN_SEPARATOR - The name separator between the directory and the
360# section.
361#------------------------------------------------------------------------------
362
363proc InstallShortMan {sourceFile section indexFileHdl} {
364 global TCL_MAN_BASEDIR TCL_MAN_SEPARATOR
365
366 set manNames [GetManNames $sourceFile]
367 if [lempty $manNames] {
368 set baseName [file tail [file root $sourceFile]]
369 puts stderr "Warning: can't parse NAME line for man page: $sourceFile."
370 puts stderr " Manual page only available as: $baseName"
371 }
372
373 set manFileBase [file tail [file root $sourceFile]]
374 set manFileName "$manFileBase.$section"
375
376 set destManDir "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$section"
377 set destCatDir "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$section"
378
379 CopyManPage $sourceFile "$destManDir/$manFileName"
380 unlink -nocomplain "$destCatDir/$manFileName"
381
382 if {![lempty $indexFileHdl]} {
383 foreach name $manNames {
384 puts $indexFileHdl "$name\t$manFileBase\t$section"
385 }
386 }
387}
388
389#------------------------------------------------------------------------------
390# InstallLongMan --
391# Install a manual page on a system that does have long file names.
392#
393# Parameters:
394# o sourceFile - Manual page source file path.
395# o section - Section to install the manual page in.
396# Globals:
397# o TCL_MAN_BASEDIR - Base manual directory where all of the man.* and cat.*
398# directories live.
399# o TCL_MAN_SEPARATOR - The name separator between the directory and the
400# section.
401#------------------------------------------------------------------------------
402
403proc InstallLongMan {sourceFile section} {
404 global TCL_MAN_BASEDIR TCL_MAN_SEPARATOR
405
406 set manNames [GetManNames $sourceFile]
407 if [lempty $manNames] {
408 set baseName [file tail [file root $sourceFile]]
409 puts stderr "Warning: can't parse NAME line for man page: $sourceFile."
410 puts stderr " Manual page only available as: $baseName"
411 set manNames $baseName
412 }
413
414 set destManDir "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$section"
415 set destCatDir "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$section"
416
417 # Copy file to the first name in the list.
418
419 set firstFile [lvarpop manNames]
420 set firstFilePath "$destManDir/$firstFile.$section"
421
422 CopyManPage $sourceFile $firstFilePath
423 unlink -nocomplain "$destCatDir/$firstFile.$section"
424
425 # Link it to the rest of the names in the list.
426
427 foreach manEntry $manNames {
428 set destFilePath "$destManDir/$manEntry.$section"
429 unlink -nocomplain $destFilePath
430 if {[catch {
431 link $firstFilePath $destFilePath
432 } msg] != 0} {
433 puts stderr "error from: link $firstFilePath $destFilePath"
434 puts stderr " $msg"
435 }
436 unlink -nocomplain "$destCatDir/$manEntry.$section"
437 }
438
439}
440
441#------------------------------------------------------------------------------
442# InstallManPage --
443# Install a manual page on a system.
444#
445# Parameters:
446# o sourceFile - Manual page source file path.
447# o section - Section to install the manual page in.
448# o indexFileHdl - File handle of the current index file being created, or
449# empty if no index is to be created.
450# Globals
451# o TCL_MAN_STYLE - SHORT if short manual page names are being used,
452# LONG if long manual pages are being used.
453#------------------------------------------------------------------------------
454
455proc InstallManPage {sourceFile section indexFileHdl} {
456 global TCL_MAN_STYLE
457
458 if {"$TCL_MAN_STYLE" == "SHORT"} {
459 InstallShortMan $sourceFile $section $indexFileHdl
460 } else {
461 InstallLongMan $sourceFile $section
462 }
463}
464
465#------------------------------------------------------------------------------
466# InstallManPages --
467# Install the manual pages.
468#------------------------------------------------------------------------------
469
470proc InstallManPages {} {
471 global TCL_UCB_DIR TCL_TK_SHELL TCL_TK_DIR
472 global TCL_MAN_BASEDIR TCL_MAN_SEPARATOR TCL_MAN_STYLE
473 global TCL_MAN_CMD_SECTION TCL_MAN_FUNC_SECTION
474 global TK_MAN_CMD_SECTION TK_MAN_FUNC_SECTION
475
476 if {![info exists TCL_MAN_STYLE]} {
477 set TCL_MAN_STYLE LONG
478 }
479 set TCL_MAN_STYLE [string toupper $TCL_MAN_STYLE]
480 case $TCL_MAN_STYLE in {
481 {SHORT} {}
482 {LONG} {}
483 default {error "invalid value for TCL_MAN_STYLE: `$TCL_MAN_STYLE'"}
484 }
485
486 MakePath $TCL_MAN_BASEDIR
487 MakePath "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$TCL_MAN_CMD_SECTION"
488 MakePath "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$TCL_MAN_CMD_SECTION"
489 MakePath "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$TCL_MAN_FUNC_SECTION"
490 MakePath "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$TCL_MAN_FUNC_SECTION"
491
492 set indexFileHdl [SetUpManIndex]
493
494 # Install all of the actual files.
495
496 echo " Installing Tcl [info tclversion] man files"
497 foreach fileName [glob $TCL_UCB_DIR/doc/*.man] {
498 if {[file root $fileName] == "Tcl.man"} {
499 set section $TCL_MAN_CMD_SECTION
500 } else {
501 set section $TCL_MAN_FUNC_SECTION
502 }
503 InstallManPage $fileName $section $indexFileHdl
504 }
505
506 echo " Installing Extended Tcl [infox version] man files"
507
508 foreach fileName [glob man/*.man] {
509 if {[file root $fileName] == "TclX.man"} {
510 set section $TCL_MAN_CMD_SECTION
511 } else {
512 set section $TCL_MAN_FUNC_SECTION
513 }
514 InstallManPage $fileName $section $indexFileHdl
515 }
516
517 if {![info exists TCL_TK_SHELL]} {
518 FinishUpManIndex $indexFileHdl
519 return
520 }
521
522 MakePath "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$TK_MAN_CMD_SECTION"
523 MakePath "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$TK_MAN_CMD_SECTION"
524 MakePath "$TCL_MAN_BASEDIR/man$TCL_MAN_SEPARATOR$TK_MAN_FUNC_SECTION"
525 MakePath "$TCL_MAN_BASEDIR/cat$TCL_MAN_SEPARATOR$TK_MAN_FUNC_SECTION"
526
527 echo " Installing Tk man files"
528
529 foreach fileName [glob $TCL_TK_DIR/doc/*.man] {
530 if {![string match "Tk_*" [file root $fileName]]} {
531 set section $TK_MAN_CMD_SECTION
532 } else {
533 set section $TK_MAN_FUNC_SECTION
534 }
535 InstallManPage $fileName $section $indexFileHdl
536 }
537
538 FinishUpManIndex $indexFileHdl
539
540} ;# InstallLongManPages
541
542#------------------------------------------------------------------------------
543# Main program code.
544#------------------------------------------------------------------------------
545
546echo ""
547echo ">>> Installing Extended Tcl [infox version] <<<"
548
549set argc [llength $argv]
550if {$argc != 0} {
551 puts stderr "usage: tcl installTcl.tcl"
552 exit 1
553}
554
555#
556# Bring in all of the macros defined bu the configuration file.
557#
558ParseConfigFile Config.mk
559ParseConfigFile config/$TCL_CONFIG_FILE
560
561#
562# Make sure all directories exists that we will be installing in.
563#
564
565MakePath [list $TCL_TCLDIR [file dirname $TCL_DEFAULT] $TCL_BINDIR]
566MakePath [list $TCL_LIBDIR $TCL_INCLUDEDIR $TCL_TCLDIR]
567
568echo " Creating default file: $TCL_DEFAULT[infox version]"
569GenDefaultFile $TCL_DEFAULT $TCL_TCLDIR
570
571echo " Installing `tcl' program in: $TCL_BINDIR"
572CopyFile tcl $TCL_BINDIR
573chmod +rx $TCL_BINDIR/tcl
574
575echo " Installing `libtcl.a' library in: $TCL_LIBDIR"
576CopyFile libtcl.a $TCL_LIBDIR
577
578echo " Installing Tcl .h files in: $TCL_INCLUDEDIR"
579CopyFile $TCL_UCB_DIR/tcl.h $TCL_INCLUDEDIR
580CopyFile $TCL_UCB_DIR/tclHash.h $TCL_INCLUDEDIR
581CopyFile src/tclExtend.h $TCL_INCLUDEDIR
582CopyFile src/tcl++.h $TCL_INCLUDEDIR
583
584echo " Installing Tcl run-time files in: $TCL_TCLDIR"
585foreach srcFile [glob tcllib/*] {
586 if {![file isdirectory $srcFile]} {
587 CopyFile $srcFile $TCL_TCLDIR
588 }
589}
590
591echo " Installing Tcl help files in: $TCL_TCLDIR/help"
592if [file exists $TCL_TCLDIR/help] {
593 echo " Purging old help tree"
594 exec rm -rf $TCL_TCLDIR/help
595}
596CopyDir tcllib/help $TCL_TCLDIR/help
597
598if [info exists TCL_TK_SHELL] {
599 echo " Installing `wish' program in: $TCL_BINDIR"
600 CopyFile wish $TCL_BINDIR
601 chmod +rx $TCL_BINDIR/wish
602
603 echo " Installing `libtk.a' library in: $TCL_LIBDIR"
604 CopyFile libtk.a $TCL_LIBDIR
605
606 echo " Installing `tk.h' in: $TCL_INCLUDEDIR"
607 CopyFile $TCL_TK_DIR/tk.h $TCL_INCLUDEDIR
608}
609
610foreach file [glob $TCL_TCLDIR/*.tlib] {
611 buildpackageindex $file
612}
613
614if {$TCL_MAN_INSTALL} {
615 InstallManPages
616}
617
618echo " *** TCL IS NOW INSTALLED ***"
619
Impressum, Datenschutz