def oom(exp):
    if exp == 'm':
        return 1.e-3
    elif exp == 'u':
        return 1.e-6
    elif exp == 'n':
        return 1.e-9
    elif exp == 'p':
        return 1.e-12
    elif exp == 'f':
        return 1.e-15
    elif exp == 'a':
        return 1.e-18
    elif exp == 'z':
        return 1.e-21
    elif exp == 'y':
        return 1.e-24
    elif exp == 'k':
        return 1.e3
    elif exp == 'M':
        return 1.e6
    elif exp == 'G':
        return 1.e9
    elif exp == 'T':
        return 1.e12


def parse_print_file(filename,rise_th,fall_th):
    import re
    f = open(filename)
    comment = re.compile(r"^\*")
    start_value = re.compile(r"^x")
    stop_value = re.compile(r"^y")
    signal_name = re.compile(r"\s+([\w\[\]\(\)]+)\s+$")
    signal_name_wrap = re.compile(r"\s+\+\s+\+\s+([\w\[\]\(\)]+)")
    numbers = re.compile(r"([\d\.]+)([TGMkmunpfazy]?)\s+([\d\.]+)([TGMkmunpfazy]?)")
    found_start = 0
    current_signal_name = ''
    signal_value = 0
    read_numbers = False
    rising_edges = {}
    falling_edges = {}

    rise_check_time = 10.0e-9
    fall_check_time = 10.0e-9
    check_wait_time = 0.7e-9
    epsilon = 0.01
    last_voltage = 0

    for line in f:
        if found_start > 0:
            if found_start < 3:
                found_start += 1
                continue
            elif found_start >= 3 and not read_numbers:
                m = signal_name.match(line)
                if m:
                    current_signal_name = m.group(1)
                    signal_value = 0
                else:
                    m = signal_name_wrap.match(line)
                    if m:
                        current_signal_name += m.group(1)
                    else:
                        read_numbers = True

                found_start += 1
        else:
            read_numbers = False
            if comment.match(line):
                continue
            elif start_value.match(line):
                found_start = 1

        if read_numbers:
            if stop_value.match(line):
                found_start = 0
            else:
                m = numbers.search(line)
                if m:
                    time = float(m.group(1))
                    if m.group(2):
                        time = time*oom(m.group(2))
                    voltage = float(m.group(3))
                    if m.group(4):
                        voltage = voltage*oom(m.group(4))
                    if signal_value == 0:
                        if voltage < fall_th:
                            signal_value = 'R'
                        elif voltage > rise_th:
                            signal_value = 'F'
                    elif signal_value == 'R':
                        if voltage > rise_th:
                            # found a threshold crossing
                            # register a rising edge and go
                            # to check state
                            if not rising_edges.has_key(current_signal_name):
                                rising_edges[current_signal_name] = []
                            rising_edges[current_signal_name].append(time)
                            # go to check state
                            signal_value = 'R_check'
                            rise_check_time = time
                            last_voltage = voltage
                    elif signal_value == 'R_check':
                        # if max. check state time has been reached
                        # check again if the signal has settled high
                        if time > (rise_check_time + check_wait_time):
                            if voltage < rise_th:
                                # drop last rising edge if signal hasn't
                                # settled high
                                del rising_edges[current_signal_name][-1]
                                #print "Dropping rising edge for "+current_signal_name
                                # since last rising edge was a failure, look again for a rising edge
                                signal_value = 'R'
                            else:
                                # go look for a falling edge
                                signal_value = 'F'
                        # if max. check state time has not been reached
                        # check for monotony
                        else:
                            if last_voltage > voltage and (last_voltage - voltage) > epsilon:
                                del rising_edges[current_signal_name][-1]
                                #print "Dropping rising edge for "+current_signal_name
                                signal_value = 'R_wait'