1: #!/usr/bin/perl
2:
3: # Scott Harrison
4: # YEAR=2001
5: # May 2001
6: # 06/19/2001,06/20,06/24 - Scott Harrison
7: # 9/5/2001,9/6,9/7,9/8 - Scott Harrison
8: # 9/17,9/18 - Scott Harrison
9: # 11/4 - Scott Harrison
10:
11: ###############################################################################
12: ## ##
13: ## ORGANIZATION OF THIS PERL SCRIPT ##
14: ## 1. Notes ##
15: ## 2. Get command line arguments ##
16: ## 3. First pass through (grab distribution-specific information) ##
17: ## 4. Second pass through (parse out what is not necessary) ##
18: ## 5. Third pass through (translate markup according to specified mode) ##
19: ## 6. Functions (most all just format contents of different markup tags) ##
20: ## 7. POD (plain old documentation, CPAN style) ##
21: ## ##
22: ###############################################################################
23:
24: # ----------------------------------------------------------------------- Notes
25: #
26: # I am using a multiple pass-through approach to parsing
27: # the lpml file. This saves memory and makes sure the server
28: # will never be overloaded.
29: #
30: # This is meant to parse files meeting the lpml document type.
31: # See lpml.dtd. LPML=Linux Packaging Markup Language.
32:
33: use HTML::TokeParser;
34:
35: my $usage=<<END;
36: **** ERROR ERROR ERROR ERROR ****
37: Usage is for lpml file to come in through standard input.
38: 1st argument is the mode of parsing.
39: 2nd argument is the category permissions to use (runtime or development)
40: 3rd argument is the distribution (default,redhat6.2,debian2.2,redhat7.1,etc).
41: 4th argument is to manually specify a sourceroot.
42: 5th argument is to manually specify a targetroot.
43:
44: Only the 1st argument is mandatory for the program to run.
45:
46: Example:
47:
48: cat ../../doc/loncapafiles.lpml |\\
49: perl lpml_parse.pl html default /home/sherbert/loncapa /tmp/install
50: END
51:
52: # ------------------------------------------------- Grab command line arguments
53:
54: my $mode;
55: if (@ARGV==5) {
56: $mode = shift @ARGV;
57: }
58: else {
59: @ARGV=();shift @ARGV;
60: while(<>){} # throw away the input to avoid broken pipes
61: print $usage;
62: exit -1; # exit with error status
63: }
64:
65: my $categorytype;
66: if (@ARGV) {
67: $categorytype = shift @ARGV;
68: }
69:
70: my $dist;
71: if (@ARGV) {
72: $dist = shift @ARGV;
73: }
74:
75: my $targetroot;
76: my $sourceroot;
77: if (@ARGV) {
78: $sourceroot = shift @ARGV;
79: }
80: if (@ARGV) {
81: $targetroot = shift @ARGV;
82: }
83: $sourceroot=~s/\/$//;
84: $targetroot=~s/\/$//;
85:
86: my $invocation;
87: # --------------------------------------------------- Record program invocation
88: if ($mode eq 'install' or $mode eq 'configinstall' or $mode eq 'build') {
89: $invocation=(<<END);
90: # Invocation: STDINPUT | lpml_parse.pl
91: # 1st argument (mode) is: $mode
92: # 2nd argument (category type) is: $categorytype
93: # 3rd argument (distribution) is: $dist
94: # 4th argument (targetroot) is: described below
95: # 5th argument (sourceroot) is: described below
96: END
97: }
98:
99: # ---------------------------------------------------- Start first pass through
100: my @parsecontents = <>;
101: my $parsestring = join('',@parsecontents);
102: my $outstring;
103:
104: # Need to make a pass through and figure out what defaults are
105: # overrided. Top-down overriding strategy (leaves don't know
106: # about distant leaves).
107:
108: my @hierarchy;
109: $hierarchy[0]=0;
110: my $hloc=0;
111: my $token;
112: $parser = HTML::TokeParser->new(\$parsestring) or
113: die('can\'t create TokeParser object');
114: $parser->xml_mode('1');
115: my %hash;
116: my $key;
117: while ($token = $parser->get_token()) {
118: if ($token->[0] eq 'S') {
119: $hloc++;
120: $hierarchy[$hloc]++;
121: $key=$token->[1].join(',',@hierarchy[0..($hloc-1)]);
122: my $thisdist=' '.$token->[2]{'dist'}.' ';
123: if ($thisdist eq ' default ') {
124: $hash{$key}=1; # there is a default setting for this key
125: }
126: elsif ($dist && $hash{$key}==1 && $thisdist=~/\s$dist\s/) {
127: $hash{$key}=2; # disregard default setting for this key if
128: # there is a directly requested distribution match
129: }
130: }
131: if ($token->[0] eq 'E') {
132: $hloc--;
133: }
134: }
135:
136: # --------------------------------------------------- Start second pass through
137: undef $hloc;
138: undef @hierarchy;
139: undef $parser;
140: $hierarchy[0]=0;
141: $parser = HTML::TokeParser->new(\$parsestring) or
142: die('can\'t create TokeParser object');
143: $parser->xml_mode('1');
144: my $cleanstring;
145: while ($token = $parser->get_token()) {
146: if ($token->[0] eq 'S') {
147: $hloc++;
148: $hierarchy[$hloc]++;
149: $key=$token->[1].join(',',@hierarchy[0..($hloc-1)]);
150: my $thisdist=' '.$token->[2]{'dist'}.' ';
151: # This conditional clause is set up to ignore two sets
152: # of invalid conditions before accepting entry into
153: # the cleanstring.
154: if ($hash{$key}==2 and
155: !($thisdist eq ' ' or $thisdist =~/\s$dist\s/)) {
156: if ($token->[4]!~/\/>$/) {
157: $parser->get_tag('/'.$token->[1]);
158: $hloc--;
159: }
160: }
161: elsif ($thisdist ne ' ' and $thisdist!~/\s$dist\s/ and
162: !($thisdist eq ' default ' and $hash{$key}!=2)) {
163: if ($token->[4]!~/\/>$/) {
164: $parser->get_tag('/'.$token->[1]);
165: $hloc--;
166: }
167: }
168: else {
169: $cleanstring.=$token->[4];
170: }
171: if ($token->[4]=~/\/>$/) {
172: $hloc--;
173: }
174: }
175: if ($token->[0] eq 'E') {
176: $cleanstring.=$token->[2];
177: $hloc--;
178: }
179: if ($token->[0] eq 'T') {
180: $cleanstring.=$token->[1];
181: }
182: }
183: $cleanstring=&trim($cleanstring);
184: $cleanstring=~s/\>\s*\n\s*\</\>\</g;
185:
186: # ---------------------------------------------------- Start final pass through
187:
188: # storage variables
189: my $lpml;
190: my $categories;
191: my $category;
192: my $category_att_name;
193: my $category_att_type;
194: my $chown;
195: my $chmod;
196: my $rpm;
197: my $rpmSummary;
198: my $rpmName;
199: my $rpmVersion;
200: my $rpmRelease;
201: my $rpmVendor;
202: my $rpmBuildRoot;
203: my $rpmCopyright;
204: my $rpmGroup;
205: my $rpmSource;
206: my $rpmAutoReqProv;
207: my $rpmdescription;
208: my $rpmpre;
209: my $directories;
210: my $directory;
211: my $targetdirs;
212: my $targetdir;
213: my $categoryname;
214: my $description;
215: my $files;
216: my $fileglobs;
217: my $links;
218: my $file;
219: my $link;
220: my $fileglob;
221: my $sourcedir;
222: my $targets;
223: my $target;
224: my $source;
225: my $note;
226: my $build;
227: my $buildlink;
228: my $commands;
229: my $command;
230: my $status;
231: my $dependencies;
232: my $dependency;
233: my @links;
234: my %categoryhash;
235:
236: my @buildall;
237: my @buildinfo;
238:
239: my @configall;
240:
241: # Make new parser with distribution specific input
242: undef $parser;
243: $parser = HTML::TokeParser->new(\$cleanstring) or
244: die('can\'t create TokeParser object');
245: $parser->xml_mode('1');
246:
247: # Define handling methods for mode-dependent text rendering
248: $parser->{textify}={
249: targetroot => \&format_targetroot,
250: sourceroot => \&format_sourceroot,
251: categories => \&format_categories,
252: category => \&format_category,
253: targetdir => \&format_targetdir,
254: chown => \&format_chown,
255: chmod => \&format_chmod,
256: rpm => \&format_rpm,
257: rpmSummary => \&format_rpmSummary,
258: rpmName => \&format_rpmName,
259: rpmVersion => \&format_rpmVersion,
260: rpmRelease => \&format_rpmRelease,
261: rpmVendor => \&format_rpmVendor,
262: rpmBuildRoot => \&format_rpmBuildRoot,
263: rpmCopyright => \&format_rpmCopyright,
264: rpmGroup => \&format_rpmGroup,
265: rpmSource => \&format_rpmSource,
266: rpmAutoReqProv => \&format_rpmAutoReqProv,
267: rpmdescription => \&format_rpmdescription,
268: rpmpre => \&format_rpmpre,
269: directories => \&format_directories,
270: directory => \&format_directory,
271: categoryname => \&format_categoryname,
272: description => \&format_description,
273: files => \&format_files,
274: file => \&format_file,
275: fileglob => \&format_fileglob,
276: links => \&format_links,
277: link => \&format_link,
278: linkto => \&format_linkto,
279: source => \&format_source,
280: target => \&format_target,
281: note => \&format_note,
282: build => \&format_build,
283: status => \&format_status,
284: dependencies => \&format_dependencies,
285: buildlink => \&format_buildlink,
286: glob => \&format_glob,
287: sourcedir => \&format_sourcedir,
288: filenames => \&format_filenames,
289: };
290:
291: my $text;
292: my $token;
293: undef $hloc;
294: undef @hierarchy;
295: my $hloc;
296: my @hierarchy2;
297: while ($token = $parser->get_tag('lpml')) {
298: &format_lpml(@{$token});
299: $text = &trim($parser->get_text('/lpml'));
300: $token = $parser->get_tag('/lpml');
301: print $lpml;
302: print "\n";
303: # $text=~s/\s*\n\s*\n\s*/\n/g;
304: print $text;
305: print "\n";
306: print &end();
307: }
308: exit;
309:
310: # ---------- Functions (most all just format contents of different markup tags)
311:
312: # ------------------------ Final output at end of markup parsing and formatting
313: sub end {
314: if ($mode eq 'html') {
315: return "<br />THE END\n";
316: }
317: if ($mode eq 'install') {
318: return '';
319: }
320: }
321:
322: # ----------------------- Take in string to parse and the separation expression
323: sub extract_array {
324: my ($stringtoparse,$sepexp) = @_;
325: my @a=split(/$sepexp/,$stringtoparse);
326: return \@a;
327: }
328:
329: # --------------------------------------------------------- Format lpml section
330: sub format_lpml {
331: my (@tokeninfo)=@_;
332: my $date=`date`; chop $date;
333: if ($mode eq 'html') {
334: $lpml = "<br />LPML BEGINNING: $date";
335: }
336: elsif ($mode eq 'install') {
337: print '# LPML install targets. Linux Packaging Markup Language,';
338: print ' by Scott Harrison 2001'."\n";
339: print '# This file was automatically generated on '.`date`;
340: print "\n".$invocation;
341: $lpml .= "SHELL=\"/bin/bash\"\n\n";
342: }
343: elsif ($mode eq 'configinstall') {
344: print '# LPML configuration file targets (configinstall).'."\n";
345: print '# Linux Packaging Markup Language,';
346: print ' by Scott Harrison 2001'."\n";
347: print '# This file was automatically generated on '.`date`;
348: print "\n".$invocation;
349: $lpml .= "SHELL=\"/bin/bash\"\n\n";
350: }
351: elsif ($mode eq 'build') {
352: $lpml = "# LPML build targets. Linux Packaging Markup Language,";
353: $lpml .= ' by Scott Harrison 2001'."\n";
354: $lpml .= '# This file was automatically generated on '.`date`;
355: $lpml .= "\n".$invocation;
356: $lpml .= "SHELL=\"/bin/sh\"\n\n";
357: }
358: else {
359: return '';
360: }
361: }
362: # --------------------------------------------------- Format targetroot section
363: sub format_targetroot {
364: my $text=&trim($parser->get_text('/targetroot'));
365: $text=$targetroot if $targetroot;
366: $parser->get_tag('/targetroot');
367: if ($mode eq 'html') {
368: return $targetroot="\n<br />TARGETROOT: $text";
369: }
370: elsif ($mode eq 'install' or $mode eq 'build' or
371: $mode eq 'configinstall') {
372: return '# TARGET INSTALL LOCATION is "'.$targetroot."\"\n";
373: }
374: else {
375: return '';
376: }
377: }
378: # --------------------------------------------------- Format sourceroot section
379: sub format_sourceroot {
380: my $text=&trim($parser->get_text('/sourceroot'));
381: $text=$sourceroot if $sourceroot;
382: $parser->get_tag('/sourceroot');
383: if ($mode eq 'html') {
384: return $sourceroot="\n<br />SOURCEROOT: $text";
385: }
386: elsif ($mode eq 'install' or $mode eq 'build' or
387: $mode eq 'configinstall') {
388: return '# SOURCE CODE LOCATION IS "'.$sourceroot."\"\n";;
389: }
390: else {
391: return '';
392: }
393: }
394: # --------------------------------------------------- Format categories section
395: sub format_categories {
396: my $text=&trim($parser->get_text('/categories'));
397: $parser->get_tag('/categories');
398: if ($mode eq 'html') {
399: return $categories="\n<br />BEGIN CATEGORIES\n$text\n".
400: "<br />END CATEGORIES\n";
401: }
402: else {
403: return '';
404: }
405: }
406: # --------------------------------------------------- Format categories section
407: sub format_category {
408: my (@tokeninfo)=@_;
409: $category_att_name=$tokeninfo[2]->{'name'};
410: $category_att_type=$tokeninfo[2]->{'type'};
411: $chmod='';$chown='';
412: $parser->get_text('/category');
413: $parser->get_tag('/category');
414: if ($mode eq 'html') {
415: return $category="\n<br />CATEGORY $category_att_name ".
416: "$category_att_type $chmod $chown";
417: }
418: else {
419: if ($category_att_type eq $categorytype) {
420: my ($user,$group)=split(/\:/,$chown);
421: $categoryhash{$category_att_name}='-o '.$user.' -g '.$group.
422: ' -m '.$chmod;
423: }
424: return '';
425: }
426: }
427: # -------------------------------------------------------- Format chown section
428: sub format_chown {
429: my @tokeninfo=@_;
430: $chown='';
431: my $text=&trim($parser->get_text('/chown'));
432: if ($text) {
433: $parser->get_tag('/chown');
434: $chown=$text;
435: }
436: return '';
437: }
438: # -------------------------------------------------------- Format chmod section
439: sub format_chmod {
440: my @tokeninfo=@_;
441: $chmod='';
442: my $text=&trim($parser->get_text('/chmod'));
443: if ($text) {
444: $parser->get_tag('/chmod');
445: $chmod=$text;
446: }
447: return '';
448: }
449: # ---------------------------------------------------------- Format rpm section
450: sub format_rpm {
451: my $text=&trim($parser->get_text('/rpm'));
452: $parser->get_tag('/rpm');
453: if ($mode eq 'html') {
454: return $rpm="\n<br />BEGIN RPM\n$text\n<br />END RPM";
455: }
456: else {
457: return '';
458: }
459: }
460: # --------------------------------------------------- Format rpmSummary section
461: sub format_rpmSummary {
462: my $text=&trim($parser->get_text('/rpmSummary'));
463: $parser->get_tag('/rpmSummary');
464: if ($mode eq 'html') {
465: return $rpmSummary="\n<br />RPMSUMMARY $text";
466: }
467: else {
468: return '';
469: }
470: }
471: # ------------------------------------------------------ Format rpmName section
472: sub format_rpmName {
473: my $text=&trim($parser->get_text('/rpmName'));
474: $parser->get_tag('/rpmName');
475: if ($mode eq 'html') {
476: return $rpmName="\n<br />RPMNAME $text";
477: }
478: else {
479: return '';
480: }
481: }
482: # --------------------------------------------------- Format rpmVersion section
483: sub format_rpmVersion {
484: my $text=$parser->get_text('/rpmVersion');
485: $parser->get_tag('/rpmVersion');
486: if ($mode eq 'html') {
487: return $rpmVersion="\n<br />RPMVERSION $text";
488: }
489: else {
490: return '';
491: }
492: }
493: # --------------------------------------------------- Format rpmRelease section
494: sub format_rpmRelease {
495: my $text=$parser->get_text('/rpmRelease');
496: $parser->get_tag('/rpmRelease');
497: if ($mode eq 'html') {
498: return $rpmRelease="\n<br />RPMRELEASE $text";
499: }
500: else {
501: return '';
502: }
503: }
504: # ---------------------------------------------------- Format rpmVendor section
505: sub format_rpmVendor {
506: my $text=$parser->get_text('/rpmVendor');
507: $parser->get_tag('/rpmVendor');
508: if ($mode eq 'html') {
509: return $rpmVendor="\n<br />RPMVENDOR $text";
510: }
511: else {
512: return '';
513: }
514: }
515: # ------------------------------------------------- Format rpmBuildRoot section
516: sub format_rpmBuildRoot {
517: my $text=$parser->get_text('/rpmBuildRoot');
518: $parser->get_tag('/rpmBuildRoot');
519: if ($mode eq 'html') {
520: return $rpmBuildRoot="\n<br />RPMBUILDROOT $text";
521: }
522: else {
523: return '';
524: }
525: }
526: # ------------------------------------------------- Format rpmCopyright section
527: sub format_rpmCopyright {
528: my $text=$parser->get_text('/rpmCopyright');
529: $parser->get_tag('/rpmCopyright');
530: if ($mode eq 'html') {
531: return $rpmCopyright="\n<br />RPMCOPYRIGHT $text";
532: }
533: else {
534: return '';
535: }
536: }
537: # ----------------------------------------------------- Format rpmGroup section
538: sub format_rpmGroup {
539: my $text=$parser->get_text('/rpmGroup');
540: $parser->get_tag('/rpmGroup');
541: if ($mode eq 'html') {
542: return $rpmGroup="\n<br />RPMGROUP $text";
543: }
544: else {
545: return '';
546: }
547: }
548: # ---------------------------------------------------- Format rpmSource section
549: sub format_rpmSource {
550: my $text=$parser->get_text('/rpmSource');
551: $parser->get_tag('/rpmSource');
552: if ($mode eq 'html') {
553: return $rpmSource="\n<br />RPMSOURCE $text";
554: }
555: else {
556: return '';
557: }
558: }
559: # ----------------------------------------------- Format rpmAutoReqProv section
560: sub format_rpmAutoReqProv {
561: my $text=$parser->get_text('/rpmAutoReqProv');
562: $parser->get_tag('/rpmAutoReqProv');
563: if ($mode eq 'html') {
564: return $rpmAutoReqProv="\n<br />RPMAUTOREQPROV $text";
565: }
566: else {
567: return '';
568: }
569: }
570: # ----------------------------------------------- Format rpmdescription section
571: sub format_rpmdescription {
572: my $text=$parser->get_text('/rpmdescription');
573: $parser->get_tag('/rpmdescription');
574: if ($mode eq 'html') {
575: return $rpmdescription="\n<br />RPMDESCRIPTION $text";
576: }
577: else {
578: return '';
579: }
580: }
581: # ------------------------------------------------------- Format rpmpre section
582: sub format_rpmpre {
583: my $text=$parser->get_text('/rpmpre');
584: $parser->get_tag('/rpmpre');
585: if ($mode eq 'html') {
586: return $rpmpre="\n<br />RPMPRE $text";
587: }
588: else {
589: return '';
590: }
591: }
592: # -------------------------------------------------- Format directories section
593: sub format_directories {
594: my $text=$parser->get_text('/directories');
595: $parser->get_tag('/directories');
596: if ($mode eq 'html') {
597: return $directories="\n<br />BEGIN DIRECTORIES\n$text\n<br />".
598: "END DIRECTORIES\n";
599: }
600: elsif ($mode eq 'install') {
601: return "\n".'directories:'."\n".$text;
602: }
603: else {
604: return '';
605: }
606: }
607: # ---------------------------------------------------- Format directory section
608: sub format_directory {
609: my (@tokeninfo)=@_;
610: $targetdir='';$categoryname='';$description='';
611: $parser->get_text('/directory');
612: $parser->get_tag('/directory');
613: if ($mode eq 'html') {
614: return $directory="\n<br />DIRECTORY $targetdir $categoryname ".
615: "$description";
616: }
617: elsif ($mode eq 'install') {
618: return "\t".'install '.$categoryhash{$categoryname}.' -d '.
619: $targetroot.'/'.$targetdir."\n";
620: }
621: else {
622: return '';
623: }
624: }
625: # ---------------------------------------------------- Format targetdir section
626: sub format_targetdir {
627: my @tokeninfo=@_;
628: $targetdir='';
629: my $text=&trim($parser->get_text('/targetdir'));
630: if ($text) {
631: $parser->get_tag('/targetdir');
632: $targetdir=$text;
633: }
634: return '';
635: }
636: # ------------------------------------------------- Format categoryname section
637: sub format_categoryname {
638: my @tokeninfo=@_;
639: $categoryname='';
640: my $text=&trim($parser->get_text('/categoryname'));
641: if ($text) {
642: $parser->get_tag('/categoryname');
643: $categoryname=$text;
644: }
645: return '';
646: }
647: # -------------------------------------------------- Format description section
648: sub format_description {
649: my @tokeninfo=@_;
650: $description='';
651: my $text=&htmlsafe(&trim($parser->get_text('/description')));
652: if ($text) {
653: $parser->get_tag('/description');
654: $description=$text;
655: }
656: return '';
657: }
658: # -------------------------------------------------------- Format files section
659: sub format_files {
660: my $text=$parser->get_text('/files');
661: $parser->get_tag('/files');
662: if ($mode eq 'html') {
663: return $directories="\n<br />BEGIN FILES\n$text\n<br />END FILES\n";
664: }
665: elsif ($mode eq 'install') {
666: return "\n".'files:'."\n".$text.
667: "\n".'links:'."\n".join('',@links);
668: }
669: elsif ($mode eq 'configinstall') {
670: return "\n".'configfiles: '.
671: join(' ',@configall).
672: "\n\n".$text.
673: "\n\nalwaysrun:\n\n";
674: }
675: elsif ($mode eq 'build') {
676: my $binfo;
677: my $tword;
678: my $command2;
679: my @deps;
680: foreach my $bi (@buildinfo) {
681: my ($target,$source,$command,$trigger,@deps)=split(/\;/,$bi);
682: $tword=''; $tword=' alwaysrun' if $trigger eq 'always run';
683: $command=~s/\/([^\/]*)$//;
684: $command2="cd $command; sh ./$1;\\";
685: my $depstring;
686: my $depstring2="\t\t\@echo '';\\\n";
687: my $olddep;
688: foreach my $dep (@deps) {
689: unless ($olddep) {
690: $olddep=$deps[$#deps];
691: }
692: $depstring.="\telif !(test -r $command/$dep);\\\n";
693: $depstring.="\t\tthen echo ".
694: "\"**** WARNING **** missing the file: ".
695: "$command/$dep\";\\\n";
696: $depstring.="\t\ttest -e $source || test -e $target || echo ".
697: "'**** ERROR **** neither source=$source nor target=".
698: "$target exist and they cannot be built';\\\n";
699: $depstring.="\t\tmake -f Makefile.build ${source}___DEPS;\\\n";
700: if ($olddep) {
701: $depstring2.="\t\tECODE=0;\\\n";
702: $depstring2.="\t\t! test -e $source && test -r $command/$olddep &&".
703: " { perl filecompare.pl -B $command/$olddep $target || ECODE=\$\$?; } && { [ \$\$ECODE != \"2\" ] || echo \"**** WARNING **** dependency $command/$olddep is newer than target file $target; SOMETHING MAY BE WRONG\"; };\\\n";
704: }
705: $olddep=$dep;
706: }
707: $binfo.="$source: $tword\n".
708: "\t\@if !(echo \"\");\\\n\t\tthen echo ".
709: "\"**** WARNING **** Strange shell. ".
710: "Check your path settings.\";\\\n".
711: $depstring.
712: "\telse \\\n\t\t$command2\n\tfi\n\n";
713: $binfo.="${source}___DEPS:\n".$depstring2."\t\tECODE=0;\n\n";
714: }
715: return 'all: '.join(' ',@buildall)."\n\n".
716: $text.
717: $binfo."\n".
718: "alwaysrun:\n\n";
719: }
720: else {
721: return '';
722: }
723: }
724: # ---------------------------------------------------- Format fileglobs section
725: sub format_fileglobs {
726:
727: }
728: # -------------------------------------------------------- Format links section
729: # deprecated.. currently <link></link>'s are included in <files></files>
730: sub format_links {
731: my $text=$parser->get_text('/links');
732: $parser->get_tag('/links');
733: if ($mode eq 'html') {
734: return $links="\n<br />BEGIN LINKS\n$text\n<br />END LINKS\n";
735: }
736: elsif ($mode eq 'install') {
737: return "\n".'links:'."\n\t".$text;
738: }
739: else {
740: return '';
741: }
742: }
743: # --------------------------------------------------------- Format file section
744: sub format_file {
745: my @tokeninfo=@_;
746: $file=''; $source=''; $target=''; $categoryname=''; $description='';
747: $note=''; $build=''; $status=''; $dependencies='';
748: my $text=&trim($parser->get_text('/file'));
749: my $buildtest;
750: if ($source) {
751: $parser->get_tag('/file');
752: if ($mode eq 'html') {
753: return ($file="\n<br />BEGIN FILE\n".
754: "$source $target $categoryname $description $note " .
755: "$build $status $dependencies" .
756: "\nEND FILE");
757: }
758: elsif ($mode eq 'install' && $categoryname ne 'conf') {
759: if ($build) {
760: my $bi=$sourceroot.'/'.$source.';'.$build.';'.
761: $dependencies;
762: my ($source2,$command,$trigger,@deps)=split(/\;/,$bi);
763: $tword=''; $tword=' alwaysrun' if $trigger eq 'always run';
764: $command=~s/\/([^\/]*)$//;
765: $command2="cd $command; sh ./$1;\\";
766: my $depstring;
767: foreach my $dep (@deps) {
768: $depstring.=<<END;
769: ECODE=0; DEP=''; \\
770: test -e $command/$dep || (echo '**** WARNING **** cannot evaluate status of dependency $command/$dep (for building ${sourceroot}/${source} with)'); DEP="1"; \\
771: [ -n DEP ] && { perl filecompare.pl -B $command/$dep ${targetroot}/${target} || ECODE=\$\$?; } || DEP="1"; \\
772: case "\$\$ECODE" in \\
773: 2) echo "**** WARNING **** dependency $command/$dep is newer than target file ${targetroot}/${target}; you may want to run make build";; \\
774: esac; \\
775: END
776: }
777: chomp $depstring;
778: $buildtest=<<END;
779: \@if !(test -e "${sourceroot}/${source}") && !(test -e "${targetroot}/${target}"); then \\
780: echo "**** ERROR **** ${sourceroot}/${source} is missing and is also not present at target location ${targetroot}/${target}; you must run make build"; exit; \\
781: END
782: $buildtest.=<<END if $depstring;
783: elif !(test -e "${sourceroot}/${source}"); then \\
784: $depstring
785: END
786: $buildtest.=<<END;
787: fi
788: END
789: }
790: my $bflag='-b';
791: $bflag='-g' if $dependencies or $buildlink;
792: return <<END;
793: $buildtest \@if !(test -e "${sourceroot}/${source}"); then \\
794: echo "**** WARNING **** CVS source file does not exist: ${sourceroot}/${source}"; \\
795: else \\
796: ECODE=0; \\
797: perl filecompare.pl $bflag ${sourceroot}/${source} ${targetroot}/${target} || ECODE=\$\$?; \\
798: case "\$\$ECODE" in \\
799: 1) echo "${targetroot}/${target} is unchanged";; \\
800: 2) echo "**** WARNING **** target file ${targetroot}/${target} is newer than CVS source; creating ${targetroot}/${target}.lpmlnewfile instead" && install -o www -g www -m 0500 ${sourceroot}/${source} ${targetroot}/${target}.lpmlnewfile;; \\
801: 0) echo "install -o www -g www -m 0500 ${sourceroot}/${source} ${targetroot}/${target}" && install -o www -g www -m 0500 ${sourceroot}/${source} ${targetroot}/${target};; \\
802: esac; \\
803: fi
804: END
805: # return "\t".'@test -e '.$sourceroot.'/'.$source.
806: # ' && perl filecompare.pl -b '.$sourceroot.'/'.$source.' '.
807: # $targetroot.'/'.$target.
808: # ' && install '.
809: # $categoryhash{$categoryname}.' '.
810: # $sourceroot.'/'.$source.' '.
811: # $targetroot.'/'.$target.
812: # ' || echo "**** LON-CAPA WARNING '.
813: # '**** CVS source file does not exist: '.$sourceroot.'/'.
814: # $source.'"'."\n";
815: }
816: elsif ($mode eq 'configinstall' && $categoryname eq 'conf') {
817: push @configall,$targetroot.'/'.$target;
818: return $targetroot.'/'.$target.': alwaysrun'."\n".
819: "\t".'@echo -n ""; ECODE=0 && { perl filecompare.pl -G '.$sourceroot.'/'.$source.' '.$targetroot.'/'.$target.' || ECODE=$$?; } && { [ $$ECODE != "2" ] || (install '.$categoryhash{$categoryname}.' '.
820: $sourceroot.'/'.$source.' '.
821: $targetroot.'/'.$target.'.lpmlnewconf'.
822: ' && echo "*** CONFIGURATION FILE CHANGE ***" && echo "'.
823: 'You likely need to compare contents of '.
824: ''.$targetroot.'/'.$target.' with the new '.
825: ''.$targetroot.'/'.$target.'.lpmlnewconf"'.
826: "); };\n\n";
827: }
828: elsif ($mode eq 'build' && $build) {
829: push @buildall,$sourceroot.'/'.$source;
830: push @buildinfo,$targetroot.'/'.$target.';'.$sourceroot.'/'.
831: $source.';'.$build.';'.
832: $dependencies;
833: # return '# need to build '.$source.";
834: }
835: else {
836: return '';
837: }
838: }
839: return '';
840: }
841: # --------------------------------------------------------- Format link section
842: sub format_link {
843: my @tokeninfo=@_;
844: $link=''; $linkto=''; $target=''; $categoryname=''; $description='';
845: $note=''; $build=''; $status=''; $dependencies='';
846: my $text=&trim($parser->get_text('/link'));
847: if ($linkto) {
848: $parser->get_tag('/link');
849: if ($mode eq 'html') {
850: return $link="\n<br />BEGIN LINK\n".
851: "$linkto $target $categoryname $description $note " .
852: "$build $status $dependencies" .
853: "\nEND LINK";
854: }
855: elsif ($mode eq 'install') {
856: my @targets=map {s/^\s*//;s/\s$//;$_} split(/\;/,$target);
857: foreach my $tgt (@targets) {
858: push @links,"\t".'ln -fs /'.$linkto.' /'.$targetroot.$tgt.
859: "\n";
860: }
861: return '';
862: }
863: else {
864: return '';
865: }
866: }
867: return '';
868: }
869: # ----------------------------------------------------- Format fileglob section
870: sub format_fileglob {
871: my @tokeninfo=@_;
872: $fileglob=''; $glob=''; $sourcedir='';
873: $targetdir=''; $categoryname=''; $description='';
874: $note=''; $build=''; $status=''; $dependencies='';
875: $filenames='';
876: my $text=&trim($parser->get_text('/fileglob'));
877: if ($sourcedir) {
878: $parser->get_tag('/fileglob');
879: if ($mode eq 'html') {
880: return $fileglob="\n<br />BEGIN FILEGLOB\n".
881: "$glob sourcedir $targetdir $categoryname $description $note ".
882: "$build $status $dependencies $filenames" .
883: "\nEND FILEGLOB";
884: }
885: elsif ($mode eq 'install') {
886: return "\t".'install '.
887: $categoryhash{$categoryname}.' '.
888: $sourceroot.'/'.$sourcedir.'[^C][^V][^S]'.$glob.' '.
889: $targetroot.'/'.$targetdir.'.'."\n";
890: }
891: else {
892: return '';
893: }
894: }
895: return '';
896: }
897: # ---------------------------------------------------- Format sourcedir section
898: sub format_sourcedir {
899: my @tokeninfo=@_;
900: $sourcedir='';
901: my $text=&trim($parser->get_text('/sourcedir'));
902: if ($text) {
903: $parser->get_tag('/sourcedir');
904: $sourcedir=$text;
905: }
906: return '';
907: }
908: # ------------------------------------------------------- Format target section
909: sub format_target {
910: my @tokeninfo=@_;
911: $target='';
912: my $text=&trim($parser->get_text('/target'));
913: if ($text) {
914: $parser->get_tag('/target');
915: $target=$text;
916: }
917: return '';
918: }
919: # ------------------------------------------------------- Format source section
920: sub format_source {
921: my @tokeninfo=@_;
922: $source='';
923: my $text=&trim($parser->get_text('/source'));
924: if ($text) {
925: $parser->get_tag('/source');
926: $source=$text;
927: }
928: return '';
929: }
930: # --------------------------------------------------------- Format note section
931: sub format_note {
932: my @tokeninfo=@_;
933: $note='';
934: my $text=&trim($parser->get_text('/note'));
935: if ($text) {
936: $parser->get_tag('/note');
937: $note=$text;
938: }
939: return '';
940:
941: }
942: # -------------------------------------------------------- Format build section
943: sub format_build {
944: my @tokeninfo=@_;
945: $build='';
946: my $text=&trim($parser->get_text('/build'));
947: if ($text) {
948: $parser->get_tag('/build');
949: $build=$sourceroot.'/'.$text.';'.$tokeninfo[2]{'trigger'};
950: }
951: return '';
952: }
953: # -------------------------------------------------------- Format build section
954: sub format_buildlink {
955: my @tokeninfo=@_;
956: $buildlink='';
957: my $text=&trim($parser->get_text('/buildlink'));
958: if ($text) {
959: $parser->get_tag('/buildlink');
960: $buildlink=$sourceroot.'/'.$text;
961: }
962: return '';
963: }
964: # ------------------------------------------------------- Format status section
965: sub format_status {
966: my @tokeninfo=@_;
967: $status='';
968: my $text=&trim($parser->get_text('/status'));
969: if ($text) {
970: $parser->get_tag('/status');
971: $status=$text;
972: }
973: return '';
974: }
975: # ------------------------------------------------- Format dependencies section
976: sub format_dependencies {
977: my @tokeninfo=@_;
978: $dependencies='';
979: my $text=&trim($parser->get_text('/dependencies'));
980: if ($text) {
981: $parser->get_tag('/dependencies');
982: $dependencies=join(';',
983: (map {s/^\s*//;s/\s$//;$_} split(/\;/,$text)));
984: }
985: return '';
986: }
987: # --------------------------------------------------------- Format glob section
988: sub format_glob {
989: my @tokeninfo=@_;
990: $glob='';
991: my $text=&trim($parser->get_text('/glob'));
992: if ($text) {
993: $parser->get_tag('/glob');
994: $glob=$text;
995: }
996: return '';
997: }
998: # ---------------------------------------------------- Format filenames section
999: sub format_filenames {
1000: my @tokeninfo=@_;
1001: my $text=&trim($parser->get_text('/filenames'));
1002: if ($text) {
1003: $parser->get_tag('/filenames');
1004: $filenames=$text;
1005: }
1006: return '';
1007: }
1008: # ------------------------------------------------------- Format linkto section
1009: sub format_linkto {
1010: my @tokeninfo=@_;
1011: my $text=&trim($parser->get_text('/linkto'));
1012: if ($text) {
1013: $parser->get_tag('/linkto');
1014: $linkto=$text;
1015: }
1016: return '';
1017: }
1018: # ------------------------------------- Render less-than and greater-than signs
1019: sub htmlsafe {
1020: my $text=@_[0];
1021: $text =~ s/</</g;
1022: $text =~ s/>/>/g;
1023: return $text;
1024: }
1025: # --------------------------------------- remove starting and ending whitespace
1026: sub trim {
1027: my ($s)=@_; $s=~s/^\s*//; $s=~s/\s*$//; return $s;
1028: }
1029:
1030: # ----------------------------------- POD (plain old documentation, CPAN style)
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>