Softpanorama

Home Switchboard Unix Administration Red Hat TCP/IP Networks Neoliberalism Toxic Managers
May the source be with you, but remember the KISS principle ;-)
Skepticism and critical thinking is not panacea, but can help to understand the world better

Beautifiers and Pretty Printers

This page introduced the notion of "fuzzy" prettyprinters -- prettyprinters that do not perform full lexical analysis of the source code  

News Programming style Recommended Links Program Understanding Defensive programming neatbash -- bash beautifier Neatperl -- a simple Perl prettyprinter
Python pretty printers Perl Prettyprinting C C++ HTML    
Multitarget verifiers Multitarget highlighters Multitarget beautifiers Compilers Algorithms Lexical analysis Debugging  
Unix History Admin Horror Stories Software Engineering Language Design and Programming Quotes Humor Random Findings Etc

Introduction

Beautifiers and pretty printers are essential language tools.  They accepts a program source file, and generates a listing and/or another equivalent source file which is nicely formatted according to the source language syntax, including first of all indentation of control statements

Unfortunately very few programmers use them. If you do not use please start now... that's a real life saver tool for any professional programmer.  Programmers spend around 50% of their time just looking at source code trying to understand it or find bugs.  Formatting source code can make them considerably more productive in this task, saving a significant amount of an time and efforts.

What is a beautifier? It is a language-specific utility that reformats a program to conform to a standard of presentation. Optionally it also can replace the  original file with the reformatted version (making a backup) but this is a more dangerous operation then just listing for comprehension and debugging purposes.  It requires perfect replication of lexical analyzer for the language in question.  That's why many prettyprinters from languages with complex lexical structure that are in use for a long time are sill considered by the original developers to be in beta (Perltidy is one example).

The most important task for any prettyprinter is the  revealing nesting level of each statement via indentation. For languages with nested functions, the function nesting level is the second one that needs to be displayed. In addition it also can improve readability by inserting blank lines after each procedure and some statements. Excessively long lines might be split into shorter ones or even refactored in "folding constant" mode.  Closing parenthesis of a block and opening keyword might be vertically aligned.  The amount of cosmetic changes depends on the esthetic preferences of the author of prettyprinter. My are pretty Spartan and I do not see much value in readability improvement described above outside the depiction of nesting level via indentation.

Among the advantages of using a beautifier:

 

Beautifier as part of defensive programming toolset

I use beautifiers with each language that I programmed until I get to Perl. When I first started learning Perl, I immediately began looking for a beautifier, and was surprised when I couldn't find one. From this point of view Perl definitely sucks... I became interested and wrote a couple of my own primitive beautifier Neatperl and Neatbash. They intentionally were designed to be short and simple (at the expense of functionality) and can be maintained independently by any qualified Perl programmer.  They also proved to be adequte for my purposes, despite their extreme simplicity. Hoping that my efforts can benefit other people I put current versions it on GitHub in 2019. 

Of course, there are several other tools for Perl that can beatify Perl programs: the most popular one is  pertidy. Even for bash you can find something like language-bash Parsing and pretty-printing Bash shell scripts

But both of those are complex tool that attempt to do lexical analysis of the program and that's a very tricky task. Resulting level of complexity makes them unmaintanable for a regular programmer.  

Moreover  Perl is very complex (but pretty regular) lexical structure so there is no guarantee that such pretty printer will not introduce subtle errors into the script.  The complexity of Perltidy reflect that fact. For more details see:

