diff --git a/CONFIG.pl b/CONFIG.pl new file mode 100644 index 0000000..b488652 --- /dev/null +++ b/CONFIG.pl @@ -0,0 +1,10 @@ + +$PACKAGE="man2md"; +$VERSION="0.1"; +$PROJECT="webutils"; +$COPYLEFT="(c) R.Jaksa 2018 GPLv3"; + +# include "colors.pl" +# include "support.pl" +# include "help.pl" + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..3470dce --- /dev/null +++ b/Makefile @@ -0,0 +1,28 @@ +PATH := $(PATH):UTIL +SRC := $(shell find . -type f -name '*.pl' | grep -v OFF/ | xargs grep -l '\#!' | cut -b3-) +BIN := $(SRC:%.pl=%) + +all: $(BIN) README.md + +%: %.pl *.pl + perlpp $< > $@ + @chmod 755 $@ + +install: all + makeinstall -f $(BIN) + +clean: + rm -fv $(BIN) + +push: all + make clean + git add . + git commit -m update + git push -f origin master + +mrproper: clean + rm -fv README.md + +README.md: $(BIN) + $< -h | man2md > $@ + diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..3e10614 --- /dev/null +++ b/NEWS @@ -0,0 +1,2 @@ +0.2 - added context + added timestamps diff --git a/README.md b/README.md new file mode 100644 index 0000000..2bfa4d8 --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +### NAME +man2md - man to (github) markdown convertor + +### USAGE + man topic > topic.txt + man2md topic.txt > topic.md + + or: + man topic | man2md + +### DESCRIPTION +Man2md just converts manpage or an interactive help, if it is man-like +formatted, into the markdown format suitable for the github README.md. + +### OPTIONS + -h This help. + +### VERSION +man2md-0.1 (c) R.Jaksa 2018 GPLv3 + + diff --git a/UTIL/getversion b/UTIL/getversion new file mode 100755 index 0000000..281c331 --- /dev/null +++ b/UTIL/getversion @@ -0,0 +1,306 @@ +#!/bin/sh + +PACKAGE="getversion" +VERSION="0.4" +PROJECT="makeutils" +COPYLEFT="(c) R.Jaksa 2009, GPLv3" + +CC_="\033[36m"; # color cyan +CG_="\033[32m"; # color green +CR_="\033[31m"; # color red +CW_="\033[37m"; # color white +CD_="\033[0m"; # color default + +# --------------------------------------------------------------------- HELP + +function printhelp () { +help=" +${CC_}NAME$CD_ + getversion - get version information for package + +${CC_}USAGE$CD_ + getversion [${CC_}OPTIONS$CD_] + +${CC_}DESCRIPTION$CD_ + The getversion utility auto-detects the version information for + the package rooted in current directory. It does so by examination + of possible configuration files, or filenames. + For not identified values the \"unknown\" keyword will be used. + +${CC_}OPTIONS$CD_ + ${CC_}-pkg${CD_} Print the name of ${CC_}package${CD_} only. + ${CC_}-ver${CD_} Print the ${CC_}version${CD_} number of package only. + ${CC_}-prj${CD_} Print the name of parent ${CC_}project${CD_} for this package. + ${CC_}-pnm${CD_} Print the full ${CC_}package name${CD_}, including the version number. + ${CC_}-cpy${CD_} Print the ${CC_}copyleft${CD_}/copyright announcement of the package. + ${CC_}-dot${CD_} Print the ${CC_}dot${CD_} character between package name and version. + + ${CC_}-h${CD_} This help. + ${CC_}-version${CD_} The version of this (getversion) utility. + +${CC_}PERL LANGUAGE$CD_ + For the perl language, files ${CC_}CONFIG.pl${CD_} and ${CC_}VERSION.pl${CD_} are examined + (in this order). In the case of singlefile package, this single + file is examined. Following code is the example of information, + we look for: + + ${CW_}\$PACKAGE=\"package-name\";${CD_} + ${CW_}\$VERSION=\"1.13\";${CD_} + ${CW_}\$PROJECT=\"project-name\";${CD_} + ${CW_}\$COPYLEFT=\"(c) The.Author 2009, GPLv3\";${CD_} + +${CC_}C LANGUAGE$CD_ + In the c language, the ${CC_}VERSION.h${CD_} file is scanned for the code: + + ${CW_}#define PACKAGE \"package-name\"${CD_} + ${CW_}#define VERSION \"1.13\"${CD_} + ${CW_}#define PROJECT \"project-name\"${CD_} + ${CW_}#define COPYLEFT \"(c) The.Author 2009, GPLv3\"${CD_} + +${CC_}SHELL SCRIPTS$CD_ + The shell file (the singlefile package) is scanned for: + + ${CW_}PACKAGE=\"package-name\"${CD_} + ${CW_}VERSION=\"1.13\"${CD_} + ${CW_}PROJECT=\"project-name\"${CD_} + ${CW_}COPYLEFT=\"(c) The.Author 2009, GPLv3\"${CD_} + +${CC_}VERSION FILE$CD_ + In other types of packages the ${CC_}VERSION${CD_} file can be used. + It's syntax is: + + ${CW_}PACKAGE: package-name${CD_} + ${CW_}VERSION: 1.13${CD_} + ${CW_}PROJECT: project-name${CD_} + ${CW_}COPYLEFT: The.Author 2009, GPLv3${CD_} + +${CC_}HEAD COMMENT$CD_ + Alternatively a note in head comment of file (a comment in first + ten lines of file) can be used. Keywords are Version, Copyleft, + Copyright, and (c) or (C). For instance: + + ${CW_}/* Package ABC Version 2.13, Copyleft The.Author 2009, GPLv3 */${CD_} + +${CC_}VERSION$CD_ + ${PACKAGE}.$VERSION $COPYLEFT + +" +printf "$help" +exit 0; } + +# --------------------------------------------------------------------- ARGS + +for arg in $*; do + if test $arg = "-h"; then printhelp; exit 0; + elif test $arg = "-version"; then echo $VERSION; exit 0; + elif test $arg = "-pkg"; then PKG_ONLY=1 + elif test $arg = "-ver"; then VER_ONLY=1 + elif test $arg = "-prj"; then PRJ_ONLY=1 + elif test $arg = "-pnm"; then PNM_ONLY=1 + elif test $arg = "-cpy"; then CPY_ONLY=1 + elif test $arg = "-dot"; then DOT_ONLY=1; fi +done + +PKG="" # PACKAGE +VER="" # VERSION +PRJ="" # PROJECT +PNM="" # PKGNAME +CPY="" # COPYLEFT +DOT="." # DOT is the character between PKG and VER in PNM + +# --------------------------------------------------------- SINGLEFILE CHECK + +if test `find . -type f | wc -l` -eq 1; then SINGLEFILE=yes; + SINGLEFILE_FILE=`find . -type f | sed s:^./::` + SINGLEFILE_BASENAME=`echo $SINGLEFILE_FILE | sed 's:\..*$::'` + if grep -q -E '^#![ ]*/.*/perl' *; then SINGLEFILE=perl; + elif grep -q -E '^#![ ]*/.*/sh' *; then SINGLEFILE=sh; fi +fi + +# ------------------------------------------------------------ GET VARIABLES + +function getvar () { CMD=$1; +if test "x$FILE" != "x"; then + S="read from file $CG_$FILE$CD_" + X=`$CMD "$FILE" PACKAGE`; if test "x$X" != "x"; then PKG=$X; PKGs=$S; fi + X=`$CMD "$FILE" VERSION`; if test "x$X" != "x"; then VER=$X; VERs=$S; fi + X=`$CMD "$FILE" PROJECT`; if test "x$X" != "x"; then PRJ=$X; PRJs=$S; fi + X=`$CMD "$FILE" COPYLEFT`; if test "x$X" != "x"; then CPY=$X; CPYs=$S; fi + X=`$CMD "$FILE" COPYRIGHT`; if test "x$X" != "x"; then CPY=$X; CPYs=$S; fi +fi; } + +# --------------------------------------------------------------------- PERL + +function perlvar () { + cat "$1" |\ + grep "\$$2=" | head -n 1 |\ + sed "s:\$$2=\"\?::" |\ + sed "s:\"\?;::"; } + +if test "x$SINGLEFILE" = "xperl"; then FILE=$SINGLEFILE_FILE; +elif test -f CONFIG.pl; then FILE=CONFIG.pl +elif test -f VERSION.pl; then FILE=VERSION.pl +else # look for the first perl file with "$PACKAGE=" instead + IFS="\n"; for i in *; do + if grep -q -E '^#![ ]*/.*/perl' "$i"; then true; else continue; fi + if grep -q -E '\$PACKAGE=' "$i"; then true; else continue; fi + FILE="$i"; break; + done; IFS=" " +fi + +getvar perlvar + +# ----------------------------------------------------------------------- SH + +function shvar () { + cat "$1" |\ + grep "^[ ]*$2=\"\?[a-zA-Z0-9.,\(\)_-]\+\"\?" | head -n 1 |\ + sed "s:$2=\"\?::" |\ + sed "s:;$::" |\ + sed "s:\"$::"; } + +if test "x$SINGLEFILE" = "xsh"; then FILE=$SINGLEFILE_FILE; +else FILE="" +fi + +getvar shvar + +# ------------------------------------------------------------------------ C + +function cvar () { + cat "$1" |\ + grep "^[ ]*\#[ ]*define[ ]\+$2[ ]\+" | head -n 1 |\ + sed "s:.*define[ ]\+$2[ ]\+::" |\ + sed "s:^\"::" |\ + sed "s:\"$::"; } + +if test -f VERSION.h; then FILE=VERSION.h +else FILE="" +fi + +getvar cvar + +# ---------------------------------------------------------------------- CFG + +function cfgvar () { + cat "$1" |\ + grep "$2: " | head -n 1 |\ + sed "s/$2: //"; } + +if test -f VERSION; then FILE=VERSION +fi + +getvar cfgvar + +# ------------------------------------------------------ SINGLEFILE FILENAME + +if test "x$PKG" = "x"; then + if test "x$SINGLEFILE" != "x"; then + PKG=$SINGLEFILE_BASENAME + PKGs="from filename $CG_$SINGLEFILE_FILE$CD_" + fi +fi + +# ------------------------------------------------ VERSION FROM HEAD COMMENT + +function verhead () { + head "$1" | grep "Version" | sed 's:.*Version \([0-9.]*\).*$:\1:'; } + +if test "x$VER" = "x"; then + if test "x$SINGLEFILE" != "x"; then + VER_HEAD=`verhead "$SINGLEFILE_FILE"` + if test "x$VER_HEAD" != "x"; then + VER=$VER_HEAD + VERs="from head-comment in $CG_$SINGLEFILE_FILE$CD_" + fi + fi +fi + +# ----------------------------------------------- COPYLEFT FROM HEAD COMMENT + +function copyleft_head () { + head "$1" | grep "[Cc]opyleft" | sed 's:.*[Cc]opyleft \(.*\)$:\1:'; } +function copyright_head () { + head "$1" | grep "[Cc]opyright" | sed 's:.*[Cc]opyright \(.*\)$:\1:'; } +function cbracket_head () { + head "$1" | grep "([Cc])" | sed 's:.*([Cc]) \(.*\)$:\1:'; } + +if test "x$CPY" = "x"; then + if test "x$SINGLEFILE" != "x"; then + if test "x$CPY_HEAD" = "x"; then CPY_HEAD=` copyleft_head "$SINGLEFILE_FILE"`; fi + if test "x$CPY_HEAD" = "x"; then CPY_HEAD=`copyright_head "$SINGLEFILE_FILE"`; fi + if test "x$CPY_HEAD" = "x"; then CPY_HEAD=` cbracket_head "$SINGLEFILE_FILE"`; fi + if test "x$CPY_HEAD" != "x"; then + CPY=$CPY_HEAD + CPYs="from head-comment in $CG_$SINGLEFILE_FILE$CD_" + fi + fi +fi + +# ------------------------------------------------------------------ DERIVED + +# NUMEND is the last digit of pkg, if it ends by digit +NUMEND=`echo $PKG | sed 's:^.*\([0-9]\)$:\1:' | sed 's:[^0-9]*::'` +if test "x$NUMEND" != "x"; then DOT="-"; fi + +if test "x$PKG" != "x"; then + if test "x$VER" != "x"; then + PNM="$PKG$DOT$VER" + PNMs="derived from $CC_$PKG$CD_ & $CC_$VER$CD_" + else + PNM="$PKG" + PNMs="derived from $CC_$PKG$CD_" + fi +fi + +if test "x$PRJ" = "x" -a "x$PKG" != "x"; then + PRJ="$PKG" + PRJs="derived from $CC_$PKG$CD_" +fi + +# ----------------------------------------------------------------- UNKNOWNS + +if test "x$PKG" = "x"; then PKG="unknown"; fi +if test "x$VER" = "x"; then VER="unknown"; fi +if test "x$PRJ" = "x"; then PRJ="unknown"; fi +if test "x$PNM" = "x"; then PNM="unknown"; fi +if test "x$CPY" = "x"; then CPY="unknown"; fi + +# ---------------------------------------------------------- CUSTOM PRINTOUT + +if test "x$PKG_ONLY" != "x"; then echo "$PKG"; exit 0; fi +if test "x$VER_ONLY" != "x"; then echo "$VER"; exit 0; fi +if test "x$PRJ_ONLY" != "x"; then echo "$PRJ"; exit 0; fi +if test "x$PNM_ONLY" != "x"; then echo "$PNM"; exit 0; fi +if test "x$CPY_ONLY" != "x"; then echo "$CPY"; exit 0; fi +if test "x$DOT_ONLY" != "x"; then echo "$DOT"; exit 0; fi + +# --------------------------------------------------------- DEFAULT PRINTOUT + +if test "x$SINGLEFILE" != "x"; then + printf "singlefile: $CG_$SINGLEFILE_FILE$CD_" + if test "x$SINGLEFILE" != "xyes"; then printf " (language $SINGLEFILE)"; fi + printf "\n" +fi + +printf " package: $CC_$PKG$CD_" +if test "x$PKGs" != "x"; then printf " ($PKGs)"; fi +printf "\n" + +printf " version: $CC_$VER$CD_" +if test "x$VERs" != "x"; then printf " ($VERs)"; fi +printf "\n" + +printf " project: $CC_$PRJ$CD_" +if test "x$PRJs" != "x"; then printf " ($PRJs)"; fi +printf "\n" + +printf " pkgname: $CC_$PNM$CD_" +if test "x$PNMs" != "x"; then printf " ($PNMs)"; fi +printf "\n" + +printf " copyleft: $CC_$CPY$CD_" +if test "x$CPYs" != "x"; then printf " ($CPYs)"; fi +printf "\n" + +# -------------------------------------------------------------------------- diff --git a/UTIL/makeinstall b/UTIL/makeinstall new file mode 100755 index 0000000..b7ca06c --- /dev/null +++ b/UTIL/makeinstall @@ -0,0 +1,486 @@ +#!/usr/bin/perl + +$PACKAGE="makeinstall"; +$VERSION="0.4"; +$COPYLEFT="(c) R.Jaksa 2009, GPLv3"; +$PROJECT="makeutils"; + +$CR_="\033[31m"; # color red +$CG_="\033[32m"; # color green +$CM_="\033[35m"; # color magenta +$CC_="\033[36m"; # color cyan +$CW_="\033[37m"; # color white +$CD_="\033[0m"; # color default + +# ------------------------------------------------------------------------ NEWS +# +# 0.4 - bin/ install subdirectories bugfix +# - default Y/n answer for other letters is now the "no" +# - dat/dat/ bugfix +# - added lib.pl/ support +# +# ------------------------------------------------------------------------ HELP +$HELP_MAIN=<{input}=$i; } + +# inputs debug message +if($DEBUG) { + dhprint "inputs"; + foreach $k (keys %FILES) { print $CG_.$k.$CD_." "; } + print "\n"; } + +# ------------------------------------------------------------- PREFIX ANALYSIS + +$INSTTYPE="map" if $PREFIX eq "/map"; +$INSTTYPE="dir" if $PREFIX eq "/opt"; +$INSTTYPE="usr" if $PREFIX=~/^\/usr/; +$INSTTYPE="dir" if $PREFIX eq "/tmp"; +$INSTTYPE="dir" if not $INSTTYPE; + +sub try { + if(-w $_[1]) { + dprint "existing prefix",$_[1] if $DEBUG; + $INSTTYPE=$_[0]; + return $_[1]; } + dprint "missing prefix",$_[1] if $DEBUG; + return; } + +$PREFIX=try "map","/map" if not $PREFIX; +$PREFIX=try "dir","/opt" if not $PREFIX; +$PREFIX=try "usr","/usr/local" if not $PREFIX; +$PREFIX=try "usr","/usr" if not $PREFIX; +$PREFIX=try "dir","/tmp" if not $PREFIX; + +dprint "install mode",$INSTTYPE if $DEBUG; + +# ------------------------------------------------------------------ GETVERSION + +undef %PKG; +$PKG{package}=`getversion -pkg`; +$PKG{version}=`getversion -ver`; +$PKG{project}=`getversion -prj`; +$PKG{pkgname}=`getversion -pnm`; +foreach $k (keys %PKG) { $PKG{$k}=~s/\n$//; } + +if($DEBUG) { + dprint "package",$PKG{package}; + dprint "version",$PKG{version}; + dprint "project",$PKG{project}; + dprint "pkgname",$PKG{pkgname}; } + +# ----------------------------------------------------------------- DIRECTORIES +# undef $PACKAGE; $PACKAGE=$PKG{package} + +if($INSTTYPE eq "map") { + $BOX="/box/$PKG{project}/$PKG{pkgname}"; + $MAP="/map/$PKG{package}"; + xprint "box directory",$BOX; + xprint "map directory",$MAP; } + +if($INSTTYPE eq "dir") { + $OPT="$PREFIX/$PKG{package}"; + xprint "opt directory",$OPT; } + +if($INSTTYPE eq "usr") { + $USR=$PREFIX; + xprint "usr directory",$USR; } + +# -------------------------------------------------------- FILES PATHS ANALYSIS + +foreach $k (keys %FILES) { + my $file=$k; + while(not -f $file and $file=~/\//) { $file=$2 if $file=~/^(.*?)\/(.*)$/; } + if(-f $file) { + $FILES{$k}->{path}=$file; } + else { + eprint "Cannot find local file: $k"; exit 1; }} + +# -------------------------------------------------------------- TYPES ANALYSIS + +# 1st check the prefix +foreach $k (keys %FILES) { + $FILES{$k}->{type}="bin" if $k=~/[^a-z]bin\// or $k=~/^bin\//; + $FILES{$k}->{type}="bim" if $k=~/[^a-z]bim\// or $k=~/^bim\//; + $FILES{$k}->{type}="dat" if $k=~/[^a-z]dat\// or $k=~/^dat\//; + $FILES{$k}->{type}="libc" if $k=~/[^a-z]lib\.c\// or $k=~/^lib\.c\//; + $FILES{$k}->{type}="libpl" if $k=~/[^a-z]lib\.pl\// or $k=~/^lib\.pl\//; + $FILES{$k}->{type}="lib" if $k=~/[^a-z]lib\// or $k=~/^lib\//; + $FILES{$k}->{type}="inc" if $k=~/[^a-z]inc\// or $k=~/^inc\//; + # etc +} + +# 2nd some autodetect +foreach $k (keys %FILES) { + if(not $FILES{$k}->{type}) { + # guess it's bin if it is executable + if(-x $FILES{$k}->{path}) { + dprint "type guess","$k$CD_ (bin)" if $DEBUG; + $FILES{$k}->{type}="bin"; }}} + +# group files by type +undef %TYPE; +foreach $k (keys %FILES) { + if($FILES{$k}->{type}) { push @{$TYPE{$FILES{$k}->{type}}},$FILES{$k}->{path}; } + else { push @{$TYPE{unknown}},$FILES{$k}->{path}; }} + +# announce +foreach $t (sort keys %TYPE) { + hprint "$t files"; + foreach $f (@{$TYPE{$t}}) { print $CG_.$f.$CD_." "; } + print "\n"; } + +# -------------------------------------------------------------------- QUESTION + +sub answer_yes { + if($QUERY) { xprintnl(); exit 0; } + return 1 if $FORCED; + my $s=$_[0]; # the question + my $l=length($s); + my $e=""; for(my $i=0;$i<$HDRLEN-$l;$i++) { $e.=" "; } + print $e.$s.": "; + print $m if $m; + # get answer + print $CG_; + system "stty", '-icanon', 'eol', "\001"; + my $k; while(not $k=~/[YyNnQq\n]/) { $k=getc(STDIN); } + system "stty", 'icanon', 'eol', '^@'; + print $CD_; print "\n" if not $k eq "\n"; + # yes + if($k=~/[yY\n]/) { return 1; } + # no + return 0; } + +if(not answer_yes("proceed? Y/n")) { + eprint("did nothing, bye..."); + xprintnl(); + exit 0; } + +# --------------------------------------------------------------------- INSTALL + +# @dir=dir2array("."); +sub dir2array { + my $d=$_[0]; $d="." if not $_[0]; + if(not opendir(DIR,$d)) { eprint("Can't open directory $CD_$d$CR_ ($!)"); exit 1; } + my @dir=readdir(DIR); + closedir(DIR); + undef my @out; + foreach my $i (@dir) { + next if $i eq "."; + next if $i eq ".."; + push @out,$i; } + return @out; } + +# ($dirs,$files)=dir2array_rec(".","/bin"); +# recursive search in /bin, returns paths relative to "/bin/." +# $dirs and $files are references to arrays +sub dir2array_rec { + my $dir=$_[0]; # directory to search in, relative to $pre + my $pre=$_[1]; $pre="" if not $pre; # directory path + my @dir=dir2array("$pre/$dir"); + undef my @dirs; undef my @files; + foreach my $i (@dir) { + my $f="$pre/$dir/$i"; + if(-f $f) { push @files,"$dir/$i"; } + elsif(-d $f) { + push @dirs ,"$dir/$i"; + (my $d2,my $f2)=&dir2array_rec("$dir/$i",$pre); + foreach $j (@{$f2}) { push @files,$j; } + foreach $j (@{$d2}) { push @dirs ,$j; }}} + foreach $i (@dirs) { $i=~s/^\.\///; } + foreach $i (@files) { $i=~s/^\.\///; } + return ([@dirs],[@files]); } + +sub cmd { + my $s=$_[0]; $s=$_[1] if $_[1]; + my $msg=$_[0] if $_[1]; + xprint $msg,"$CC_$s$CD_"; + print $CW_; + system "$s"; + print $CD_; } + +# ----------------------------------------------------------------------------- + +sub makedir { + my $dir=$_[0]; $dir=$_[1] if $_[1]; + my $msg=$_[0] if $_[1]; + cmd "$msg","mkdir -p $dir" if not -d $dir; } + +# copy source to the destination point +sub xcopy { + my $src=$_[0]; my $srcx=$src; $srcx="\"$srcx\"" if $srcx=~/ /; + my $dst=$_[1]; + my $dstdir=$dst; $dstdir=~s/\/[^\/]*$//; + my $dstdirx=$dstdir; $dstdirx="\"$dstdirx\"" if $dstdirx=~/ /; + makedir "install",$dstdirx if ! -d $dstdirx; + if(-f $dst) { return if not `diff -q \"$src\" \"$dst\"`; } + cmd "install","cp $srcx $dstdirx"; } + +# link dest. file to the point where the source is linked (source is a link) +sub xlink { + my $src=$_[0]; + my $dst=$_[1]; my $dstx=$dst; $dstx="\"$dstx\"" if $dstx=~/ /; + my $dstdir=$dst; $dstdir=~s/\/[^\/]*$//; + my $dstdirx=$dstdir; $dstdirx="\"$dstdirx\"" if $dstdirx=~/ /; + my $srcl=readlink $src if -l $src; + my $srclx=$srcl; $srclx="\"$srclx\"" if $srclx=~/ /; + my $dstl=readlink $dst if -l $dst; + makedir "install",$dstdirx if ! -d $dstdirx; + if(not $dstl eq $srcl) { + cmd "install","rm $dstx" if -e $dst; + cmd "install","ln -s $srclx $dstx"; }} + +# xlink if file is link, xcopy if file is file +sub xlncp { + my $src=$_[0]; my $dst=$_[1]; + if( -l $src) { xlink $src,$dst; } + elsif(-f $src) { xcopy $src,$dst; }} + +# link source directory to destination point +sub dlink { + my $src=$_[0]; my $srcx=$src; $srcx="\"$srcx\"" if $srcx=~/ /; + my $dst=$_[1]; my $dstx=$dst; $dstx="\"$dstx\"" if $dstx=~/ /; + my $dstl=readlink $dst if -l $dst; + if(not $dstl eq $src) { + cmd "rm $dstx" if -e $dst; + cmd "ln -s $srcx $dstx"; }} + +# index file (or link) into directory +sub xndex { + my $src=$_[0]; my $srcx=$src; $srcx="\"$srcx\"" if $srcx=~/ /; + my $dst=$_[1]; my $dstx=$dst; $dstx="\"$dstx\"" if $dstx=~/ /; + my $dstl=readlink $dst if -l $dst; + my $srcl=readlink $src if -l $src; + my $dstdir=$dst; $dstdir=~s/\/[^\/]*$//; + my $dstdirx=$dstdir; $dstdirx="\"$dstdirx\"" if $dstdirx=~/ /; + my $srct=$src; $srct=$srcl if -l $src; # test-src = src or link to it + if((not $dstl eq $srct) or (not -l $dst)) { + cmd "index","rm $dstx" if -e $dst; + if(-l $src) { cmd "index","cp -d $srcx $dstdirx"; } + else { cmd "index","ln -s $srcx $dstx"; }}} + +# return basename of file +sub bnm { + my $f=$_[0]; + $f=~s/^.*\///; + return $f; } + +# bin/ installer +sub inst_bin { + if($INSTTYPE eq "map") { + makedir "bin directory","$BOX/bin"; dlink $BOX,$MAP; + foreach $f (@{$TYPE{bin}}) { xlncp $f,"$BOX/bin/".bnm($f); } + foreach $f (dir2array "$MAP/bin") { xndex "$MAP/bin/".bnm($f),"/bin/".bnm($f); } + return; } + if($INSTTYPE eq "dir") { + makedir "bin directory","$OPT/bin"; + foreach $f (@{$TYPE{bin}}) { xlncp $f,"$OPT/bin/".bnm($f); } + return; } + if($INSTTYPE eq "usr") { + makedir "bin directory","$USR/bin"; + foreach $f (@{$TYPE{bin}}) { xlncp $f,"$USR/bin/".bnm($f); } + return; }} + +# lib/ installer +sub inst_lib { + if($INSTTYPE eq "map") { + makedir "lib directory","$BOX/lib"; dlink $BOX,$MAP; + foreach $f (@{$TYPE{lib}}) { xlncp $f,"$BOX/lib/$f"; } + foreach $f (dir2array "$MAP/lib") { xndex "$MAP/lib/$f","/lib/$f"; } + return; } + if($INSTTYPE eq "dir") { + makedir "lib directory","$OPT/lib"; + foreach $f (@{$TYPE{lib}}) { xlncp $f,"$OPT/lib/$f"; } + return; } + if($INSTTYPE eq "usr") { + makedir "lib directory","$USR/lib"; + foreach $f (@{$TYPE{lib}}) { xlncp $f,"$USR/lib/$f"; } + return; }} + +# inc/ installer +sub inst_inc { + if($INSTTYPE eq "map") { + makedir "inc directory","$BOX/inc/$PKG{package}"; dlink $BOX,$MAP; + foreach $f (@{$TYPE{inc}}) { xlncp $f,"$BOX/inc/$PKG{package}/$f"; } + (my $dirs,my $files)=dir2array_rec ".","$MAP/inc/$PKG{package}"; + foreach $f (@{$dirs}) { makedir "dir index","/inc/$PKG{package}/$f"; } + foreach $f (@{$files}) { xndex "$MAP/inc/$PKG{package}/$f","/inc/$PKG{package}/$f"; } + return; } + if($INSTTYPE eq "dir") { + makedir "inc directory","$OPT/include/$PKG{package}"; + foreach $f (@{$TYPE{inc}}) { xlncp $f,"$OPT/include/$PKG{package}/$f"; } + return; } + if($INSTTYPE eq "usr") { + makedir "inc directory","$USR/include/$PKG{package}"; + foreach $f (@{$TYPE{inc}}) { xlncp $f,"$USR/include/$PKG{package}/$f"; } + return; }} + +# dat/ path normalizer +sub datnm { + my $f=$_[0]; + $f=~s/^dat\///; + return $f; } + +# dat/ installer +sub inst_dat { + if($INSTTYPE eq "map") { + makedir "$BOX/dat"; dlink $BOX,$MAP; + foreach $f (@{$TYPE{dat}}) { xlncp $f,"$BOX/dat/".datnm($f); } + return; } + if($INSTTYPE eq "dir") { + makedir "$OPT/dat"; + foreach $f (@{$TYPE{dat}}) { xlncp $f,"$OPT/dat/".datnm($f); } + return; } + if($INSTTYPE eq "usr") { + makedir "$USR/share/$PKG{package}"; + foreach $f (@{$TYPE{dat}}) { xlncp $f,"$USR/share/$PKG{package}/".datnm($f); } + return; }} + +# src/ installer (lib.c), differs for local lib.c files and main pkg sources +sub inst_libc { + my $DIR="/tmp"; + $DIR=$BOX if $INSTTYPE eq "map"; dlink $BOX,$MAP if $INSTTYPE eq "map"; + $DIR=$OPT if $INSTTYPE eq "dir"; + $DIR=$USR if $INSTTYPE eq "usr"; + makedir "lib.c directory","$DIR/lib.c/$PKG{pkgname}"; + foreach $k (keys %FILES) { + next if not $FILES{$k}->{type} eq "libc"; + my $pre=""; # inside lib.c directory prefix + if($k=~/^(.*)\/($FILES{$k}->{path})$/) { + $pre=$1; # the prefix directory + $pre=~s/^lib\.c\///; # strip the "lib.c/" + $pre="" if $pre eq "lib.c"; } # nothing if it's full prefix + $pre="lib.c/$pre/" if not $pre eq ""; + my $f=$FILES{$k}->{path}; + xlncp $f,"$DIR/$pre$f"; }} + +# src/ installer (lib.pl), differs for local lib.pl files and main pkg sources +sub inst_libpl { + my $DIR="/tmp"; + $DIR=$BOX if $INSTTYPE eq "map"; dlink $BOX,$MAP if $INSTTYPE eq "map"; + $DIR=$OPT if $INSTTYPE eq "dir"; + $DIR=$USR if $INSTTYPE eq "usr"; + makedir "lib.pl directory","$DIR/lib.pl/$PKG{pkgname}"; + foreach $k (keys %FILES) { + next if not $FILES{$k}->{type} eq "libpl"; + my $pre=""; # inside lib.pl directory prefix + if($k=~/^(.*)\/($FILES{$k}->{path})$/) { + $pre=$1; # the prefix directory + $pre=~s/^lib\.pl\///; # strip the "lib.pl/" + $pre="" if $pre eq "lib.pl"; } # nothing if it's full prefix + $pre="lib.pl/$pre/" if not $pre eq ""; + my $f=$FILES{$k}->{path}; + xlncp $f,"$DIR/$pre$f"; }} + +# install! +inst_bin if $TYPE{bin}; +inst_dat if $TYPE{dat}; +inst_libc if $TYPE{libc}; +inst_libpl if $TYPE{libpl}; +inst_lib if $TYPE{lib}; +inst_inc if $TYPE{inc}; + +xprintnl(); + +# ----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- +# ----------------------------------------------------------------------------- diff --git a/UTIL/perlpp b/UTIL/perlpp new file mode 100755 index 0000000..1f0c9e4 --- /dev/null +++ b/UTIL/perlpp @@ -0,0 +1,322 @@ +#!/usr/bin/perl +$PACKAGE="perlpp"; +$VERSION="0.6"; +$PROJECT="makeutils"; +$COPYLEFT="(c) R.Jaksa 2008, GPLv3"; + +$CC_="\033[36m"; # color cyan +$CR_="\033[31m"; # color red +$CW_="\033[37m"; # color white +$CD_="\033[0m"; # color default + +foreach $i (@ARGV) { if($i eq "-h") { printhelp($0); exit 0; }} +foreach $i (@ARGV) { if($i eq "-d") { $DEBUG=1; $i=""; last; }} +foreach $i (@ARGV) { if($i eq "-m") { $MARK=1; $i=""; last; }} +foreach $i (@ARGV) { if($i eq "-p") { $PREPREPROC=1; $i=""; last; }} +foreach $i (@ARGV) { if($i eq "-c") { $REMOVECOMMENTS=1; $i=""; last; }} +foreach $i (@ARGV) { if($i eq "-x") { $OVERWRITE=1; $i=""; last; }} + +# appendix files +@APFILE=(); +for($i=0;$i<$#ARGV;$i++) { + if($ARGV[$i] eq "-a" and -f $ARGV[$i+1]) { + push @APFILE,$ARGV[$i+1]; + $ARGV[$i]=""; $ARGV[$i+1]=""; last; }} + +# error/debug messages +sub error { print STDERR $CR_.$_[0].$CD_."\n"; } +sub debug { print STDERR $CC_.$_[0].$CD_."\n" if $DEBUG; } + +# inar(\@a,$i) - check whether the string is in an array +sub inar { local(*a)=$_[0]; my $s=$_[1]; + foreach $j (@a) { if($j eq $s) { return(1); }} + return(0); } + +# the cat +sub cat { + my $file=$_[0]; + my $s=""; + open(I,"$file") or error "Can't open file $file ($!)."; + while () { $s.=$_; } + close(I); + return $s; } + +# getdirs(\@out,"/path") put names of all dirs from /path into @out +sub getdirs { local(*dirs)=$_[0]; my $parent=$_[1]; + opendir(DIR,$parent); my @dir=readdir(DIR); closedir(DIR); + foreach my $i (@dir) { + next if $i=~/^\./; + my $path="$parent/$i"; + if(-d $path) { + push(@dirs,$path); + getdirs(\@dirs,$path); }}} + +# ---------------------------------------------------------- PREPARE THE GROUND + +# get list of subdirectories +getdirs(\@dirs,"."); + +# get file to overwrite +if($OVERWRITE) { + undef my @paths; # list of paths already recognized (we look for the last one) + foreach my $file (@ARGV) { # cycle through list of requested files + next if $file eq ""; # skip empty string(s) + my $path; + foreach my $dir (".",@dirs) { # look for path of actual file, cycle dirs + $path="$dir/$file"; # try every dir + next if inar(\@paths,$path); # skip already recognized path + last if -f $path; } # now if file on this path exists, it is! + $path="./$file" if not -f $path; # if file does not exist, use current dir + push @paths,$path; # push this path + debug "Overwrite candidate \"$path\"."; + $OVERWRITEFILE=$path; } + debug "We will overwrite the file \"$OVERWRITEFILE\"."; } + +# -------------------------------------------------------------- OUTPUT ROUTINE + +$OUTPUT=""; # content for the overwriting +sub output { + my $s=$_[0]; + if($OVERWRITE) { $OUTPUT.=$s; } + else { print $s; }} + +# --------------------------------------------------------------------- ADDFILE + +# process and add given file into output +sub addfile { + my $file=$_[0]; + my $path; + debug "Try to add file \"$file\" to the output."; + + # look for file recursively + foreach my $dir (".",@dirs) { + $path="$dir/$file"; + if(inar(\@INCLUDED,$path)) { + debug "File \"$path\" was already included."; + return; } + last if -f $path; } + if(not -f $path) { + error "File \"$path\" not found (requested as \"$file\")."; + return; } # not-found file cannot be added, so we return here + + # read the file + my $content=""; + debug "Add the file \"$path\" (requested as \"$file\")."; + $content=cat($path); + push @INCLUDED,$path; + + # preprocessor + if($PREPREPROC) { + $content=~s/\n\#.*[\n\t ]*$/ /; } # remove comments on last line + + # parse the file + my $AFTERCOMMENT=0; # 1 if we are on line just after removed comment + foreach $line (split(/\n/,$content)) { + + # remove emty lines after the comment too + if($REMOVECOMMENTS and $AFTERCOMMENT) { + if($line=~/^\h*$/) { $AFTERCOMMENT=1; next; } # if empty line + else { $AFTERCOMMENT=0; }} # otherwise + + # process include lines + my $RE=qr/^\h*\#\h*include\h+\"(.*)\"/; + if($line=~/$RE/) { + output "# START OF THE INCLUDE \"$1\"\n" if $MARK; + addfile($1); + output "# END OF THE INCLUDE \"$1\"\n" if $MARK; + next; } + + # process eval lines + my $RE=qr/^\h*\#\h*eval\h+\$(.*)/; + if($line=~/$RE/) { + my $VAR=$1; + my $VAL=$ENV{$VAR}; + debug "Evaluate directive eval: \$$VAR=\"$VAL\"."; + output "\$$VAR=\"$VAL\";\n"; + next; } + + # process debug-labels + my $RE=qr/^(.+?)\h*\#\(([a-zA-Z0-9_-]+)\)\#/; + if($line=~/$RE/) { + my $CODE=$1; + my $LABEL=$2; + # skip commented out active comment + if($CODE=~/^\h*\#/) { next; } + # dosomething-if condition; + elsif($CODE=~/^\h*(.*)\h+if\h+([^;]*?);(\h*\})?$/) { + my $c1=$1; my $c2=$2; my $b2=$3; + # print STDERR "=> if($c2) { $APX{$LABEL} $c1; } <=\n"; + if($c1=~/^(.*)\h?(next|return.*|exit.*)$/) { + output "if($c2) { $APX{$LABEL} $c1; }$b2\n"; } + else { + output "if($c2) { $c1; $APX{$LABEL} }$b2\n"; } + next; } + # ending } + elsif($CODE=~/^(.*?)\h*(next;|return.*?;|exit.*?;)?\h*\}([\h\}]*)\h*$/) { + my $c1=$1; my $c2=$2; my $b=$3; + # print STDERR "=> $c1 $APX{$LABEL} next; }}} <=\n"; + output "$c1 $APX{$LABEL} $c2 }$b\n"; next; } + # otherwise + else { + # print STDERR "=> $CODE $APX{$LABEL} <=\n"; + output "$CODE $APX{$LABEL}\n"; next; }} + + # remove comments + if($REMOVECOMMENTS) { + if($line=~/^\h*\#[^!]/) { # full-line comments + $AFTERCOMMENT=1; + next; } + my $RE=qr/^(.*[;\}])\h*\#.*$/; + if($line=~/$RE/) { # comments after semicolon or bracket + $line=~s/$RE/$1/; + output "$line\n"; + next; }} + + # regular lines + output "$line\n"; } + + # end of file + output ""; } + +# --------------------------------------------------------- LOAD APPENDIX FILES + +%APX=(); +foreach my $file (@APFILE) { + my $s=cat($file); + + # read .pl.debug file, look for single-lines with #(xyz)# comments + foreach my $line (split /\n/,$s) { + next if $line=~/^\h*$/; + next if $line=~/^\h*\#/; + if($line=~/^\h*(.+?)\h*\#\(([a-zA-Z0-9_-]+)\)\#/) { + my $all=$&; my $qall=quotemeta($all); + my $code=$1; + my $label=$2; + $APX{$label}=$code; + $s=~s/$qall//; }} + + # read .pl.debug file, look for code blocks starting with #(xyz)# label comment + my $RE=qr/\n\h*\#\((.+)\)\#\h*(.*)\n((.|\n)+?)\n\h*?\n/; + while($s=~/$RE/) { + my $label=$1; + my $comment=$2; + my $code=$3; + $APX{$label}=$code; + #$APXCOM{$label}=$comment; + $s=~s/$RE/\n\n/; } + + # report the junk left + foreach my $line (split /\n/,$s) { + next if $line=~/^\h*$/; + debug "Dummy code in appendix: $CR_$line$CD_"; }} + +# ------------------------------------------------------------------- MAIN LOOP + +undef my @INCLUDED; # list of files already included + +# add each requested file to the output +foreach my $file (@ARGV) { + next if $file eq ""; + addfile $file; } + +# overwrite file when requested, otherwise output is already printed on stdout +if($OVERWRITE) { + debug "Overwrite the file \"$OVERWRITEFILE\"."; + if(not open(O,">$OVERWRITEFILE")) { + error("Can't open \"$OVERWRITEFILE\" for writing ($!)."); + exit 1; } + print O $OUTPUT; + close(O); } + +# we are done now! +exit 0; + +# ------------------------------------------------------------------------ HELP + +sub printhelp { + my $DOLLAR="\$"; + my $help=<$file") or die "Can't create file $CG_$file$CD_ $CR_($!)$CD_."; #(writefile)# + print O $s; + close(O); } + +# read the first line +sub firstline { + my $file = $_[0]; + my $s; + open(FILE,"<$file") or die "Can't read file $CG_$file$CD_ $CR_($!)$CD_."; #(firstline)# + $s = ; + close(FILE); + return $s; } + +# --------------------------------------------------------------------------------------------------- + diff --git a/man2md.pl b/man2md.pl new file mode 100644 index 0000000..5674ddf --- /dev/null +++ b/man2md.pl @@ -0,0 +1,164 @@ +#!/usr/bin/perl +# Copyleft: R.Jaksa 2018, GNU General Public License version 3 +# include "CONFIG.pl" +# ------------------------------------------------------------------------------- HELP + +$HELP=< topic.txt + man2md topic.txt > topic.md + + or: + man topic | man2md + +DESCRIPTION + Man2md just converts manpage or an interactive help, if it is man-like + formatted, into the markdown format suitable for the github README.md. + +OPTIONS + -h This help. + +EOF + +# ------------------------------------------------------------------------------ ARGVS +foreach(@ARGV) { if($_ eq "-h") { printhelp $HELP; exit 0; }} + +our $INPUT; +foreach(@ARGV) { + next if $_ eq ""; + if(-f $_) { $INPUT=$_; $_=""; last; }} + +# ------------------------------------------------------------------------------ INPUT + +if(defined $INPUT) { + $RAW = `cat $INPUT`; } + +else { + while() { + $RAW .= "$_"; }} + +# ---------------------------------------------------------------------- PREPROCESSING + +# remove color escape sequences +$RAW =~ s/\033\[36m//g; # cyan +$RAW =~ s/\033\[37m//g; # white +$RAW =~ s/\033\[90m//g; # black +$RAW =~ s/\033\[0m//g; # default + +# titles +$RAW =~ s/\n([A-Z])/\n\#\#\# $1/g; +$RAW =~ s/\n([A-Za-z0-9-]+(\h+[A-Za-z0-9-]+)?(\h+[A-Za-z0-9-]+)?:)/\n\#\#\#\# $1/g; + +# multiple newlines +$RAW =~ s/\n\h*\n\h*(\n\h*)+/\n\n/g; + +# --------------------------------------------------------------------- SPLIT SECTIONS + +# split into sections +our @HEAD; # header text +our %HDPX; # header prefix +our %BODY; # section body +sub addsec { push @HEAD,$_[0]; $HDPX{$_[0]} = $_[1]; $BODY{$_[0]} = $_[2]; } + +my $head; # current header +my $hdpx; # header prefix +my $body; # current body +foreach my $s (split /\n/,$RAW) { + + # header => store past section + if($s =~ /^(\#\#*) (.*)\h*$/) { + addsec $head,$hdpx,$body and undef $body if defined $head and defined $body; + $head = $2; + $hdpx = $1; } + + # just line + else { + $body .= "$s\n" if defined $head; }} # store the body only for recognized head + +addsec $head,$hdpx,$body if defined $head and defined $body; +# print "$_\n$BODY{$_}" foreach @HEAD; exit 1; + +# --------------------------------------------------------------------- SECTIONS TYPES + +# list of sections always treated as regular +$REG=<