/*
  shaderStats.java
  Statistics on assembly code output by Nvidia's CG compiler (cgc).

  Copyright (C) 2006 Aymeric AUGUSTIN

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License
  as published by the Free Software Foundation; either version 2
  of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/


import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.EOFException;
import java.util.Hashtable;
import java.util.Enumeration;

class StringInt implements java.lang.Comparable {

    String s;
    int i;
    
    StringInt (String ss, int ii) {
        s = ss; i = ii;
    }
    
    public String toString() {
        return "\t" + s + "\t" + i;
    }
    
    public int compareTo(Object o) {
        StringInt si = (StringInt) o;
        if (i == si.i) {
            return s.compareTo(si.s);
        } else {
            return ((Integer)i).compareTo((Integer)si.i);
        }
    }
    

}

class ShaderStats {
    
    static void countLines(BufferedReader inBuffer) throws IOException {
    }
    
    static String getNextOp(BufferedReader inBuffer) throws IOException {
        return (inBuffer.readLine().split(" ")[0]);
    }
    
    static void analyseCmds(BufferedReader inBuffer) throws IOException {
        // count total number of lines
        int totalLines = 0;
        while (inBuffer.readLine() != null) {
            totalLines++;
        }
        inBuffer.reset();
        // read number of instructions from stats line
        for (int i = 0; i < totalLines - 1; i++) {
            inBuffer.readLine();
        }
        String stats = inBuffer.readLine();
        inBuffer.reset();
        int instLines = Integer.parseInt(stats.split(" ")[1]);

        // position buffer
        for (int i = 0; i < totalLines - instLines - 2; i++) {
            inBuffer.readLine();
        }

        // count instructions
        String asmCmd = "";
        Hashtable<String,Integer> table = new Hashtable<String,Integer>();
        for (int i = 0; i < instLines; i++) {
            asmCmd = getNextOp(inBuffer);
            int n = 0;
            if (table.containsKey(asmCmd)) {
                n = (Integer)table.get(asmCmd);
            }
            table.put(asmCmd, n+1);
        }
        Enumeration eKeys = table.keys();
        StringInt[] values = new StringInt[table.size()];
        String key;
        for (int i = 0 ; eKeys.hasMoreElements() ; i++) {
            key = (String)eKeys.nextElement();
            values[i] = new StringInt(key, (Integer)table.get(key));
        }
        java.util.Arrays.sort(values);
        // output results
        System.out.println(stats);
        for (int i = values.length - 1; i >= 0; i--) {
            System.out.println(values[i]);
        }
    }
    
    public static void main(String[] args) {
        
        if (args.length != 1) {
            System.out.println("Requires 1 argument : file to analyze.");
            System.exit(0);
        }
        
        String filename = args[0];
        try {
            File file = new File(filename);
            FileReader inFile = new FileReader(file);
            BufferedReader inBuffer = new BufferedReader(inFile);
            inBuffer.mark(new Long(file.length()+1).intValue());
            analyseCmds(inBuffer);
            inBuffer.close();
        } catch (IOException e) {
            System.err.println("Failed reading file '" + filename + "'.");
            System.err.println(e);
            System.exit(1);
        }
        
    }
    
}