Then I realized that usage of beautifier is a part of defensive programming style and did some additional research (I am mot a newcomer to the field; I actually wrote my first beautifier with full lexical analysis of the language in late 70th (neatpl for PL/1) to help me to write a compiler form that relational algebra based language (pre SQL), for which implementation language was PL/1. But now we need to find a different approach even if it means less functionality. That's how this page was created.  It reflects my findings and it is not updated often, it's primitive, but still it's better than nothing because it addresses a very important topic that few other pages address...

The traditional way to built a beautifier vs "fuzzy method"

The traditional way to build a beautifier is to lexically parse the source language according to the source language lexical rules. See, for example, my old NEATPL pretty printer  for PL/1 (http://www.softpanorama.org/Articles/Oldies/neatpl.pdf ) This ensures that the lexems (lexical tokens) found by formatter are those that corresponds to lexems/tokens of the language.  But that requires presence of well defines and not too complex lexical level of the language. But there are language without lexical level (Unix shell is the primary example) or with a very complex (although well defined)  lexical level (Perl). For those languages a different approach is needed.

The class of beautifiers that do not perform full lexical analysis of the source code can be called "fuzzy" prettyprinters." We will use this term as it reflects how both Neatperl and Neatbash. were programmed.  

Pretty printers that do not perform full lexical analysis of the source code can be called "fuzzy" prettyprinter.  Fuzzy prettyprinters limit themselves to changes of indentation only, so they usually do not introduce errors in the script, leaving statements structure intact

For Bash which does not has lexical level at all full analysis involved writing a partial syntax analyzer. That further complicate the task in comparison with Perl and similar languages with complex lexical structure. 

Fuzzy prettyprinters limit themselves to changes of indentation only, so they usually do not introduce errors in the script, leaving statements structure intact.  Only HERE statements present problem and incorrect recognition of them still can change the script in undesirable way.

But using special pragma which  are processed by prettyprinter you can exclude certain fragments of your script from pretty printing and that solve the problem in indirect, but  a very efficient way. In any case you should get a prettyprinter for the language you use, or if this impossible switch to another scripting language ;-) .

In other words fuzzy prettyprinter represents "two way street" approach to Prettyprinting.  It expect that the programmer to adhere to certain rules and convention, but in turn makes pretty printing compliant source more reliable and more immune form errors introduced by pretty printer as the result not completely understanding or misunderstanding certain lexical constructs in the language. .

 

 Why worry so much about beautifier?

Programming is hard. So any tool that makes introduction of certain errors into the source code more difficult, or detention  of  common errors much easier is a valuable tool in the programmer arcenal. That';s the key postulate of "defensive programming" methodology.

For C-style language with their chromic problem of unclosed or closed incorrectly "{" bracket no other tool can provide she same level of help as prettyprinter.

That's why any programmer writing programs in C-style languages greatly benefit from a good beautifier. It makes the indentation  exactly corresponding to the nesting level of particular control statements. For other language like Ruby which used keywords for closing control structures (returning to the PL/1 style) this problem is less acute but still exists and prettyprinter remains a valuable tool.

The most important use case is when are modifying you own program which was written a long time ago. This is the  situation when the most nasty errors are introduced because you do not remember all the context of particular programming decisions made and, as the result, along with fixing this particular problem intrudes a couple of other, probably more serious and nastry that the problem you fixed. In other words maintenance of old program typically lead to the loss of connection integrity due the lack of program understanding. Pretty printer helps a little bit  with program understanding and thus is a simple and valuable tool to be used in this situation.

Deceptive, incorrect nesting levels can mask pretty subtle  errors like incorrect end of a particular control structure block ( for example wrong "extension of the block"). In this case the syntax of the program remains correct and such errors are very difficult to trace as people instinctively trust indenting.

That's why beautifier is and in foreseeable future remains a useful debugging aid -- kind of lint for poor people. 

Running away string constant is another use case.  Actually good programming editors like Komodo Edit do a good job in the latter case by changing color of the subsequent text. 

Beautifier is a very important debugging aid -- kind of lint for poor people.  It makes finding missing '}' and, to a lesser extent, run-away constants in C-style languages much easier and far less time consuming. Actually good programming editors like Komodo Edit do a good job in the latter case by changing color of the subsequent text.

Another benefit of beautification comes from its role as the enforcer of a  standard format for programs in the particular language in the particular organization.  This makes it much easier for a programmer to read the code of somebody else as well as his own programs in the future. In this sense, a beautifier is vital for program maintenance. 

Another benefit of beautification comes from its role as the enforcer of a  standard format for programs in the particular language in the particular organization. 

Obfuscators

Beautifier with full lexical analyser can  also work as obfuscators  by eliminating all white space and comments.

A related topic is , which are "anti-beautifiers" and are designed to remove meaningful formatting and all comments in order to make code more difficult to read and comprehend, to discourage reverse engineering. Their success is another point about tremendous value of a good beautifier.

Individual style and beautifiers

Beatifiers can also interfere with individual programming style. Beautifiers that perform full lexical analysis are more prone to enforce more that is reasonable or desirable.

Fuzzy beautifiers by definition do not interfere with programming style much changing only nesting level of statements.

The danger of introducing programming errors

Beautifier can work pretty well for many sample files. But it might fails for complex cases like commented out blocks of code; comments within statements (if the language allow such comments), obscure language features such as escapes in quoted strings, etc. 

If you use it just to create a listing of the program this does not matter. But if you use it to reformat actual source code, then badly tested beautifier can introduce syntax errors, or worse, create program source that is still syntactically correct but semantically different then the original (for example, by mangling some string constants -- the most common problem with semi-debugged beautifiers).

That means that for a new beautifier need a lot of tests which needs to be performed before you can trust it for reformatting production scripts.

At least for the initial several weeks the results should be verified using diff (see How can I trust Beautifier programs??!! about this procedure).  In case beautifier performs full lexical analysis you need to pay special attention for any lines that contain string constants. 

This is the most fundamental reason why for languages with very complex lexical structure or without defined lexical level fuzzy beautifiers represent  a better deal.

Dr. Nikolai Bezroukov


Top Visited
Switchboard
Latest
Past week
Past month

NEWS CONTENTS

Old News ;-)

[Mar 04, 2020] A command-line HTML pretty-printer Making messy HTML readable - Stack Overflow

Jan 01, 2019 | stackoverflow.com

A command-line HTML pretty-printer: Making messy HTML readable [closed] Ask Question Asked 10 years, 1 month ago Active 10 months ago Viewed 51k times


knorv ,

Closed. This question is off-topic . It is not currently accepting answers.

jonjbar ,

Have a look at the HTML Tidy Project: http://www.html-tidy.org/

The granddaddy of HTML tools, with support for modern standards.

There used to be a fork called tidy-html5 which since became the official thing. Here is its GitHub repository .

Tidy is a console application for Mac OS X, Linux, Windows, UNIX, and more. It corrects and cleans up HTML and XML documents by fixing markup errors and upgrading legacy code to modern standards.

For your needs, here is the command line to call Tidy:

tidy inputfile.html

Paul Brit ,

Update 2018: The homebrew/dupes is now deprecated, tidy-html5 may be directly installed.
brew install tidy-html5

Original reply:

Tidy from OS X doesn't support HTML5 . But there is experimental branch on Github which does.

To get it:

 brew tap homebrew/dupes
 brew install tidy --HEAD
 brew untap homebrew/dupes

That's it! Have fun!

Boris , 2019-11-16 01:27:35

Error: No available formula with the name "tidy" . brew install tidy-html5 works. – Pysis Apr 4 '17 at 13:34

[Sep 16, 2019] Artistic Style - Index

Sep 16, 2019 | astyle.sourceforge.net

Artistic Style 3.1 A Free, Fast, and Small Automatic Formatter
for C, C++, C++/CLI, Objective‑C, C#, and Java Source Code

Project Page: http://astyle.sourceforge.net/
SourceForge: http://sourceforge.net/projects/astyle/

Artistic Style is a source code indenter, formatter, and beautifier for the C, C++, C++/CLI, Objective‑C, C# and Java programming languages.

When indenting source code, we as programmers have a tendency to use both spaces and tab characters to create the wanted indentation. Moreover, some editors by default insert spaces instead of tabs when pressing the tab key. Other editors (Emacs for example) have the ability to "pretty up" lines by automatically setting up the white space before the code on the line, possibly inserting spaces in code that up to now used only tabs for indentation.

The NUMBER of spaces for each tab character in the source code can change between editors (unless the user sets up the number to his liking...). One of the standard problems programmers face when moving from one editor to another is that code containing both spaces and tabs, which was perfectly indented, suddenly becomes a mess to look at. Even if you as a programmer take care to ONLY use spaces or tabs, looking at other people's source code can still be problematic.

To address this problem, Artistic Style was created – a filter written in C++ that automatically re-indents and re-formats C / C++ / Objective‑C / C++/CLI / C# / Java source files. It can be used from a command line, or it can be incorporated as a library in another program.

[Sep 16, 2019] Usage -- PrettyPrinter 0.18.0 documentation

Sep 16, 2019 | prettyprinter.readthedocs.io

Usage

Install the package with pip :

pip install prettyprinter

Then, instead of

from pprint import pprint

do

from prettyprinter import cpprint

for colored output. For colorless output, remove the c prefix from the function name:

