brp

back

NAME

brp - line oriented universal preprocesser using posix-sh

SYNOPSIS

sh ./yourcode [-mw]

EXAMPLE

this script works by just copying a sh-script to your code head. all the codes are written at the 10-lines. -[mw] is defined in it too.

  • eg1 (src.abc.xyz)
#include <emsg: see ... '~$ sh aaa.sh.c -h'   (other opt:no/-m/-w/)>    /*
C='^[/][/*]SH_'     ;O=${0##*[/]};R=`dirname $0`;R=${R%/}/;R0=$R$O;R=$R${O%%.*}
O=${0##*.};Rs=$R.$O;Rm=$R.tmp.$O;Rh=$R.h;R=$Rs$Rh$Rm;Rp='printf %s\n ';Rc=:;O="
";[ "${R##*$R0*}" = '' ]&&$Rp"$0:NGsuffix"&&exit 1;R='sed -ne ';Cm=$R'"/[E]ND/!d
:l;n;p;bl"<$R0>$Rm;$Rp"$Rm"';RB=$($R"s/${C}OP//p"<$R0|(F=mw;while read -r a b;do
B=${a%:};F=`$Rp"$F"|$R"s#$B:*##1;p"`${a%_};$Rp"C$B=\$(cat<<'E'$O$b${O}E$O)";done
$Rp"R1=$F"));Rw=$R'"/$C$R/!d;:l;n;/${C}ED/q;p;bl"<$R0';Cw="(R=LS;$Rw;$Rw>&3;R=HD
$Rw;R=SC;$Rw>&3)"'>$Rh 3>$Rs;$Rp"$Rh $Rs"';Re=eval\ ;$Re"$RB";while getopts $R1\
 R;do case $R in \?)exit 1;;*)$Re"O$R=\$OPTARG";Rc=$Rc$O`$Re'$Rp"$C'$R\"`;;esac
done;[ "$Rc" = : ]&&Rc=$Cm;shift $((OPTIND-1));$Re"$C_$O$Rc";exit  #END GPLv3+*/
//SH_OP a echo "hw"
//SH_OP z pwd; ls -al

(run)~$ sh src.abc.xyz -a    #>> hw
(run)~$ sh src.abc.xyz -z    #>> disp info

  • eg2 (src.sh.c)
#inc...
    ...#END
//SH_LS
//this code license is XXX...
//SH_ED

//SH_HD
int myf(void);
//SH_ED

/*SH_SC*/
int myf(void){puts("hw");return 0;}
int main(int argc, char** argv){return myf();}
//SH_ED

(run)
~$ sh src.sh.c -m    #>> output tMpfile (brp.tmp.c) and disp “brp.tmp.c”
~$ sh src.sh.c   #>> same as the above. noopt is statically fixed to -m
… -m opt (or noopt) works as

  1. delete the header script.
  2. write it to a tmpfile. (aaa.tmp.c etc)
  3. disp filename to stdout.

~$ sh brp.sh.c -w    #>> make brp.h + brp.c. if brp.sh.java, brp.h + brp.java
… -w(output double file) opt works as

  1. write SH_LS - SH_ED(LS_block) to both brp.h/brp.c
  2. add HD_block to brp.h and add SC_block to brp.c
  3. disp filename to stdout. (brp.h, brp.c)
  • eg3 (src.sh.c)
#inc..(header script)..#END
//SH_OP a echo "hello"
//SH_OP b: z=100;echo "good-bye $2 $Ob $1 $z"   #Ob ...optarg of -b

..(license block)..

//SH_OP x date
//SH_OP y echo "he said, "; eval "$Ca"      #Ca ... Command -a...

(run)
~$ sh brp.sh.c -a    #>> hello
~$ sh brp.sh.c -a -x -a    #>> hello y1999.m1.d31 hello
~$ sh brp.sh.c -y    #>> he said, hello
~$ sh brp.sh.c -b 123 ag1 ag2    #>> good-bye ag2 123 ag1 100

option setting format

    //SH_OP b: z=100;echo "good-bye $2 $Ob $1 $z $R0"
        1  2 3                 4 

1- dfl opthead is "//SH_OP" or "/*SH_OP". see below '$C'. 
2- separate with blank char(spaces or tabs)
3- optchar allows only [a-zA-Z0-9] + '_'(see below). add ':' if you use optarg.
4- write raw sh-script with ONE LINE.
  1-2char var names R?, C?, O? are reserved.(R,C,O,Ra,R7,Cg,O5 ...)
  optarg is set to $O? ( a: >> $Oa ,  v: >> $Ov etc)

