#!/usr/bin/perl
use strict;

package main;
    my $line;
    my $name;
    my $size;
    my $description;

    (open INFILE, "<stdint.h") or die "Cannot open stdint.h: $!\n";

    while ($line = <INFILE>) {
        
        if ($line =~ m@^typedef (\C*?) ([a-zA-Z0-9_]+);$@) {
            # Typedef
            $name = $2;
            next if ($name !~ m@\C*?(\d{0,2})_t@);
            $size = $1;
            $description = $name;
            my $description2 = 'Definition mandated by the C99 standard.';
            my $unsigned = ((index($name,'u') == 0) ? 'n unsigned ' : ' signed ');
            my $unsigned2 = ((index($name,'u') == 0) ? 'unsigned' : 'signed');
            
            if (index($description, 'least') != -1) {
                $description = "An alias type for a${unsigned}integer type that contains at least $size bits.";
            }
            elsif (index($description, 'fast') != -1) {
                $description = "An alias type for a${unsigned}integer type that contains at least $size bits, the one that the processor handles most efficiently.";
            }
            elsif (index($description, 'ptr') != -1) {
                $description = "An alias type for a${unsigned}integer type such that a <I>void *</I> can be converted to this type and back, while remaining equal to the original pointer.";
                $description2 = '';
            }
            elsif (index($description, 'max') != -1) {
                $description = "An alias type for a${unsigned}integer type capable of representing any value of any $unsigned2 type.";
            }
            else {
                $description = "An alias type for a${unsigned}integer type that contains exactly $size bits.";
                $description2 = '';
            }
            
            $line =~ s/\n//g; # Swallow newline.
            open OUTFILE, "+>trunk/tigcc/doc/System/Include/stdint.h/$name.hsf";
            print OUTFILE <<EOF
[Main]\r
Name=$name\r
Type=Type\r
Subtype=Scalar\r
Header Files=stdint.h\r
Definition=$line\r
\r
[Description]\r
$description\r
\r
[Explanation]\r
$description2\r
EOF
;
            close OUTFILE;
        }
        elsif ($line =~ m@^#\s*define (\S+) (\C*?)$@) {
            $name = $1;
            my $definition = $line;
            
            if (index($name, '(') != -1) {
                my $type;
                # Macro with argument
                next if ($name !~ m@\C*?(\d{0,2})_C\(c\)@);
                $size = $1;
                
                if (index($name, 'MAX') != -1) {
                    $type = ((index($name,'U') == 0) ? 'u' : '') . "intmax_t";
                }
                else {
                    $type = ((index($name,'U') == 0) ? 'u' : '') . "int_least${size}_t";
                }
                $description = "Integer constant expression having the value specified by its argument and the type $type.";

                $line =~ s/\n//g; # Swallow newline.
                $name = substr($name, 0, index($name,'('));
                open OUTFILE, "+>trunk/tigcc/doc/System/Include/stdint.h/$name.hsf";
                print OUTFILE <<EOF
[Main]\r
Name=$name\r
Type=Function\r
Subtype=Macro\r
Header Files=stdint.h\r
Definition=$line\r
\r
[Description]\r
$description\r
\r
[Explanation]\r
Definition mandated by the C99 standard.\r
EOF
;
                close OUTFILE;
            }
            else {
                # Macro without argument
                next if ($name !~ m@(\C*?(\d{0,2})_)(MAX|MIN)@);
                $size = $2;
                my $type = lc($1) . 't';
                
                if (index($name, 'MAX') != -1) {
                    $description = "Maximal value which can be stored in a $type variable.";
                }
                else {
                    # Assume it's a MIN.
                    $description = "Minimal value which can be stored in a $type variable.";
                }

                $line =~ s/\n//g; # Swallow newline.
                open OUTFILE, "+>trunk/tigcc/doc/System/Include/stdint.h/$name.hsf";
                print OUTFILE <<EOF
[Main]\r
Name=$name\r
Type=Constant\r
Header Files=stdint.h\r
Definition=$line\r
\r
[Description]\r
$description\r
\r
[Explanation]\r
Definition mandated by the C99 standard.\r
EOF
;
                close OUTFILE;
            }
        }
        # else do nothing
        
    }