from prettyprinter import pprint

[Sep 16, 2019] JavaScript code prettifier

Sep 16, 2019 | github.com

Announcement: Action required rawgit.com is going away .

An embeddable script that makes source-code snippets in HTML prettier.

[Sep 16, 2019] Pretty-print for shell script

Sep 16, 2019 | stackoverflow.com

Benoit ,Oct 21, 2010 at 13:19

I'm looking for something similiar to indent but for (bash) scripts. Console only, no colorizing, etc.

Do you know of one ?

Jamie ,Sep 11, 2012 at 3:00

Vim can indent bash scripts. But not reformat them before indenting.
Backup your bash script, open it with vim, type gg=GZZ and indent will be corrected. (Note for the impatient: this overwrites the file, so be sure to do that backup!)

Though, some bugs with << (expecting EOF as first character on a line) e.g.

EDIT: ZZ not ZQ

Daniel Martí ,Apr 8, 2018 at 13:52

A bit late to the party, but it looks like shfmt could do the trick for you.

Brian Chrisman ,Sep 9 at 7:47

In bash I do this:
reindent() {
source <(echo "Zibri () {";cat "$1"; echo "}")
declare -f Zibri|head --lines=-1|tail --lines=+3 | sed -e "s/^\s\s\s\s//"
}

this eliminates comments and reindents the script "bash way".

If you have HEREDOCS in your script, they got ruined by the sed in the previous function.

So use:

reindent() {
source <(echo "Zibri () {";cat "$1"; echo "}")
declare -f Zibri|head --lines=-1|tail --lines=+3"
}

But all your script will have a 4 spaces indentation.

Or you can do:

reindent () 
{ 
    rstr=$(mktemp -u "XXXXXXXXXX");
    source <(echo "Zibri () {";cat "$1"|sed -e "s/^\s\s\s\s/$rstr/"; echo "}");
    echo '#!/bin/bash';
    declare -f Zibri | head --lines=-1 | tail --lines=+3 | sed -e "s/^\s\s\s\s//;s/$rstr/    /"
}

which takes care also of heredocs.

> ,

Found this http://www.linux-kheops.com/doc/perl/perl-aubert/fmt.script .

Very nice, only one thing i took out is the [...]->test substitution.

[Sep 16, 2019] A command-line HTML pretty-printer Making messy HTML readable - Stack Overflow

Notable quotes:
"... Have a look at the HTML Tidy Project: http://www.html-tidy.org/ ..."
Sep 16, 2019 | stackoverflow.com

nisetama ,Aug 12 at 10:33

I'm looking for recommendations for HTML pretty printers which fulfill the following requirements:

> ,

Have a look at the HTML Tidy Project: http://www.html-tidy.org/

The granddaddy of HTML tools, with support for modern standards.

There used to be a fork called tidy-html5 which since became the official thing. Here is its GitHub repository .

Tidy is a console application for Mac OS X, Linux, Windows, UNIX, and more. It corrects and cleans up HTML and XML documents by fixing markup errors and upgrading legacy code to modern standards.

For your needs, here is the command line to call Tidy:

[Sep 03, 2019] Run PerlTidy to beautify the code

Notable quotes:
"... Once I installed Code::TidyAll and placed those files in the root directory of the project, I could run tidyall -a . ..."
Sep 03, 2019 | perlmaven.com

The Code-TidyAll distribution provides a command line script called tidyall that will use Perl::Tidy to change the layout of the code.

This tandem needs 2 configuration file.

The .perltidyrc file contains the instructions to Perl::Tidy that describes the layout of a Perl-file. We used the following file copied from the source code of the Perl Maven project.

-pbp
-nst
-et=4
--maximum-line-length=120

# Break a line after opening/before closing token.
-vt=0
-vtc=0

The tidyall command uses a separate file called .tidyallrc that describes which files need to be beautified.

[PerlTidy]
select = {lib,t}/**/*.{pl,pm,t}
select = Makefile.PL
select = {mod2html,podtree2html,pods2html,perl2html}
argv = --profile=$ROOT/.perltidyrc

[SortLines]
select = .gitignore
Once I installed Code::TidyAll and placed those files in the root directory of the project, I could run tidyall -a .

That created a directory called .tidyall.d/ where it stores cached versions of the files, and changed all the files that were matches by the select statements in the .tidyallrc file.

Then, I added .tidyall.d/ to the .gitignore file to avoid adding that subdirectory to the repository and ran tidyall -a again to make sure the .gitignore file is sorted.

[Sep 02, 2019] bash - Pretty-print for shell script

Oct 21, 2010 | stackoverflow.com

Pretty-print for shell script Ask Question Asked 8 years, 10 months ago Active 30 days ago Viewed 14k times


Benoit ,Oct 21, 2010 at 13:19

I'm looking for something similiar to indent but for (bash) scripts. Console only, no colorizing, etc.

Do you know of one ?

Jamie ,Sep 11, 2012 at 3:00

Vim can indent bash scripts. But not reformat them before indenting.
Backup your bash script, open it with vim, type gg=GZZ and indent will be corrected. (Note for the impatient: this overwrites the file, so be sure to do that backup!)

Though, some bugs with << (expecting EOF as first character on a line) e.g.

EDIT: ZZ not ZQ

Daniel Martí ,Apr 8, 2018 at 13:52

A bit late to the party, but it looks like shfmt could do the trick for you.

Brian Chrisman ,Aug 11 at 4:08

In bash I do this:
reindent() {
source <(echo "Zibri () {";cat "$1"; echo "}")
declare -f Zibri|head --lines=-1|tail --lines=+3 | sed -e "s/^\s\s\s\s//"
}

this eliminates comments and reindents the script "bash way".

If you have HEREDOCS in your script, they got ruined by the sed in the previous function.

So use:

reindent() {
source <(echo "Zibri () {";cat "$1"; echo "}")
declare -f Zibri|head --lines=-1|tail --lines=+3"
}

But all your script will have a 4 spaces indentation.

Or you can do:

reindent () 
{ 
    rstr=$(cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 16 | head -n 1);
    source <(echo "Zibri () {";cat "$1"|sed -e "s/^\s\s\s\s/$rstr/"; echo "}");
    echo '#!/bin/bash';
    declare -f Zibri | head --lines=-1 | tail --lines=+3 | sed -e "s/^\s\s\s\s//;s/$rstr/    /"
}

which takes care also of heredocs.

Pius Raeder ,Jan 10, 2017 at 8:35