- reserved words
  $R0,Rm,Rs,Rh ... orig/tMp/src/header filename. ($Rm == ./aaa.tmp.c etc)
    filename uses topname+last suffix.  eg) $R0: ./brp.xx.yy.py3,   $Rm: ./brp.py3
    original filename should avoid tmp/src/header name.
    (sh sh_aaa.c -w >>> sh_aaa.h / **sh_aaa.c** ...orig destroyed)  

  $C? ... $Cm/$Cw etc. used for opt command buffer
    //SH_OP a echo "hw";echo "$Rm"      #>>sh brp.sh.c -a ...hw aaa.tmp.c
    //SH_OP b printf "$Ca"      #>> sh brp.sh.c -b ... echo "hw";echo "$Rm"
    //SH_OP c eval "$Ca"        #>> sh brp.sh.c -c ... works as equals to -a

  $C ... comment sed-regex. default is C='^[/][/*]SH_' ...//SH_xx or /*SH_yy
     brp uses linecmt as directive. if you want to use other
     pg-lang(python etc), edit srctop 'C=...' directly with BRE-regex.

      shell : C='^#ANYSTR_';    >>  #ANYSTR_LS, #ANYSTR_ED etc
      python: C='^["]["]["]MARKER_'; >> """MARKER_OP   etc
      BASIC : C="^[']SH_";      >>'SH_OP etc

     $C is used as below. escape slash '/' plz. 
      sed -e "/${C}ED/"  ...  bad:C='^/[/*]SH_'  good:C='^\/[/*]SH_'

  $O? ... optargs.      eg) //SH_OP a: echo "$Oa"  .. sh brp.sh.c -a 11 ..11
  $O  ... newline(\n).  eg) //SH_OP a echo "a${O}b" >> disp a(\n)b
  $0,1,2 ..normal args. this pg uses getopts. checked opts are removed.
    eg) //SH_OP a echo "$1"     #>> ~$ sh foo.sh.c -a -- hw     >> hw

- dupulicated defination
  adopt new one if option setting is duplicate.
    //SH_OP a echo "hw" >> ignored. sh brp.sh.c -a  -> disp "gw"
    //SH_OP a echo "gw"
    //SH_OP w echo "123" >> overwrite dflopt. you cant remap old one

- preceding command
  if you set optchar '_'(0x5F underscore), it will run at first automatically.
  this optchar works as preprocesser.
  (set)
    //SH_OP _ echo "preset AA";AA=1
    /*SH_OP a echo "$AA"    #*/
    //SH_OP 1 echo "hw"
  (exec)
    ~$ brp.sh.c -a      #>> disp "preset AA", "1"
    ~$ brp.sh.c -a      #>> disp "preset AA", "hw"
    ~$ brp.sh.c         #>> disp "preset AA" and drop brp.c/brp.h

- opt 'm/w' is defined at the header script and uses SH_xx (LS,HD,SC,ED)
- SH_xx (OP,LS,HD,SC,ED) suffixes are fixed
- linetop '#include...' is assert() for c/cpp. (run ~$ gcc brp.sh.c)
  you can delete if you want.

appendix

--- src.cpp
    #inc...(script)...#END
    
    #include <iostream>
    int main(void){ std::cout << "hw" << std::endl;}
    //SH_OP b eval "$Cm";g++ "$Rm"; ./a.out

(run)~$ sh aaa.brp.c -b #>> hw
---

---src.c
    #inc...(script)...#END
    
    #include <stdio.h>
    int main(void){ puts("hw");}
    //add -L./ -lm -DTEST -O2 -Wall

    //SH_OP o buf=`sed -ne 's@^//add@@p'<$R0`
    //SH_OP b eval "$Co"; eval "$Cm"; gcc $Rm $buf

(run)~$ sh -x src.sh.c -b       #>> gcc src.tmp.c -L./ -lm -DTEST -O2 -Wall
---

-one liner sample 
  Cm='sed -ne "/[E]ND/{n;bl};d;:l;p;n;bl"<"$R0">"$Rm";echo "$Rm"'
  >>
  sed -ne '...' < "$R0" > "$Rm"
  echo "$Rm"
  >>
  cat 'foo.sh.c' | sed -ne '..see below..' > foo.tmp.c
  echo "foo.tmp.c"
    
-sed command
  sed -ne '/[E]ND/{n;bl};d;:l;p;n;bl'

  -n: no print. print only when requested
  -e: expression of sed-script

  >>(explain sed command with pseudo code)
  if (line==/END/){  .../[E]ND/
    n(ext read) ...n (if not -n opt, print nowline & readnext)
    goto label l ...b l (b=jump/goto. babc -> b abc -> goto abc)
  }
  del line ...d (del line & read nextline & *goto top*. d cmd is hard worker)
  label l:      ... :l (label. ':' + 'label name') 
  p(rint line)      ... p
  n(extline read)   ... n
  goto label l      ... b l
  
  ...sed cmd is difficult but very powerful. add option '--posix' to avoid
  bashism if you use gnused.  eg) ~$ sed --posix -e '/hello/p'
    https://www.gnu.org/software/sed/manual/sed.html (verbose but bashism)
    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.html
    ~$ man sed

-edit string with shell
  posix-sed cant use shortest match, but shell is possible(shotest+longest).
    str="aa_bb_cc"
    echo "${str#*_}"    #>> bb_cc (match aa_ and del)
    echo "${str##*_}"   #>> cc (longet)
    echo "${str%_*}"    #>> aa_bb (from tail)
    echo "${str%%_*}"   #>> aa

  The way to remember is '# is to the left of % at keyboard' or
  '# is often used at the beginning of comments'.
    
  shell pattern(glob pattern) is very similar to regex.
    aa_bb_cc -> a_bb_cc
    reg: s/^.//g  sh: ${str#?}  ... any one char. reg:'.'    sh:'?'
    
    aa_bb_cc -> (del)
    reg: ^[.]*  sh: ${str#*}    ... all. sh can uses wild card.
    
    aa_bb_cc -> aa_
    reg: [^a_]*  sh: ${str%%[!a_]*} ... not.  reg:'^'    sh:'!'
        ...[], bracket works as same, 'one char'
    
    escape
    sh: ${str%123"*"*}  ... "*" uses as literal. 0123*567 -> 0
  
  - see also
  https://en.wikipedia.org/wiki/Glob_%28programming%29
  ~$ man sh     #and input '/pattern' + enter + 'n' + shift 'n'

back