: "@(#)fglpp.sh 0.0b" # # Created by: marcog@ctonline.it # On: Wed Nov 5 12:08:19 MET 1997 # Contents: fglpp, a precompiler for Informix-4gl # # This shell script will install several files (and possibly # directories) in your hard drive. # It is suggested that it be run from an empty subdir, since # failing to do so might result in partial file installation # and / or disk cluttering. # Be aware that its use and that of its contents may have # limitations as set forth in the welcome screen and the archive # contents itself. # Possible switches: # # -n doesn't check for file presence # -q for (almost) quiet operation # # Files in this archive: # # fglpp/fglpp # fglpp/p4gl # fglpp/readme # # Here's all the shell utilities usage that might cause problems. # Edit appropriately if you are stuck. # AWK=${AWK:-awk} filesize() { ls -l $1 | $AWK '{print $5}' } PG=`find /bin /usr/bin /usr/lbin -name pg -print` if [ -z "$PG" ] then PG=more fi # # get parms # QUIET=false NOCHECK=false while [ $# -ne 0 ] do case $1 in -n) NOCHECK=true ;; -q) QUIET=true ;; *) echo Usage: $0 [-c] [-q] exit 1 ;; esac shift done # # display welcome text - it may not fit on the screen, so we need a paginator # tput clear $PG <<'EOF-entry' This shell script will install fglpp, a precompiler for Informix-4gl. An ad hoc directory named fglpp will be created in the current path to hold fglpp files. If, for any reason, you do not wish to install fglpp, hit now to abort installation EOF-entry # # more does not wait for a key while displaying last screen # if [ $PG = more ] then read a unset a fi # # create directories as needed # mkdir -p fglpp # # begin fglpp # if [ -f fglpp/fglpp -a $NOCHECK != true ] then echo $0: fglpp/fglpp already exists else if [ $QUIET != true ] then echo fglpp/fglpp \(4683 characters\) fi cat >fglpp/fglpp <<'EOF-fglpp' #! /usr/bin/awk -f # fglpp - A 4gl precompiler (could have called it 'mouse4gl', though) # # Marco Greco (marcog@ctonline.it), Catania, Italy # # Initial release: Apr 96 # Current release: Oct 97 # # NOTICE # Permission to use, copy, modify and redistribute this software and # its documentation is hereby granted without fee provided that # # - all copies of the software and related documentation contain this # notice and authorship information, UNMODIFIED # # - no fee is charged for the physical act of redistributing this # software or modified copies thereof # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INCIDENTAL, # INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED # OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING # OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # ALL RISKS CONNECTED TO THE USE OF THIS SOFTWARE OR IMPOSSIBILITY # THEREOF LIE SOLELY ON YOU. # USE OF THIS SOFTWARE CONSTITUES AGREEMENT WITH THE ABOVE TERMS # AND CONDITIONS. # BEGIN { # token separator FS="[ \t]*[()\+-/=<>!,\*\\[\\]][ \t]*|[ \t]+" if (ARGC<4) { print "bad # of parms" exit } # save include search path for later for (i=4; i of filestack[++filepoint]=t[2] curfile=t[2] continue } # defining some constant, here if ($0 ~ /^#define/) { buff=$0 sub("#define[ \t]+", "") sub("#.*", "") term=$1 sub(term "[ \t]+", "") for (i=1; i<=NF; i++) if ($i in defs) sub($i, defs[$i]) defs[term]=$0 if (!(filepoint||not_a_4gl)) print buff > of continue } # for the sake of line counts, skip included comment lines... if ($0 ~ /^#|^--/) { if (!(filepoint||not_a_4gl)) print > of continue } # ...and included empty lines if (!NF) { if (not_a_4gl||!filepoint) print > of continue } # globals "filename" directive if ($0 ~ /^[^#]*globals *\".*\"/) { if (!inglobals) { n=split($0, t, "\"") if (globalsdone) $0="{" $0 "}" else $0="{" $0 "} globals \"" gf "\"" filestack[++filepoint]=t[2] curfile=t[2] nextrowoutput=gf inglobals=filepoint } else error=1 nootherglobals=0 } # end globals directive if ($0 ~ /end *globals/) { if (inglobals==filepoint && inglobals) { gsub("end *globals", "") inglobals=0 nextrowoutput=of globalsdone=1 close(filestack[filepoint--]) } else error=1 nootherglobals=0 } # plain globals directive if ($0 ~ /[^#]*globals/) { if (nootherglobals) if (inglobals==filepoint && inglobals) { if (globalsdone) sub("globals", "") } else error=1 nootherglobals=1 } # database directive if ($0 ~ /[^#]*database *[^ ]*/) { if (inglobals==filepoint && inglobals) { if (globalsdone) sub("database *[^ ]*", "") } else error=dbcount dbcount++ } # plain line, perform substitutions for (i=1; i<=NF; i++) if ($i in defs) sub($i, defs[$i]) if (error) { error=0 print $0 " # fglpp: probable error" > rowoutput } else print > rowoutput } } #at the end of the fair, terminate output globals file, if needed END { if (globalsdone) print "end globals" > gf } EOF-fglpp if [ `filesize fglpp/fglpp` -ne 4683 ] then echo $0: fglpp/fglpp extracted with wrong size fi fi # # end fglpp # # begin p4gl # if [ -f fglpp/p4gl -a $NOCHECK != true ] then echo $0: fglpp/p4gl already exists else if [ $QUIET != true ] then echo fglpp/p4gl \(1656 characters\) fi cat >fglpp/p4gl <<'EOF-p4gl' # p4gl - script that demostrates fglpp usage # # Marco Greco (marcog@ctonline.it), Catania, Italy # # Initial release: Apr 96 # Current release: Dec 96 # # # Usage: p4gl file.4gl... # # NOTICE # Permission to use, copy, modify and redistribute this software and # its documentation is hereby granted without fee provided that # # - all copies of the software and related documentation contain this # notice and authorship information, UNMODIFIED # # - no fee is charged for the physical act of redistributing this # software or modified copies thereof # # THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, # EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY # WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. # # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INCIDENTAL, # INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER # RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED # OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING # OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # # ALL RISKS CONNECTED TO THE USE OF THIS SOFTWARE OR IMPOSSIBILITY # THEREOF LIE SOLELY ON YOU. # USE OF THIS SOFTWARE CONSTITUES AGREEMENT WITH THE ABOVE TERMS # AND CONDITIONS. # for file in $@ do # # get basename and directory of file # sp=`dirname $file` fn=`basename $file .4gl` # # search for globals and include files in the input file directory # nawk -f fglpp $file glb$$ fglpp$$.4gl $sp c4gl -c fglpp$$.4gl -o $fn.o done # # now that we're thru, drop the temporary files # rm glb$$ fglpp$$.4gl EOF-p4gl if [ `filesize fglpp/p4gl` -ne 1656 ] then echo $0: fglpp/p4gl extracted with wrong size fi fi # # end p4gl # # begin readme # if [ -f fglpp/readme -a $NOCHECK != true ] then echo $0: fglpp/readme already exists else if [ $QUIET != true ] then echo fglpp/readme \(3981 characters\) fi cat >fglpp/readme <<'EOF-readme' Fglpp documentation ~~~~~~~~~~~~~~~~~~~ Contents: fglpp - the tool p4gl - sample shell script readme - this readme file Author: Marco Greco (marcog@ctonline.it), Catania, Italy Initial release: Apr 96 Current release: Oct 97 Usage: nawk -f fglpp input.4gl tempglobals output.4gl [ search_dirs... ] where input.4gl is the file to be preprocessed tempglobals is the temporary globals file referenced by output.4gl output.4gl is the preprocessed file to be passed to c4gl or fglpc search_dirs is a list of directories where #include or globals files can be found Directives: #define name token_string #include "filename" Notes: Fglpp was written mostly because existing 4gl preprocessing tools (m4gl and ppcc4gl) do not apply (or allow, for that matter) #define directives within globals files referenced by the files to be preprocessed By contrast, with fglpp is possible to use code like the following: sample.4gl: | globals.4gl: ~~~~~~~~~~~ | ~~~~~~~~~~~ ... | ... #define arraysize 10 | globals | define globals "globals.4gl" | my_array array[arraysize] of ... | ... for i=1 to arraysize | end globals ... | end for | or: sample.4gl: | globals.4gl: ~~~~~~~~~~~ | ~~~~~~~~~~~ ... | #define arraysize 10 globals "globals.4gl" | globals | define for i=1 to arraysize | my_array array[arraysize] of ... ... | ... end for | end globals or even: sample.4gl: | globals.4gl: ~~~~~~~~~~~ | ~~~~~~~~~~~ ... | ... #include "projectdefs" | globals | define globals "globals.4gl" | my_array array[arraysize] of ... | ... for i=1 to arraysize | end globals ... | end for | and have arraysize defined in projectdefs. Note that the first or third example give you the possibility to have different arraysize for different applications (and you could even use, in different applications, different types for the same globals variable) Unlike ppcc4gl, fglpp tries to preserve the line count of the file to be preprocessed. It does this by not writing the the ouput file #define directives or comments found in #include files, so if you refrain from #including code, the line count of the output file will match that of the input file. M4gl achieves the same result by discarding anything but define directives from included files. This altogether precludes the possibility of including code in the source file, unless you hack with m4 directives on your own. Also, m4gl does not permit to define something within the input file itself (of course, it's pretty easy to extend m4gl with such a capability). On the other hand, fglpp lacks all the beautiful features of cpp and m4. #define & #include directives may appear anywhere in the input or globals files. #include directives can be freely nested. Globals and #include files can be placed, besides than in the current directory, in any of the directories specified in the command line. Note that globals and end globals statements should appear in globals files only, and not in #include files referenced by the former. If you do differently, fglpp will try to make sense of your code, but it's not guaranteed to succeed. Lastly, as a bonus, fglpp will simulate support for multiple globals files, if your 4gl release does not support them. Restrictions: To partly address speed issues, fglpp currently uses pattern matching for #define substitutions. This, while being as much as 3 times faster than proper substitution (i.e. match & substr operations), is not completely secure, and could lead to the wrong token being substituted for poorly named #defines. This *usually* leads to compile-time errors, so fear not incomprehensible run time behaviour (that is, if you refrain from naming a definition like a substring of another). To be on the safe side I use unique definition prefixes (T_ for types, K_ for constants, etc). The general rule is not to use definition names that are substrings of other tokens. EOF-readme if [ `filesize fglpp/readme` -ne 3981 ] then echo $0: fglpp/readme extracted with wrong size fi fi # # end readme # $PG fglpp/readme