Found this http://www.linux-kheops.com/doc/perl/perl-aubert/fmt.script .

Very nice, only one thing i took out is the [...]->test substitution.

[Sep 02, 2019] mvdan-sh A shell parser, formatter, and interpreter (POSIX-Bash-mksh)

Written in Go language
Sep 02, 2019 | github.com
go parser shell bash formatter posix mksh interpreter bash-parser beautify
  1. Go 98.8%
  2. Other 1.2%
Type Name Latest commit message Commit time
Failed to load latest commit information.
_fuzz/ it
_js
cmd
expand
fileutil
interp
shell
syntax
.gitignore
.travis.yml
LICENSE
README.md
go.mod
go.sum
release-docker.sh
README.md

sh

A shell parser, formatter and interpreter. Supports POSIX Shell , Bash and mksh . Requires Go 1.11 or later.

Quick start

To parse shell scripts, inspect them, and print them out, see the syntax examples .

For high-level operations like performing shell expansions on strings, see the shell examples .

shfmt

Go 1.11 and later can download the latest v2 stable release:

cd $(mktemp -d); go mod init tmp; go get mvdan.cc/sh/cmd/shfmt

The latest v3 pre-release can be downloaded in a similar manner, using the /v3 module:

cd $(mktemp -d); go mod init tmp; go get mvdan.cc/sh/v3/cmd/shfmt

Finally, any older release can be built with their respective older Go versions by manually cloning, checking out a tag, and running go build ./cmd/shfmt .

shfmt formats shell programs. It can use tabs or any number of spaces to indent. See canonical.sh for a quick look at its default style.

You can feed it standard input, any number of files or any number of directories to recurse into. When recursing, it will operate on .sh and .bash files and ignore files starting with a period. It will also operate on files with no extension and a shell shebang.

shfmt -l -w script.sh

Typically, CI builds should use the command below, to error if any shell scripts in a project don't adhere to the format:

shfmt -d .

Use -i N to indent with a number of spaces instead of tabs. There are other formatting options - see shfmt -h . For example, to get the formatting appropriate for Google's Style guide, use shfmt -i 2 -ci .

Packages are available on Arch , CRUX , Docker , FreeBSD , Homebrew , NixOS , Scoop , Snapcraft , and Void .

Replacing bash -n

bash -n can be useful to check for syntax errors in shell scripts. However, shfmt >/dev/null can do a better job as it checks for invalid UTF-8 and does all parsing statically, including checking POSIX Shell validity:

$ echo '${foo:1 2}' | bash -n
$ echo '${foo:1 2}' | shfmt
1:9: not a valid arithmetic operator: 2
$ echo 'foo=(1 2)' | bash --posix -n
$ echo 'foo=(1 2)' | shfmt -p
1:5: arrays are a bash feature

gosh

cd $(mktemp -d); go mod init tmp; go get mvdan.cc/sh/v3/cmd/gosh

Experimental shell that uses interp . Work in progress, so don't expect stability just yet.

Fuzzing

This project makes use of go-fuzz to find crashes and hangs in both the parser and the printer. To get started, run:

git checkout fuzz
./fuzz

Caveats

$ echo '${array[spaced string]}' | shfmt
1:16: not a valid arithmetic operator: string
$ echo '${array[dash-string]}' | shfmt
${array[dash - string]}
$ echo '$((foo); (bar))' | shfmt
1:1: reached ) without matching $(( with ))

JavaScript

A subset of the Go packages are available as an npm package called mvdan-sh . See the _js directory for more information.

Docker

To build a Docker image, checkout a specific version of the repository and run:

docker build -t my:tag -f cmd/shfmt/Dockerfile .

Related projects

[Oct 10, 2011] Uncrustify 0.59

Written in C++

Uncrustify is a source code beautifier that allows you to banish crusty code. It works with C, C++, C#, D, Java, and Pawn and indents (with spaces only, tabs and spaces, and tabs only), adds and removes... newlines, has a high degree of control over operator spacing, aligns code, is extremely configurable, and is easy to modify (more)

prettyprinter.de

This is a Web-based source code beautifier (source code formatter), similiar to indent. Please make a backup before you replace your code!

[Jan 19, 2011] pb

#!/usr/bin/perl

# 'pb' Perl Beautifier

# Written by P. Lutus Ashland, Oregon lutusp@arachnoid.com 5/20/96

# This script processes Perl scripts, cleans up and indents, like cb does for C

# Be careful with this script - it accepts wildcards and processes every text file
# that meets the wildcard criteria. This could be a catastrophe in the hands of the unwary.

$tabstring = "  "; # You may place any tab-stop characters you want here

if($ARGV[0] eq "") {
  print "usage: file1 file2 etc. or wildcards (replaces originals in place)\n";
}
else {
  foreach $filename (@ARGV) {
    if(-T $filename) {
      &process($filename);
    }
  }
}

sub process {
  $fn = $_[0];
  undef $/; # so we can grab the entire file at once
  undef @infa; # prevent left-overs
  print STDERR "$fn";
  open (INFILE,$fn);
  @infa = split(/\n/,<INFILE>);
  close INFILE;
  
  $/ = "\n"; # restore default
  
  open (OUTFILE,">$fn");
  $tabtotal = 0;
  for (@infa) {
    
    s/^\s*(.*?)\s*$/$1/; # strip leading and trailing spaces
    
    $a = $_; # copy original string
    $q = $a; # i plan to modify this copy for testing
    $q =~ s/\\\#//g; # remove escaped comment tokens
    $q =~ s/\#.*?$//g; # remove Perl-style comments
    $q =~ s{/\*.*?\*/} []gsx; # remove C-style comments
    $q =~ s/\\\{//g; # remove escaped left  braces
    $q =~ s/\\\}//g; # remove escaped right braces
    $q =~ s/\\\(//g; # remove escaped left  parentheses
    $q =~ s/\\\)//g; # remove escaped right parentheses
    
    $q =~ s/\'.*?\'//g; # remove single-quoted lines
    
# now the remaining braces/parentheses should be structural
    
    $delta = -($q =~ s/\}/\}/g); # subtract closing braces
    $delta += ($q =~ s/\{/\{/g); # add opening braces
    
    $delta -= ($q =~ s/\)/\)/g); # subtract closing parens
    $delta += ($q =~ s/\(/\(/g); # add opening parens
    
    $tabtotal += ($delta < 0)?$delta:0; # subtract closing braces/parentheses
    
    $i = ($tabtotal > 0)?$tabtotal:0; # create tab index
    
    $tabtotal += ($delta>0)?$delta:0; # add opening braces/parentheses for next print
    
    if(substr($a,0,1) ne "#") { # don't tab comments
      print OUTFILE $tabstring x $i; # "tab" out to position
    }
    
    print OUTFILE "$a\n"; # print original line
  } # -- for (@infa)
  
  close OUTFILE;
  
  if($tabtotal != 0) {
    print STDERR " Indentation error: $tabtotal\n";
  }
  else {
    print STDERR "\n";
  }
} # sub process

