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