/[polypkg]/trunk/pp.front
ViewVC logotype

Contents of /trunk/pp.front

Parent Directory Parent Directory | Revision Log Revision Log


Revision 196 - (show annotations)
Thu Oct 23 18:35:15 2008 UTC (12 months, 4 weeks ago) by tperciva
File size: 12767 byte(s)
Add %depend processing for deb

Allows specifying explicit package dependencies.
1 #
2 # Polypkg frontend - reads a polypkg file and split it up into the various
3 # section files that get read by the backend(s).
4 #
5 # The output files from frontend() are:
6 #
7 # %files.run - required runtime files
8 # %files.doc - optional documentation files
9 # %files.dbg - optional debugging files
10 # %files.dev - optional developer files
11 #
12 # Lines in %files.* consist only of:
13 # [d|f] path mode owner group [v|-]
14 # s path mode owner group [v|-] target
15 #
16 # %post.$cpt - post-install script ($cpt component)
17 # %preun.$cpt - pre-uninstall script ($cpt component)
18 # %check.$cpt - pre-install check script ($cpt component)
19 #
20 # where $cpt is one of [ run doc dbg dev ]
21 #
22 # %service.$svc - service variables
23 #
24 # %depend - common package dependencies (one per line)
25 # %depend.$cpt - $cpt component dependencies
26 #
27 # Internal file output:
28 #
29 # frontend.tmp - result of [platform] prefix removal
30 #
31 # Each backend should examine these files and construct the right
32 # output package.
33 #
34 # The frontend also sets the variable $components to be the list of
35 # file components defined
36 #
37 # Each of the %files.* files contains entries of the form
38 # f mode owner group flags file-path
39 # d mode owner group flags directory-path
40 # s mode owner group flags symlink-path symlink-target
41 #
42 # The mode/owner/group may be the special symbol '-' which means
43 # that the platform should choose an appropriate preference based on the
44 # path (this is usually the 'root' or 'bin' user/group or mode 755 or 644.
45 #
46 # If the symlink-target is omitted, then a readlink is performed and
47 # any $pre_destdir prefix is removed.
48 #
49 # The flags is either - or a sequence of letters. The letters mean:
50 # v - the file is volatile, and expected to change content during use
51 #
52
53 pp_if_true=0
54 pp_if_false=0
55
56 #@ pp_frontend_init(): Set variables to their default values
57 pp_frontend_init () {
58 name=
59 version=
60 summary="no summary"
61 description="No description"
62 copyright="(c) 2008 Quest Software, Inc. All rights reserved"
63
64 #-- if the user supplied extra arguments on the command line
65 # then load them now.
66 pp_debug "pp_opt_init_vars=$pp_opt_init_vars"
67 test -n "$pp_opt_init_vars" && eval "$pp_opt_init_vars"
68 }
69
70 #@ pp_is_qualifier(): returns true if the arg is a qualifier expression
71 pp_is_qualifier () {
72 typeset ret
73
74 case "$1" in
75 "["*"]") ret=true;;
76 *) ret=false;;
77 esac
78 pp_debug "is_qualifier: $* -> $ret"
79 test $ret = true
80 }
81
82 #@ pp_eval_qualifier(): returns true if plat qual matches current plat
83 # Platform qualifiers match the following grammar
84 # '[' '!'? platform ( ',' platform )* ']'
85 # Returns true if the current platform is in the list of platforms.
86 # Starting with a '!' reverses the sense of the test.
87 # Special consequential qualifiers:
88 # [] - always false
89 # [!] - always true
90 pp_eval_qualifier () {
91 typeset ret
92
93 case "$1" in
94 "[!$pp_platform]"| \
95 "[!"*",$pp_platform]"| \
96 "[!$pp_platform,"*"]"| \
97 "[!"*",$pp_platform,"*"]") ret=false;;
98 "[!"*"]") ret=true;;
99 "[$pp_platform]"| \
100 "["*",$pp_platform]"| \
101 "[$pp_platform,"*"]"| \
102 "["*",$pp_platform,"*"]") ret=true;;
103 "["*"]") ret=false;;
104 *) pp_die "pp_eval_qualifier: bad qualifier '$1'"
105 esac
106 pp_debug "eval: $* -> $ret"
107 test true = $ret
108 }
109
110 #@ pp_frontend_if(): helper function for %if/%else/%endif logic
111 # Updates $pp_if_true and $pp_if_false variables which count
112 # the depth of true or false if/else branches. (Note that this
113 # counting scheme is unable to support an '%elif' construct,
114 # which really needs a stack.)
115 # The '%if' arguments can be by any one of:
116 # - 1, true, 0, false => explicit true or false
117 # - [qualifier] => see pp_eval_qualifier()
118 # - test-expr => given to the shell's test command
119 # The variables $pp_if_false and $pp_if_true are counters for if nesting.
120 # If $pp_if_false is non-zero then processing should be suppressed.
121 pp_frontend_if () {
122 typeset ifcmd ifret
123 ifcmd="$1";
124 shift
125 case "$ifcmd" in
126 %if) if test 0 = $pp_if_false; then
127 case "$*" in
128 true |1) pp_incr pp_if_true;;
129 false|0) pp_incr pp_if_false;;
130 *)
131 ifret=true
132 if pp_is_qualifier "$*"; then
133 pp_eval_qualifier "$*" || ifret=false
134 else
135 eval test "$@" || ifret=false
136 pp_debug "evaluating test $* -> $ifret"
137 fi
138 pp_incr pp_if_$ifret
139 ;;
140 esac
141 else
142 pp_incr pp_if_false
143 fi;;
144 %else) test $# = 0 || pp_warn "ignoring argument to %else"
145 if test $pp_if_false -gt 1; then
146 : no change
147 elif test $pp_if_false = 1; then
148 pp_incr pp_if_true
149 pp_decr pp_if_false
150 elif test $pp_if_true = 0; then
151 pp_die "unmatched %else"
152 else
153 pp_incr pp_if_false
154 pp_decr pp_if_true
155 fi;;
156 %endif) test $# = 0 || pp_warn "ignoring argument to %endif"
157 if test $pp_if_false -gt 0; then
158 pp_decr pp_if_false
159 elif test $pp_if_true -gt 0; then
160 pp_decr pp_if_true
161 else
162 pp_die "unmatched %endif"
163 fi;;
164 *) pp_die "frontend_if: unknown cmd $ifcmd";;
165 esac
166 }
167
168
169 #@ pp_frontend()
170 # Processes a polypkg script on stdin. The output is
171 # a collection of output files named %*
172 # This function recognises section tags (eg %preun, %set, etc)
173 # and directs subsequent lines to the right output file.
174 # This function also
175 # - process [platform]/[!platform] tags on lines (eg [AIX])
176 # - removes comment lines
177 # - detects %set, %post, %preun etc sections
178 # - handles %if/%else/%endif logic
179 pp_frontend () {
180 typeset section newsection sed_word sed_ws line cpt svc
181 typeset section_enabled newsection_enabled s sed sed_candidate
182
183 section='%_initial'
184 newsection='%_initial'
185 section_enabled=:
186 newsection_enabled=:
187 sed_word="[a-zA-Z_][a-zA-Z_0-9]*"
188 sed_ws="[ ]"
189
190 #-- not all seds are created equal
191 sed=
192 for sed_candidate in ${PP_SED:-sed} /usr/xpg4/bin/sed; do
193 if echo 'foo' | $sed_candidate -ne '/^\(x\)*foo/p' | grep foo > /dev/null
194 then
195 sed="$sed_candidate"
196 break
197 fi
198 done
199 test -z "$sed" &&
200 pp_die "sed is broken on this system"
201
202 pp_lineno=0
203
204 #-- Note: this sed script should perform similar to pp_eval_qualifier()
205 $sed -e "/^#/s/.*//" \
206 -e "/^\\[!\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]/s/.*//" \
207 -e "s/^\\[\\($sed_word,\\)*$pp_platform\\(,$sed_word\\)*\\]$sed_ws*//" \
208 -e "s/^\\[!\\($sed_word,\\)*$sed_word\\]$sed_ws*//" \
209 -e "/^\\[\\($sed_word,\\)*$sed_word\\]/s/.*//" \
210 -e "s/^%$sed_ws*/%/" \
211 -e "s/^$sed_ws/%\\\\&/" \
212 > $pp_wrkdir/frontend.tmp
213
214 #-- add an ignore section at the end to force section completion
215 echo '%ignore' >> $pp_wrkdir/frontend.tmp
216 echo >> $pp_wrkdir/frontend.tmp
217
218 exec 0<$pp_wrkdir/frontend.tmp
219 : > $pp_wrkdir/tmp
220 : > $pp_wrkdir/%fixup
221 while read -r line; do
222 #-- Convert leading double-% to single-%, or switch sections
223 pp_incr pp_lineno
224
225 pp_debug "line $pp_lineno: $line"
226 set -f
227 set -- $line
228 set +f
229 #pp_debug "line $pp_lineno: $*"
230
231 case "$line" in %*)
232 case "$1" in
233 %if|%else|%endif)
234 pp_debug "processing if directive $1"
235 pp_frontend_if "$@"
236 continue;;
237 esac
238 test 0 -ne $pp_if_false && continue # ignore lines %if'd out
239
240 case "$1" in
241 %set|%fixup|%ignore)
242 pp_debug "processing new section $1"
243 newsection="$1"; shift
244 newsection_enabled=:
245 if pp_is_qualifier "$1"; then
246 pp_eval_qualifier "$1" || newsection_enabled=false
247 shift
248 fi
249 test $# -eq 0 || pp_warn "ignoring extra arguments: $line"
250 continue;;
251 %post|%preun|%files|%depend|%check)
252 pp_debug "processing new component section $*"
253 s="$1"; shift
254 if test $# -eq 0 || pp_is_qualifier "$1"; then
255 cpt=run
256 else
257 cpt="$1"
258 shift
259 fi
260 newsection="$s.$cpt"
261 newsection_enabled=:
262 if test $# -gt 0 && pp_is_qualifier "$1"; then
263 pp_eval_qualifier "$1" || newsection_enabled=false
264 shift
265 fi
266 test $# -eq 0 ||
267 pp_warn "ignoring extra arguments: $line"
268 case "$cpt" in
269 run|dbg|doc|dev)
270 $newsection_enabled && pp_add_component "$cpt";;
271 x-*) :;; # useful for discarding stuff
272 *) pp_error "unknown component: $1 $cpt";;
273 esac
274 continue;;
275 %pp)
276 newsection="%ignore"; shift
277 if test $# -gt 0; then
278 pp_set_api_version "$1"
279 shift
280 else
281 pp_error "%pp: missing version"
282 fi
283 test $# -gt 0 &&
284 pp_error "%pp: too many arguments"
285 continue;;
286 %service)
287 pp_debug "processing new service section $1 $2"
288 s="$1"; shift
289 if test $# -eq 0 || pp_is_qualifier "$1"; then
290 pp_error "$s: service name required"
291 svc=unknown
292 else
293 svc="$1"; shift
294 fi
295
296 newsection="$s.$svc"
297 newsection_enabled=:
298 if test $# -gt 0 && pp_is_qualifier "$1"; then
299 pp_eval_qualifier "$1" || newsection_enabled=false
300 shift
301 fi
302 test $# -eq 0 ||
303 pp_warn "ignoring extra arguments: $line"
304 $newsection_enabled && pp_add_service "$svc"
305 continue;;
306 %\\*)
307 pp_debug "removing leading %\\"
308 line="${line#??}"
309 pp_debug " result is <$line>"
310 set -f
311 set -- $line
312 set +f
313 ;;
314 %%*)
315 pp_debug "removing leading %"
316 line="${line#%}"
317 set -f
318 set -- $line
319 set +f
320 ;;
321 %*)
322 pp_error "unknown section $1"
323 newsection='%ignore'
324 newsection_enabled=:
325 continue;;
326 esac;;
327 esac
328
329 test 0 != $pp_if_false && continue # ignore lines %if'd out
330
331 pp_debug "section=$section (enabled=$section_enabled) newsection=$newsection (enabled=$newsection_enabled)"
332
333 #-- finish processing a previous section
334 if test x"$newsection" != x""; then
335 $section_enabled && case "$section" in
336 %ignore|%_initial)
337 pp_debug "leaving ignored section $section"
338 : ignore # guaranteed to be the last section
339 ;;
340 %set)
341 pp_debug "leaving $section: sourcing $pp_wrkdir/tmp"
342 $pp_opt_debug && cat $pp_wrkdir/tmp >&2
343 . $pp_wrkdir/tmp
344 : > $pp_wrkdir/tmp
345 ;;
346 %preun.*|%post.*|%depend.*|%check.*|%service.*|%fixup)
347 pp_debug "leaving $section: substituting $pp_wrkdir/tmp"
348 # cat $pp_wrkdir/tmp >&2 # debugging
349 $pp_opt_debug && pp_substitute < $pp_wrkdir/tmp >&2
350 pp_substitute < $pp_wrkdir/tmp > $pp_wrkdir/tmp.sh
351 . $pp_wrkdir/tmp.sh >> $pp_wrkdir/$section ||
352 pp_error "shell error in $section"
353 rm -f $pp_wrkdir/tmp.sh
354 : > $pp_wrkdir/tmp
355 ;;
356 esac
357 section="$newsection"
358 section_enabled="$newsection_enabled"
359 newsection=
360 fi
361
362 #-- ignore section content that is disabled
363 $section_enabled || continue
364
365 #-- process some lines in-place
366 case "$section" in
367 %_initial)
368 case "$line" in "") continue;; esac # ignore non-section blanks
369 pp_die "Ignoring text before % section introducer";;
370 %set|%preun.*|%post.*|%check.*|%service.*|%fixup)
371 pp_debug "appending line to \$pp_wrkdir/tmp"
372 echo "$line" >> $pp_wrkdir/tmp
373 ;;
374 %files.*)
375 test $# -eq 0 && continue;
376 pp_files_expand "$@" >> $pp_wrkdir/$section
377 ;;
378 %depend.*)
379 pp_debug "Adding explicit dependency $@ to $cpt"
380 echo "$@" >> $pp_wrkdir/%depend.$cpt
381 ;;
382 esac
383 done
384 exec <&-
385
386 if test $pp_if_true != 0 -o $pp_if_false != 0; then
387 pp_die "missing %endif at end of file"
388 fi
389
390 pp_lineno=
391
392 pp_debug " name = $name"
393 pp_debug " version = $version"
394 pp_debug " summary = $summary"
395 pp_debug " description = $description"
396 pp_debug " copyright = $copyright"
397 pp_debug ""
398 pp_debug "\$pp_components: $pp_components"
399 pp_debug "\$pp_services: $pp_services"
400 }
401
402 #@ pp_set_api_version($v): change pp's behaviour to match the desired version
403 pp_set_api_version() {
404 case "$1" in
405 1.0) : ;;
406 *) pp_error "This version of polypackage is too old";;
407 esac
408 }

Ted.Percival@quest.com
ViewVC Help
Powered by ViewVC 1.1.2