Beautifier freshmeat.net

Beautifier (previously known as PSH, the PHP Syntax Highlighter) highlights and indents source code using highlight configuration files which are similar to Ultraedit highlighting files.

It supports C, C#, Java, Perl, PHP, Pascal, Lisp, Mumps, Eiffel, Euphoria, and x86 Assembler, amongst others.

It handles line/block comments, keyword highlighting, correct indentation, string highlighting, language contexts (allowing embedded languages), and selection highlighting. It is available in PHP and Perl versions.

[Aug 20, 2008] Pretty Diff - The difference tool by Austin Cheney

A very interesting online tool that provides "pretty diff" feature for HTML and Javascript code. "
The Diff View Type option provides two choices. The first choice, Side by Side View, reports the output into two columns that display a side by side comparison of the differences. The second choice, Inline View, displays the output into a single column so that the differences can be seen in a vertical comparison."
Pretty Diff

[Jun 30, 2008] NArrange 0.2.5 by James Nies

About: NArrange is a tool for arranging .NET source code. This code beautifier automatically sorts and organizes class members into groups or regions. Currently, C# and VB code files are supported.

Changes: This release adds support for processing source files with conditional compilation preprocessor directives, and fixes a couple of C# and VB parsing/writing bugs.

[Mar 27, 2008] Highlight 2.6.9 by André Simon

The converter from source code to HTML

About: Highlight is a universal converter from source code to HTML, XHTML, RTF, TeX, LaTeX, and XML. (X)HTML output is formatted by Cascading Style Sheets. It supports more than 100 programming languages, and includes 40 highlighting color themes. It's possible to easily enhance the parsing database. The converter includes some features to provide a consistent layout of the input code.

Changes: Embedded output instructions specific to the output document format were added. Support for Arc and Lilypond was added.

[Dec 7, 2007] freshmeat.net Project details for perltidy

Perltidy is a Perl script indenter and beautifier. By default it approximately follows the suggestions in perlstyle(1), but the style can be adjusted with command line parameters. Perltidy can also write syntax-colored HTML output.

Release focus: Minor feature enhancements

[Dec 6, 2007] Project details for JsDecoder

freshmeat.net

JavascriptDecoder is a tool to easily decode obfuscated Javascript code. Besides decoding, it can also serve as a Javascript code beautifier and colorizer.

[Mar 24, 2007] freshmeat.net Project details for GNU Source-highlight

About:
GNU Source-highlight produces a document with syntax highlighting when given a source file. It handles many languages, e.g., Java, C/C++, Prolog, Perl, PHP3, Python, Flex, HTML, and other formats, e.g., ChangeLog and log files, as source languages and HTML, XHTML, DocBook, ANSI color escapes, LaTeX, and Texinfo as output formats. Input and output formats can be specified with a regular expression-oriented syntax.

Release focus: Major feature enhancements

Changes:
Language definitions for makefiles, CSS files, and m4 files were added. The --quiet option was added to show no progress information. Direct color specifications in double quotes in style files are allowed. In style files, one can specify formatting options for more than one element on the same line. CSS files can be specified as style files (with limited support). Background colors for single elements and the entire document are now handled.

[Nov 25, 2006] freshmeat.net Project details for Uncrustify

Uncrustify is a source code beautifier that allows you to banish crusty code. It works with C, C++, C#, D, Java, and Pawn and indents (with spaces only, tabs and spaces, and tabs only), adds and removes newlines, has a high degree of control over operator spacing, aligns code, is extremely configurable, and is easy to modify.

NONAGS Command Line Tools - Freeware

GC! GreatCode 1.095 for Win9x/NT4/ME/Win2k (50 kb)
From NonagsPLUS (Members) (50 kb)
Updated: Sep 19, 2000
Homepage
Author: christophe beaudet
Description: Very powerful C/C++ source code beautifier.

Project details for Beautifier

freshmeat.net

Beautifier (previously known as PSH, the PHP Syntax Highlighter) highlights and indents source code using highlight configuration files which are similar to Ultraedit highlighting files. It supports C, C#, Java, Perl, PHP, Pascal, Lisp, Mumps, Eiffel, Euphoria, and x86 Assembler, amongst others. It handles line/block comments, keyword highlighting, correct indentation, string highlighting, language contexts (allowing embedded languages), and selection highlighting. It is available in PHP and Perl versions.

C-C++ Beautifier HOW-TO

(The latest version of this document is at "http://www.milkywaygalaxy.freeservers.com" . You may want to check there for changes).

Coding standards for C/C++ or any language is required in order to make the programs more readable/understandable by programmers. There are C/C++ beautifiers (formating tools) to accomplish this goal. Formatted (beautified) code improves the productivity of programmers by 2 times !!

On Linux/Unixes there is a command called "indent" and "cb" . Refer to 'man indent' and 'man cb'. Note that indent and cb work for only "C" programs. For "C++" programs use "bcpp" .

Important NOTE: To compile bcpp under unix, unpack bcpp.tar.gz and you MUST change directory to "code" and give a make. Do not change to "unix" directory and give a make. That will give lots of errors.

Download the beautifier program from one of the following

I used BCPP to format the C++ programs and it worked fine for me. You may want to check other tools and use the one which you may like the most.

BCPP was written by Steven De Toni at steve@alpha.ocbbs.gen.nz

Info Node (cookbook.info)Prettyprint Text

Outputting Text with Language Highlighting
------------------------------------------

The `enscript' tool currently recognizes the formatting of more than
forty languages and formats, from the Perl and C programming languages
to HTML, email, and Usenet news articles; `enscript' can highlight
portions of the text based on its syntax. In Unix-speak, this is called
"pretty-printing".

The following table lists the names of some of the language filters
that are available at the time of this writing and describes the
languages or formats they're used for.

