i have been thinking of several ways to integrate the string escape code in 
logprintf. the more i think about it, the more i like the idea of including 
in wget a stripped-down version of vsnprintf to be used inside logprintf. 
this function would also understand a special escape code (%e? %es?) that 
would actually trigger the escaping of the given string before the 
interpolation (but only if we print to a tty).

to test which kind of conversions are used by wget inside logprintf calls, 
yesterday i came up with this python 2.3 script (i know, it is not very 
pythonic but this is not the point since it works pretty well):

#!/usr/bin/env python

import sys
import sets

debug = False
used_fmt_codes = sets.Set([])

def debug_print (str):
    if debug:
        print str

def debug_format (str):
    pretty_print (str)
    examine_format (str)

def is_escaped (str, index):
    tmp = index - 1
    count = 0
    while (str[tmp] == '\\'):
        tmp -= 1
        count += 1
    if count % 2:
        return True
    return False

def retrieve_format_string (str):
    i = str.find ('"')
    j = str.find ('"', i + 1)
    while (is_escaped(str, j)):
        j = str.find ('"', j + 1)
    return str[i:j+1]

def retrieve_format_code (str, index):
    chars = "c%msbpxXdiuofg"
    i = index + 1
    while (str[i] not in chars):
        i += 1
    return str[index:i+1]
    
def examine_format (str):
    fmtstr = retrieve_format_string (str)
    i = fmtstr.find ('%')
    debug_print("format code(s):")
    while (i >= 0):
        fmt = retrieve_format_code (fmtstr, i)
        #print fmt
        used_fmt_codes.add(fmt)
        i = fmtstr.find ('%', i + len(fmt))

def pretty_print (str):
    print " ".join(str.split())
    
def process_logprintf (file, func):
    keep_scanning = False
    for line in file:
        if not keep_scanning:
            i = line.find("logprintf")
            if i >= 0:
                debug_print("found logprintf")
                debug_print(line[:-1])
                j = line.find ('(', i + len("logprintf"))
                if j < 0:
                    debug_print("checking next line for open brace")
                    keep_scanning = True
                    continue
                count = 1
                debug_print("found open brace, count = %d" % count)
                for c in range (j+1, len(line)-1):
                    if line[c] == '(':
                        count += 1
                        debug_print("found open brace, count = %d" % count)
                    elif line[c] == ')':
                        count -= 1
                        debug_print("found closing brace, count = %d" % count)
                    if count == 0:
                        str = line[i:c+1]
                        func(str)
                        break
                if count != 0:
                    debug_print("keep scanning on next line, count = %d" % 
count)
                    str = line[i:-1]
                    keep_scanning = True
        else:
            debug_print("scanning going on")
            debug_print(line[:-1])
            for c in range (0, len(line)-1):
                if line[c] == '(':
                    count += 1
                    debug_print("found opening brace, count = %d" % count)
                elif line[c] == ')':
                    count -= 1
                    debug_print("found closing brace, count = %d" % count)
                if count == 0:
                    str += line[:c+1]
                    keep_scanning = False
                    func(str)
                    break
            if count != 0:
                debug_print("keep scanning on next line, count = %d" % count)
                str += line[:-1]
                debug_print(line[:-1])

if __name__ == "__main__":
    for i in range (1, len(sys.argv)):
        print "opening file %s" % sys.argv[i]
        file = open(sys.argv[i])
        process_logprintf(file, examine_format)
    print used_fmt_codes
        
# vim: et ts=4 sw=4


the result is:

Set(['%5ld', '%%', '%d', '%ld', '%2d', '%.2f', '%3d', '%c', '%s', '%*s'])

so, all the conversions we need are:

- integer with long and field size
- % charachter escape
- charachter
- string
- float with decimal field size

given this consideration, what i was planning to do is to borrow some code 
from the vsnprintf implementation in dietlibc and adapt it for our needs.

what do you think about it?

-- 
Aequam memento rebus in arduis servare mentem...

Mauro Tortonesi

University of Ferrara - Dept. of Eng.    http://www.ing.unife.it
Institute of Human & Machine Cognition   http://www.ihmc.us
Deep Space 6 - IPv6 for Linux            http://www.deepspace6.net
Ferrara Linux User Group                 http://www.ferrara.linux.it

Reply via email to