Annotation of nsdl/build/piml_parse.pl, revision 1.1

1.1     ! harris41    1: #!/usr/bin/perl
        !             2: 
        !             3: # -------------------------------------------------------- Documentation notice
        !             4: # Run "perldoc ./lpml_parse.pl" in order to best view the software
        !             5: # documentation internalized in this program.
        !             6: 
        !             7: # --------------------------------------------------------- License Information
        !             8: # The LearningOnline Network with CAPA
        !             9: # piml_parse.pl - Linux Packaging Markup Language parser
        !            10: #
        !            11: # $Id: piml_parse.pl,v 1.7 2002/04/08 12:51:03 harris41 Exp $
        !            12: #
        !            13: # Written by Scott Harrison, codeharrison@yahoo.com
        !            14: #
        !            15: # Copyright Michigan State University Board of Trustees
        !            16: #
        !            17: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
        !            18: #
        !            19: # LON-CAPA is free software; you can redistribute it and/or modify
        !            20: # it under the terms of the GNU General Public License as published by
        !            21: # the Free Software Foundation; either version 2 of the License, or
        !            22: # (at your option) any later version.
        !            23: #
        !            24: # LON-CAPA is distributed in the hope that it will be useful,
        !            25: # but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            26: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            27: # GNU General Public License for more details.
        !            28: #
        !            29: # You should have received a copy of the GNU General Public License
        !            30: # along with LON-CAPA; if not, write to the Free Software
        !            31: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
        !            32: #
        !            33: # /home/httpd/html/adm/gpl.txt
        !            34: #
        !            35: # http://www.lon-capa.org/
        !            36: #
        !            37: # YEAR=2002
        !            38: # 1/28,1/29,1/30,1/31,2/5,4/8 - Scott Harrison
        !            39: #
        !            40: ###
        !            41: 
        !            42: ###############################################################################
        !            43: ##                                                                           ##
        !            44: ## ORGANIZATION OF THIS PERL SCRIPT                                          ##
        !            45: ## 1. Notes                                                                  ##
        !            46: ## 2. Get command line arguments                                             ##
        !            47: ## 3. First pass through (grab distribution-specific information)            ##
        !            48: ## 4. Second pass through (parse out what is not necessary)                  ##
        !            49: ## 5. Third pass through (translate markup according to specified mode)      ##
        !            50: ## 6. Functions (most all just format contents of different markup tags)     ##
        !            51: ## 7. POD (plain old documentation, CPAN style)                              ##
        !            52: ##                                                                           ##
        !            53: ###############################################################################
        !            54: 
        !            55: # ----------------------------------------------------------------------- Notes
        !            56: #
        !            57: # I am using a multiple pass-through approach to parsing
        !            58: # the piml file.  This saves memory and makes sure the server
        !            59: # will never be overloaded.
        !            60: #
        !            61: # This is meant to parse files meeting the piml document type.
        !            62: # See piml.dtd.  PIML=Post Installation Markup Language.
        !            63: 
        !            64: use HTML::TokeParser;
        !            65: 
        !            66: my $usage=(<<END);
        !            67: **** ERROR ERROR ERROR ERROR ****
        !            68: Usage is for piml file to come in through standard input.
        !            69: 1st argument is the category permissions to use (runtime or development)
        !            70: 2nd argument is the distribution (default,redhat6.2,debian2.2,redhat7.1,etc).
        !            71: 3rd argument is to manually specify a targetroot
        !            72: 
        !            73: Only the 1st argument is mandatory for the program to run.
        !            74: 
        !            75: Example:
        !            76: 
        !            77: cat ../../doc/loncapafiles.piml |\\
        !            78: perl piml_parse.pl html development default /home/sherbert/loncapa /tmp/install
        !            79: END
        !            80: 
        !            81: # ------------------------------------------------- Grab command line arguments
        !            82: 
        !            83: my $mode;
        !            84: if (@ARGV==3) {
        !            85:     $mode = shift @ARGV;
        !            86: }
        !            87: else {
        !            88:     @ARGV=();shift @ARGV;
        !            89:     while(<>){} # throw away the input to avoid broken pipes
        !            90:     print $usage;
        !            91:     exit -1; # exit with error status
        !            92: }
        !            93: 
        !            94: my $categorytype;
        !            95: if (@ARGV) {
        !            96:     $categorytype = shift @ARGV;
        !            97: }
        !            98: 
        !            99: my $dist;
        !           100: if (@ARGV) {
        !           101:     $dist = shift @ARGV;
        !           102: }
        !           103: 
        !           104: my $targetroot;
        !           105: my $targetrootarg;
        !           106: if (@ARGV) {
        !           107:     $targetroot = shift @ARGV;
        !           108: }
        !           109: $targetroot=~s/\/$//;
        !           110: $targetrootarg=$targetroot;
        !           111: 
        !           112: my $logcmd='| tee -a WARNINGS';
        !           113: 
        !           114: my $invocation;
        !           115: # --------------------------------------------------- Record program invocation
        !           116: if ($mode eq 'install' or $mode eq 'configinstall' or $mode eq 'build') {
        !           117:     $invocation=(<<END);
        !           118: # Invocation: STDINPUT | piml_parse.pl
        !           119: #             1st argument (category type) is: $categorytype
        !           120: #             2nd argument (distribution) is: $dist
        !           121: #             3rd argument (targetroot) is: described below
        !           122: END
        !           123: }
        !           124: 
        !           125: # ---------------------------------------------------- Start first pass through
        !           126: my @parsecontents = <>;
        !           127: my $parsestring = join('',@parsecontents);
        !           128: my $outstring='';
        !           129: 
        !           130: # Need to make a pass through and figure out what defaults are
        !           131: # overrided.  Top-down overriding strategy (leaves don't know
        !           132: # about distant leaves).
        !           133: 
        !           134: my @hierarchy;
        !           135: $hierarchy[0]=0;
        !           136: my $hloc=0;
        !           137: my $token='';
        !           138: $parser = HTML::TokeParser->new(\$parsestring) or
        !           139:     die('can\'t create TokeParser object');
        !           140: $parser->xml_mode('1');
        !           141: my %hash;
        !           142: my $key;
        !           143: while ($token = $parser->get_token()) {
        !           144:     if ($token->[0] eq 'S') {
        !           145: 	$hloc++;
        !           146: 	$hierarchy[$hloc]++;
        !           147: 	$key=$token->[1].join(',',@hierarchy[0..($hloc-1)]);
        !           148: 	my $thisdist=' '.$token->[2]{'dist'}.' ';
        !           149: 	if ($thisdist eq ' default ') {
        !           150: 	    $hash{$key}=1; # there is a default setting for this key
        !           151: 	}
        !           152: 	elsif ($dist && $hash{$key}==1 && $thisdist=~/\s$dist\s/) {
        !           153: 	    $hash{$key}=2; # disregard default setting for this key if
        !           154: 	                   # there is a directly requested distribution match
        !           155: 	}
        !           156:     }
        !           157:     if ($token->[0] eq 'E') {
        !           158: 	$hloc--;
        !           159:     }
        !           160: }
        !           161: 
        !           162: # --------------------------------------------------- Start second pass through
        !           163: undef $hloc;
        !           164: undef @hierarchy;
        !           165: undef $parser;
        !           166: $hierarchy[0]=0;
        !           167: $parser = HTML::TokeParser->new(\$parsestring) or
        !           168:     die('can\'t create TokeParser object');
        !           169: $parser->xml_mode('1');
        !           170: my $cleanstring;
        !           171: while ($token = $parser->get_token()) {
        !           172:     if ($token->[0] eq 'S') {
        !           173: 	$hloc++;
        !           174: 	$hierarchy[$hloc]++;
        !           175: 	$key=$token->[1].join(',',@hierarchy[0..($hloc-1)]);
        !           176: 	my $thisdist=' '.$token->[2]{'dist'}.' ';
        !           177: 	# This conditional clause is set up to ignore two sets
        !           178: 	# of invalid conditions before accepting entry into
        !           179: 	# the cleanstring.
        !           180: 	if ($hash{$key}==2 and
        !           181: 	    !($thisdist eq '  ' or $thisdist =~/\s$dist\s/)) {
        !           182: 	    if ($token->[4]!~/\/>$/) {
        !           183: 		$parser->get_tag('/'.$token->[1]);
        !           184: 		$hloc--;
        !           185: 	    }
        !           186: 	}
        !           187: 	elsif ($thisdist ne '  ' and $thisdist!~/\s$dist\s/ and
        !           188: 	       !($thisdist eq ' default ' and $hash{$key}!=2)) {
        !           189: 	    if ($token->[4]!~/\/>$/) {
        !           190: 		$parser->get_tag('/'.$token->[1]);
        !           191: 		$hloc--;
        !           192: 	    }
        !           193: 	}
        !           194: 	else {
        !           195: 	    $cleanstring.=$token->[4];
        !           196: 	}
        !           197: 	if ($token->[4]=~/\/>$/) {
        !           198: #	    $hloc--;
        !           199: 	}
        !           200:     }
        !           201:     if ($token->[0] eq 'E') {
        !           202: 	$cleanstring.=$token->[2];
        !           203: 	$hloc--;
        !           204:     }
        !           205:     if ($token->[0] eq 'T') {
        !           206: 	$cleanstring.=$token->[1];
        !           207:     }
        !           208: }
        !           209: $cleanstring=&trim($cleanstring);
        !           210: $cleanstring=~s/\>\s*\n\s*\</\>\</g;
        !           211: 
        !           212: # ---------------------------------------------------- Start final pass through
        !           213: 
        !           214: # storage variables
        !           215: my $piml;
        !           216: my $categories;
        !           217: my @categorynamelist;
        !           218: my $category;
        !           219: my $category_att_name;
        !           220: my $category_att_type;
        !           221: my $chown;
        !           222: my $chmod;
        !           223: my $abbreviation; # space-free abbreviation; esp. for image names
        !           224: my $categoryname;
        !           225: my $description;
        !           226: my $files;
        !           227: my $file;
        !           228: my $target;
        !           229: my $note;
        !           230: my $commands;
        !           231: my $command;
        !           232: my $dependencies;
        !           233: my @links;
        !           234: my %categoryhash;
        !           235: my $dpathlength;
        !           236: my %fab; # file category abbreviation
        !           237: my $directory_count;
        !           238: my $file_count;
        !           239: my $link_count;
        !           240: my $fileglob_count;
        !           241: my $fileglobnames_count;
        !           242: my %categorycount;
        !           243: 
        !           244: my $mode;
        !           245: 
        !           246: my @buildall;
        !           247: my @buildinfo;
        !           248: 
        !           249: my @configall;
        !           250: 
        !           251: # Make new parser with distribution specific input
        !           252: undef($parser);
        !           253: $parser = HTML::TokeParser->new(\$cleanstring) or
        !           254:     die('can\'t create TokeParser object');
        !           255: $parser->xml_mode('1');
        !           256: 
        !           257: # Define handling methods for mode-dependent text rendering
        !           258: 
        !           259: $parser->{textify}={
        !           260:     specialnotices => \&format_specialnotices,
        !           261:     specialnotice => \&format_specialnotice,
        !           262:     targetroot => \&format_targetroot,
        !           263:     categories => \&format_categories,
        !           264:     category => \&format_category,
        !           265:     abbreviation => \&format_abbreviation,
        !           266:     chown => \&format_chown,
        !           267:     chmod => \&format_chmod,
        !           268:     categoryname => \&format_categoryname,
        !           269:     files => \&format_files,
        !           270:     file => \&format_file,
        !           271:     target => \&format_target,
        !           272:     note => \&format_note,
        !           273:     build => \&format_build,
        !           274:     dependencies => \&format_dependencies,
        !           275:     filenames => \&format_filenames,
        !           276:     perlscript => \&format_perlscript,
        !           277:     TARGET => \&format_TARGET,
        !           278:     };
        !           279: 
        !           280: my $text;
        !           281: my $token;
        !           282: undef($hloc);
        !           283: undef(@hierarchy);
        !           284: my $hloc;
        !           285: my @hierarchy2;
        !           286: while ($token = $parser->get_tag('piml')) {
        !           287:     &format_piml(@{$token});
        !           288:     $text = &trim($parser->get_text('/piml'));
        !           289:     $token = $parser->get_tag('/piml');
        !           290:     print($piml); 
        !           291:     print("\n");
        !           292:     print($text);
        !           293:     print("\n");
        !           294:     print(&end());
        !           295: }
        !           296: exit(0);
        !           297: 
        !           298: # ---------- Functions (most all just format contents of different markup tags)
        !           299: 
        !           300: # ------------------------ Final output at end of markup parsing and formatting
        !           301: sub end {
        !           302: 
        !           303: }
        !           304: 
        !           305: # ----------------------- Take in string to parse and the separation expression
        !           306: sub extract_array {
        !           307:     my ($stringtoparse,$sepexp) = @_;
        !           308:     my @a=split(/$sepexp/,$stringtoparse);
        !           309:     return \@a;
        !           310: }
        !           311: 
        !           312: # --------------------------------------------------------- Format piml section
        !           313: sub format_piml {
        !           314:     my (@tokeninfo)=@_;
        !           315:     my $date=`date`; chop $date;
        !           316:     $piml=<<END;
        !           317: #!/usr/bin/perl
        !           318: 
        !           319: # Generated from a PIML (Post Installation Markup Language) document
        !           320: 
        !           321: END
        !           322: }
        !           323: # --------------------------------------------------- Format targetroot section
        !           324: sub format_targetroot {
        !           325:     my $text=&trim($parser->get_text('/targetroot'));
        !           326:     $text=$targetroot if $targetroot;
        !           327:     $parser->get_tag('/targetroot');
        !           328:     return('# TARGET INSTALL LOCATION is "'.$targetroot."\"\n");
        !           329: }
        !           330: # -------------------------------------------------- Format perl script section
        !           331: sub format_perlscript {
        !           332:     my (@tokeninfo)=@_;
        !           333:     $mode=$tokeninfo[2]->{'mode'};
        !           334:     my $text=$parser->get_text('/perlscript');
        !           335:     $parser->get_tag('/perlscript');
        !           336:     if ($mode eq 'bg') {
        !           337: 	open(OUT,">/tmp/piml$$.pl");
        !           338: 	print(OUT $text);
        !           339: 	close(OUT);
        !           340: 	return(<<END);
        !           341: 	# launch background process for $target
        !           342: 	system("perl /tmp/piml$$.pl &");
        !           343: END
        !           344:     }
        !           345:     else {
        !           346: 	return($text);
        !           347:     }
        !           348: }
        !           349: # --------------------------------------------------------------- Format TARGET
        !           350: sub format_TARGET {
        !           351:     my (@tokeninfo)=@_;
        !           352:     $parser->get_tag('/TARGET');
        !           353:     return($target);
        !           354: }
        !           355: # --------------------------------------------------- Format categories section
        !           356: sub format_categories {
        !           357:     my $text=&trim($parser->get_text('/categories'));
        !           358:     $parser->get_tag('/categories');
        !           359:     return('# CATEGORIES'."\n".$text);
        !           360: }
        !           361: # --------------------------------------------------- Format categories section
        !           362: sub format_category {
        !           363:     my (@tokeninfo)=@_;
        !           364:     $category_att_name=$tokeninfo[2]->{'name'};
        !           365:     $category_att_type=$tokeninfo[2]->{'type'};
        !           366:     $abbreviation=''; $chmod='';$chown='';
        !           367:     $parser->get_text('/category');
        !           368:     $parser->get_tag('/category');
        !           369:     $fab{$category_att_name}=$abbreviation;
        !           370:     if ($category_att_type eq $categorytype) {
        !           371: 	my ($user,$group)=split(/\:/,$chown);
        !           372: 	$categoryhash{$category_att_name}='-o '.$user.' -g '.$group.
        !           373: 	    ' -m '.$chmod;
        !           374:     }
        !           375:     return('');
        !           376: }
        !           377: # --------------------------------------------------- Format categories section
        !           378: sub format_abbreviation {
        !           379:     my @tokeninfo=@_;
        !           380:     $abbreviation='';
        !           381:     my $text=&trim($parser->get_text('/abbreviation'));
        !           382:     if ($text) {
        !           383: 	$parser->get_tag('/abbreviation');
        !           384: 	$abbreviation=$text;
        !           385:     }
        !           386:     return('');
        !           387: }
        !           388: # -------------------------------------------------------- Format chown section
        !           389: sub format_chown {
        !           390:     my @tokeninfo=@_;
        !           391:     $chown='';
        !           392:     my $text=&trim($parser->get_text('/chown'));
        !           393:     if ($text) {
        !           394: 	$parser->get_tag('/chown');
        !           395: 	$chown=$text;
        !           396:     }
        !           397:     return('');
        !           398: }
        !           399: # -------------------------------------------------------- Format chmod section
        !           400: sub format_chmod {
        !           401:     my @tokeninfo=@_;
        !           402:     $chmod='';
        !           403:     my $text=&trim($parser->get_text('/chmod'));
        !           404:     if ($text) {
        !           405: 	$parser->get_tag('/chmod');
        !           406: 	$chmod=$text;
        !           407:     }
        !           408:     return('');
        !           409: }
        !           410: # ------------------------------------------------- Format categoryname section
        !           411: sub format_categoryname {
        !           412:     my @tokeninfo=@_;
        !           413:     $categoryname='';
        !           414:     my $text=&trim($parser->get_text('/categoryname'));
        !           415:     if ($text) {
        !           416: 	$parser->get_tag('/categoryname');
        !           417: 	$categoryname=$text;
        !           418:     }
        !           419:     return('');
        !           420: }
        !           421: # -------------------------------------------------------- Format files section
        !           422: sub format_files {
        !           423:     my $text=$parser->get_text('/files');
        !           424:     $parser->get_tag('/files');
        !           425:     return("\n".'# There are '.$file_count.' files this script works on'.
        !           426: 	"\n\n".$text);
        !           427: }
        !           428: # --------------------------------------------------------- Format file section
        !           429: sub format_file {
        !           430:     my @tokeninfo=@_;
        !           431:     $file=''; $source=''; $target=''; $categoryname=''; $description='';
        !           432:     $note=''; $build=''; $status=''; $dependencies='';
        !           433:     my $text=&trim($parser->get_text('/file'));
        !           434:     $file_count++;
        !           435:     $categorycount{$categoryname}++;
        !           436:     $parser->get_tag('/file');
        !           437:     return("# File: $target\n".
        !           438: 	"$text\n");
        !           439: }
        !           440: # ------------------------------------------------------- Format target section
        !           441: sub format_target {
        !           442:     my @tokeninfo=@_;
        !           443:     $target='';
        !           444:     my $text=&trim($parser->get_text('/target'));
        !           445:     if ($text) {
        !           446: 	$parser->get_tag('/target');
        !           447: 	$target=$targetrootarg.$text;
        !           448:     }
        !           449:     return('');
        !           450: }
        !           451: # --------------------------------------------------------- Format note section
        !           452: sub format_note {
        !           453:     my @tokeninfo=@_;
        !           454:     $note='';
        !           455:     my $aref;
        !           456:     my $text;
        !           457:     while ($aref=$parser->get_token()) {
        !           458: 	if ($aref->[0] eq 'E' && $aref->[1] eq 'note') {
        !           459: 	    last;
        !           460: 	}
        !           461: 	elsif ($aref->[0] eq 'S') {
        !           462: 	    $text.=$aref->[4];
        !           463: 	}
        !           464: 	elsif ($aref->[0] eq 'E') {
        !           465: 	    $text.=$aref->[2];
        !           466: 	}
        !           467: 	else {
        !           468: 	    $text.=$aref->[1];
        !           469: 	}
        !           470:     }
        !           471:     if ($text) {
        !           472: 	$note=$text;
        !           473:     }
        !           474:     return('');
        !           475: }
        !           476: # ------------------------------------------------- Format dependencies section
        !           477: sub format_dependencies {
        !           478:     my @tokeninfo=@_;
        !           479:     $dependencies='';
        !           480:     my $text=&trim($parser->get_text('/dependencies'));
        !           481:     if ($text) {
        !           482: 	$parser->get_tag('/dependencies');
        !           483: 	$dependencies=join(';',
        !           484: 			      (map {s/^\s*//;s/\s$//;$_} split(/\;/,$text)));
        !           485:     }
        !           486:     return('');
        !           487: }
        !           488: # ------------------------------------------------ Format specialnotice section
        !           489: sub format_specialnotices {
        !           490:     $parser->get_tag('/specialnotices');
        !           491:     return('');
        !           492: }
        !           493: # ------------------------------------------------ Format specialnotice section
        !           494: sub format_specialnotice {
        !           495:     $parser->get_tag('/specialnotice');
        !           496:     return('');
        !           497: }
        !           498: # ------------------------------------- Render less-than and greater-than signs
        !           499: sub htmlsafe {
        !           500:     my $text=@_[0];
        !           501:     $text =~ s/</&lt;/g;
        !           502:     $text =~ s/>/&gt;/g;
        !           503:     return($text);
        !           504: }
        !           505: # --------------------------------------- remove starting and ending whitespace
        !           506: sub trim {
        !           507:     my ($s)=@_; $s=~s/^\s*//; $s=~s/\s*$//; return($s);
        !           508: }
        !           509: 
        !           510: # ----------------------------------- POD (plain old documentation, CPAN style)
        !           511: 
        !           512: =pod
        !           513: 
        !           514: =head1 NAME
        !           515: 
        !           516: piml_parse.pl - This is meant to parse piml files (Post Installation Markup Language)
        !           517: 
        !           518: =head1 SYNOPSIS
        !           519: 
        !           520: Usage is for piml file to come in through standard input.
        !           521: 
        !           522: =over 4
        !           523: 
        !           524: =item * 
        !           525: 
        !           526: 1st argument is the category permissions to use (runtime or development)
        !           527: 
        !           528: =item *
        !           529: 
        !           530: 2nd argument is the distribution
        !           531: (default,redhat6.2,debian2.2,redhat7.1,etc).
        !           532: 
        !           533: =item *
        !           534: 
        !           535: 3rd argument is to manually specify a targetroot.
        !           536: 
        !           537: =back
        !           538: 
        !           539: Only the 1st argument is mandatory for the program to run.
        !           540: 
        !           541: Example:
        !           542: 
        !           543: cat ../../doc/loncapafiles.piml |\\
        !           544: perl piml_parse.pl html default /home/sherbert/loncapa /tmp/install
        !           545: 
        !           546: =head1 DESCRIPTION
        !           547: 
        !           548: I am using a multiple pass-through approach to parsing
        !           549: the piml file.  This saves memory and makes sure the server
        !           550: will never be overloaded.
        !           551: 
        !           552: =head1 README
        !           553: 
        !           554: I am using a multiple pass-through approach to parsing
        !           555: the piml file.  This saves memory and makes sure the server
        !           556: will never be overloaded.
        !           557: 
        !           558: =head1 PREREQUISITES
        !           559: 
        !           560: HTML::TokeParser
        !           561: 
        !           562: =head1 COREQUISITES
        !           563: 
        !           564: =head1 OSNAMES
        !           565: 
        !           566: linux
        !           567: 
        !           568: =head1 SCRIPT CATEGORIES
        !           569: 
        !           570: Packaging/Administrative
        !           571: 
        !           572: =head1 AUTHOR
        !           573: 
        !           574:  Scott Harrison
        !           575:  codeharrison@yahoo.com
        !           576: 
        !           577: Please let me know how/if you are finding this script useful and
        !           578: any/all suggestions.  -Scott
        !           579: 
        !           580: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>