FILTER LANGUAGE OR FORMAT
`ada' Ada95 programming language.
`asm' Assembler listings.
`awk' AWK programming language.
`bash' Bourne-Again shell programming language.
`c' C programming language.
`changelog' ChangeLog files.
`cpp' C++ programming language.
`csh' C-Shell script language.
`delphi' Delphi programming language.
`diff' Normal "difference reports" made from `diff'.
`diffu' Unified "difference reports" made from `diff'.
`elisp' Emacs Lisp programming language.
`fortran' Fortran77 programming language.
`haskell' Haskell programming language.
`html' HyperText Markup Language (HTML).
`idl' IDL (CORBA Interface Definition Language).
`java' Java programming language.
`javascript' JavaScript programming language.
`ksh' Korn shell programming language.
`m4' M4 macro processor programming language.
`mail' Electronic mail and Usenet news articles.
`makefile' Rule files for `make'.
`nroff' Manual pages formatted with `nroff'.
`objc' Objective-C programming language.
`pascal' Pascal programming language.
`perl' Perl programming language.
`postscript' PostScript programming language.
`python' Python programming language.
`scheme' Scheme programming language.
`sh' Bourne shell programming language.
`skill' Cadence Design Systems Lisp-like language.
`sql' Sybase 11 SQL.
`states' Definition files for `states'.
`synopsys' Synopsys `dc' shell scripting language.
`tcl' Tcl programming language.
`tcsh' TC-Shell script language.
`vba' Visual Basic (for Applications).
`verilog' Verilog hardware description language.
`vhdl' VHSIC Hardware Description Language (VHDL).
`vrml' Virtual Reality Modeling Language (VRML97).
`zsh' Z-shell programming language.

To pretty-print a file, give the name of the filter to use as an
argument to the `-E' option, without any whitespace between the option
and argument.

* To pretty-print the HTML file `index.html', type:

$ enscript -Ehtml index.html <RET>

* To pretty-print an email message saved to the file
`important-mail', and output it with no headers to a file named
`important-mail.ps', type:

$ enscript -B -Email -p important-mail.ps important-mail <RET>

Use the special `--help-pretty-print' option to list the languages
supported by the copy of `enscript' you have.

* To peruse a list of currently supported languages, type:

$ enscript --help-pretty-print | less <RET>

www.bitterberg.de -- Tilmanns Corner -- diff HTML beautifier

GNU Source-highlight - GNU Project - Free Software Foundation (FSF) v1.6 by Lorenzo Bettini

This program, given a source file, produces a document with syntax highlighting.

At the moment this package can handle

as source languages, and

as output format.

NOTICE: now the name of the program is source-highlight: there are no two separate programs, namely java2html and cpp2html, anymore. However there are two shell scripts with the same name in order to facilitate the migration (however their use is not advised).

GNU Source-highlight is free software. Please see the file COPYING for details. For documentation, please read this file.

GNU Source-highlight is a GNU program and its main home page is at GNU site:
http://www.gnu.org/software/src-highlite/source-highlight.html

You can download it from GNU's ftp site:
ftp://ftp.gnu.org/gnu/source-highlight/ or from one of its mirrors (see http://www.gnu.org/prep/ftp.html).

I do not distribute Windows binaries anymore; since, they can be easily built by using Cygnus C/C++ compiler, available at http://www.cygwin.com/. However, if you don't feel like downloading such compiler, you can request such binaries directly to me, by e-mail (bettini@gnu.org) and I can send them to you.
An MS-Windows port of Source-highlight is available from http://gnuwin32.sourceforge.net/.

You may also want to check the md5sum of the archives, which are also digitally signed by me (Lorenzo Bettini) with GNU gpg (http://www.gnupg.org). My GPG public key can be found at my home page (see at the end of this doc).

You can also get the patches, if they are available for a particular release (see below for patching from a previous version).

BS Repository

[July 19, 2002] Mangle 3.0.6

About: Mangle is a source de-formatter/de-commentor. It will remove all comments and/or formatting from C/C++ source code leaving only what is required.

Changes: Some bugfixes, cleanups, and new features.

designed for HTML, Java, and Perl programming. WinTidy is easily
customized, handles huge files, and includes powerful validation and
beautification tools. Integrated browser, Java support, DOS, Unix,
Mac file formats. Print options include 'two-up' printing, syntax
coloring, and line numbers. It's easy to take advantage of WinTidy's
many features. WinTidy's design is intuitive, allowing you to avoid
the pitfalls of learning a new program. Its slick, simple interface
includes customizable menus, toolbars, and keyboard settings. WinTidy
includes powerful editing features including column blocks, drag and
drop editing, bookmarks, split-file editing, and global search and
replace. WinTidy is built for programmers with features like brace
matching, configurable color-syntax highlighting, and custom tool
support. Compilers and other tools are launched on separate threads,
and can be controlled without leaving WinTidy, allowing complete
automation of the compile, build and debug sequence.

Special requirements: 16MB RAM

Adware. Uploaded by the authorized Distributor.

Dave Collins, SharewarePromotions
dave@Sharewarepromotions.com
WinEdit Software Co.
sales@wintidy.com
http://www.wintidy.com/

www.simtel.net wde21.zip (Win32 Pretty Printer for C-code. Free w-C src)

Category: WinME / Win98 / Win95 / Programming Utilities

Publisher: Herman Oosthuysen

Website: http://www.AerospaceSoftware.com/

File Name: wdent121.zip

Also works from the command line and can be called from a batch file. Indent up to 256 files in one go. Freeware with C source code.

Special requirements: None

Freeware. Uploaded by the author.

Herman Oosthuysen, Aerospace Software Ltd.
aerosoft@AerospaceSoftware.com
http://www.AerospaceSoftware.com/

Pprint home page

PPRINT generates source code listings in postscript. It italicizes comments, boldfaces typedefs, and bold-italicizes keywords. It generates line numbers and a cross reference of all typedefs, static and global functions, listing both definitions and references. Definitions are in bold.

PPRINT manages print-outs of multiple files by producing both global and local page numbers. At the end of the run, it prints out a table of contents, and index, and a reference of all globally accessible typedefs and classes.

PPRINT works with C files, C++ files, Verilog files, and text files. It figures out which language based on extension:

From Advanced programming in Perl: Data structures pretty-printing

2.5 Pretty-Printing

In building complicated data structures, it is always nice to have a pretty-printer handy for debugging. There are at least two options for pretty-printing data structures. The first is the Perl debugger itself. It uses a function called dumpValue in a file called dumpvar.pl, which can be found in the standard library directory. We can help ourselves to it, with the caveat that it is an unadvertised function and could change someday. To pretty-print this structure, for example:

  @sample = (11.233,{3 => 4, "hello" => [6,7]});

we write the following:

require 'dumpvar.pl';
dumpValue(\@sample); # always pass by reference

This prints something like this:

0  11.233
1  HASH(0xb75dc0)
   3 => 4
   'hello' => ARRAY(0xc70858)
      0  6
      1  7

We will cover the require statement in Chapter 6, Modules. Meanwhile, just think of it as a fancy #include (which doesn't load the file if it is already loaded).

The Data::Dumper module available from CPAN is another viable alternative for pretty-printing. Chapter 10, Persistence, covers this module in some detail, so we will not say any more about it here. Both modules detect circular references and handle subroutine and glob references.

It is fun and instructive to write a pretty-printer ourselves. Example 2.5 illustrates a simple effort, which accounts for circular references but doesn't follow typeglobs or subroutine references. This example is used as follows:

pretty_print(@sample); # Doesn't need a reference

This prints

11.233
{ # HASH(0xb78b00)
:  3 => 4
:  hello =>
:  :  [ # ARRAY(0xc70858)
:  :  :  6
:  :  :  7
:  :  ]
}

The following code contains specialized procedures (print_array, print_hash, or print_scalar) that know how to print specific data types. print_ref, charged with the task of pretty-printing a reference, simply dispatches control to one of the above procedures depending upon the type of argument given to it. In turn, these procedures may call print_ref recursively if the data types that they handle contain one or more references.

Whenever a reference is encountered, it is also checked with a hash %already_seen to determine whether the reference has been printed before. This prevents the routine from going into an infinite loop in the presence of circular references. All functions manipulate the global variable $level and call print_indented, which appropriately indents and prints the string given to it.

Example 2.5: Pretty-Printing

$level = -1; # Level of indentation

sub pretty_print {
    my $var;
    foreach $var (@_) {
        if (ref ($var)) {
            print_ref($var);
        } else {
            print_scalar($var);
        }
    }
}

sub print_scalar {
    ++$level;
    my $var = shift;
    print_indented ($var);
    --$level;
}

sub print_ref {
    my $r = shift;
    if (exists ($already_seen{$r})) {
        print_indented ("$r (Seen earlier)");
        return;
    } else {
        $already_seen{$r}=1;
    }
    my $ref_type = ref($r);
    if ($ref_type eq "ARRAY") {
        print_array($r);
    } elsif ($ref_type eq "SCALAR") {
        print "Ref -> $r";
        print_scalar($$r);
    } elsif ($ref_type eq "HASH") {
        print_hash($r);
    } elsif ($ref_type eq "REF") {
        ++$level;
        print_indented("Ref -> ($r)");
        print_ref($$r);
        --$level;
    } else {
        print_indented ("$ref_type (not supported)");
    }
}

sub print_array {
    my ($r_array) = @_;
    ++$level;
    print_indented ("[ # $r_array");
    foreach $var (@$r_array) {
        if (ref ($var)) {
            print_ref($var);
        } else {
            print_scalar($var);
        }
    }
    print_indented ("]");
    --$level;
}

sub print_hash {
    my($r_hash) = @_;
    my($key, $val);
    ++$level;
    print_indented ("{ # $r_hash");
    while (($key, $val) = each %$r_hash) {
        $val = ($val ? $val : '""');
        ++$level;
        if (ref ($val)) {
            print_indented ("$key => ");
            print_ref($val);
        } else {
            print_indented ("$key => $val");
        }
        --$level;
    }
    print_indented ("}");
    --$level;
}

sub print_indented {
    $spaces = ":  " x $level;
    print "${spaces}$_[0]\n";
}

print_ref simply prints its argument (a reference) and returns if it has already seen this reference. If you were to read the output produced by this code, you would find it hard to imagine which reference points to which structure. As an exercise, you might try producing a better pretty-printer, which identifies appropriate structures by easily identifiable numeric labels like this:

:  hello =>
:  :  [          # 10
:  :  :  6
:  :  :  7
:  :  ]
:  foobar => array-ref # 10
}

The number 10 is an automatically generated label, which is more easily identifiable than something like ARRAY(0xc70858).


Recommended Links

Google matched content

Softpanorama Recommended

Top articles

Sites

www.simtel.net - Search Results

C Programming

Beautifiers for other Languages

To create presentation of codes to display using HTML -


Multitarget highllighters

GNU Source-highlight - GNU Project - Free Software Foundation (FSF) v1.6 by Lorenzo Bettini

This program, given a source file, produces a document with syntax highlighting.

At the moment this package can handle

as source languages, and

as output format.

NOTICE: now the name of the program is source-highlight: there are no two separate programs, namely java2html and cpp2html, anymore. However there are two shell scripts with the same name in order to facilitate the migration (however their use is not advised).

GNU Source-highlight is free software. Please see the file COPYING for details. For documentation, please read this file.

GNU Source-highlight is a GNU program and its main home page is at GNU site:
http://www.gnu.org/software/src-highlite/source-highlight.html

You can download it from GNU's ftp site:
ftp://ftp.gnu.org/gnu/source-highlight/ or from one of its mirrors (see http://www.gnu.org/prep/ftp.html).

I do not distribute Windows binaries anymore; since, they can be easily built by using Cygnus C/C++ compiler, available at http://www.cygwin.com/. However, if you don't feel like downloading such compiler, you can request such binaries directly to me, by e-mail (bettini@gnu.org) and I can send them to you.
An MS-Windows port of Source-highlight is available from http://gnuwin32.sourceforge.net/.

You may also want to check the md5sum of the archives, which are also digitally signed by me (Lorenzo Bettini) with GNU gpg (http://www.gnupg.org). My GPG public key can be found at my home page (see at the end of this doc).

You can also get the patches, if they are available for a particular release (see below for patching from a previous version).


Multitarget verifiers

www.simtel.net wintid10.zip (Powerful validating HTML,Java,Perl ed. Adware)


Multitarget beautifiers

ASBeautifier 0.8.0
ASBeautifier is a C++ port of JSBeautifier. It automatically reindents C++, C, and Java source files, i.e. beautifies them. ABeautifier is small, fast, and distributed as open-software (under the 'Artistic License'). ASBeautifier was created following interest from users of the jstyle family of source code filters.

C beautifiers

indent - GNU Project - Free Software Foundation (FSF)

Indent -- This is the home page for the GNU indent tool.

Artistic Style 1.2.0
Artistic Style is a fast and small open-source(TM) indenter and reformatter of C, C++ and Java source codes.

Version 1.2.0 contains numerous serious bug fixes, and a new formatting option for special treatment of mono-line blocks of code.

Tal Davidson @ 12/19/98 - 15:49 EST
ASBeautifier 0.8.0
ASBeautifier is a C++ port of JSBeautifier. It automatically reindents C++, C, and Java source files, i.e. beautifies them. ABeautifier is small, fast, and distributed as open-software (under the 'Artistic License'). ASBeautifier was created following interest from users of the jstyle family of source code filters.

C++

[36] Miscellaneous environmental issues, C++ FAQ Lite

In alphabetical order:

Finally, you might consider lgrind which is another C++ to LaTeX translator (check for the closest mirror site of the ctan archive). The following is a grind definition for C++ (but this one doesn't recognize some new keywords such as bool or wchar_t, and it doesn't recognize a file ending with .cpp as C++):

C++|c++|CC:\
:pb=\p\d?\(:cf:np=\)\d?;:bb={:be=}:\
:cb=/*:ce=*/:ab=//:ae=$:sb=":se=\e":lb=':\
:zb=@:ze=@:tb=%%:te=%%:mb=%\$:me=\$%:vb=%\|:ve=\|%:\
:le=\e':tl:id=_~\::\
:kw=asm auto break case cdecl char continue default do double else\
enum extern far float for fortran goto huge if int interrupt long\
near pascal register return short signed sizeof static struct\
switch typedef union unsigned while void\
#define #else #endif #if #ifdef #ifndef #include #undef # define\
endif ifdef ifndef include undef defined #pragma\
class const delete friend inline new operator overload private\
protected public template this virtual:

Random Findings

A Fortran Pretty Printer

The prettyp package

Consists of a suite of program that generates "pretty" PostScript source code listings using TeX. For a given language, comments are rendered in Times Roman italics, keywords in bold, strings in Courier; line-numbers, every 10 lines in a tiny font, and function/subroutine/procedure definitions, in a larger font, are displayed along the right margin. HISTORY prettyp (a new addition to the tgrind package) uses tfontedpr, written by Van Jacobson, which was originally based on BSD 4.2 vfontedpr, written by Bill Joy & Dave Presotto, which used troff. All the contents of the original tgrind package are included for backwards compatibility. This release was ported to build under GNU/Linux (there was a variable called _start that was messing with the compiler's idea of reality), and Solaris with TeX (Web2C 7.2) 3.14159 by Luis Fernandes & Jason Naughton. The major feature of prettyp (w.r.t. tgrind) is its automatic language detection capabilities that enables one to grind source code without specifying the -l (language) option. prettyp uses a combination of filename extensions and interpreter (#! magic) to deduce the language. LANGUAGE SUPPORT Languages supported by this release are: C, C++ (new), FORTRAN77, ISP, Icon, Java (new), LDL, Emacs Mock Lisp, Model, Modula2, Pascal, Perl (new), Python (new), RATFOR, Russell, sh/csh, Tcl (new) and yacc grammer. Support for additional languages can be easily added, see EXTENDING LANGUAGE SUPPORT below. REQUIREMENTS You will need TeX to be installed on your system for this program to work. You will need perl to use the prettyp front-end (specifically, the script "lang", that performs automatic language detection). PLATFORMS tfontedpr, the program that does all the actual work, has been successfully built on i586 GNU/Linux 2.0.34, SPARC Solaris 2.5.1, and SunOS 4.1.4. It should compile without problem for most other platforms. EXAMPLE To grind a C source-code file and a shell script, type: prettyp vgrindefs.c prettyp to generate vgrindefs.c.ps and prettyp.ps which may be viewed with ghostview or printed on a PostScript printer. You can visit the prettyp home page at www.ee.ryerson.ca/~elf/prettyp/ and view the "pretty" PostScript output for a shell script, a perl script, C code and Tcl/Tk code. EXTENDING LANGUAGE SUPPORT To add pretty print capabilities for other languages, add the language definition to the vgrindefs database and modify the alist in the lang perl script adding a file-extension/interpreter to language mapping. - -- This article has been digitally signed by the moderator, using PGP. http://www.iki.fi/mjr/cola-public-key.asc has PGP key for validating signature. Send submissions for comp.os.linux.announce to: linux-announce@news.ornl.gov PLEASE remember a short description of the software and the LOCATION. This group is archived at http://www.iki.fi/mjr/linux/cola.html



Etc

The Last but not Least Technology is dominated by two types of people: those who understand what they do not manage and those who manage what they do not understand ~Archibald Putt. Ph.D


Copyright © 1996-2018 by Dr. Nikolai Bezroukov. www.softpanorama.org was initially created as a service to the (now defunct) UN Sustainable Development Networking Programme (SDNP) in the author free time and without any remuneration. This document is an industrial compilation designed and created exclusively for educational use and is distributed under the Softpanorama Content License. Original materials copyright belong to respective owners. Quotes are made for educational purposes only in compliance with the fair use doctrine.

FAIR USE NOTICE This site contains copyrighted material the use of which has not always been specifically authorized by the copyright owner. We are making such material available to advance understanding of computer science, IT technology, economic, scientific, and social issues. We believe this constitutes a 'fair use' of any such copyrighted material as provided by section 107 of the US Copyright Law according to which such material can be distributed without profit exclusively for research and educational purposes.

This is a Spartan WHYFF (We Help You For Free) site written by people for whom English is not a native language. Grammar and spelling errors should be expected. The site contain some broken links as it develops like a living tree...

You can use PayPal to make a contribution, supporting development of this site and speed up access. In case softpanorama.org is down you can use the at softpanorama.info

Disclaimer:

The statements, views and opinions presented on this web page are those of the author (or referenced source) and are not endorsed by, nor do they necessarily reflect, the opinions of the author present and former employers, SDNP or any other organization the author may be associated with. We do not warrant the correctness of the information provided or its fitness for any purpose.

The site uses AdSense so you need to be aware of Google privacy policy. You you do not want to be tracked by Google please disable Javascript for this site. This site is perfectly usable without Javascript.

Last modified: February, 19, 2020