Index: xml/patch-headers.py
===================================================================
RCS file: /sources/avr-libc/avr-libc/xml/patch-headers.py,v
retrieving revision 1.11
diff -u -r1.11 patch-headers.py
--- xml/patch-headers.py	20 Dec 2007 20:43:54 -0000	1.11
+++ xml/patch-headers.py	26 Mar 2009 20:14:04 -0000
@@ -1,6 +1,8 @@
 #! /usr/bin/env python
+# -*- coding: UTF-8 -*-
 #
 # Copyright (c) 2005,2006,2007  Joerg Wunsch
+# Copyright (c) 2009, Frédéric Nadeau
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -212,6 +214,7 @@
     dump_vectors (root, tradheader)
     dump_ioregs (root)
     dump_boot_info (root)
+    dump_pin_info (root)
     dump_footer (root)
     sys.stdout.close()
     sys.stdout = savedstdout
@@ -221,6 +224,13 @@
 r = re.compile(r'#\s*define\s+((SIG_)?[A-Z0-9_]+(_vect)?)\s+_VECTOR[(](\d+)[)]')
 
 print "Patching headers:"
+
+#Ask user if it wants to apply vector patch
+doVectorPatch = raw_input("Do you want to apply vector patch(yes/no)?: ")
+doPinDescPatch = raw_input("Do you want to apply pin description patch(yes/no)?: ")
+doVector2Patch = raw_input("Do you want to apply vector patch(yes/no)?: ")
+
+
 docs = {}
 nlist = table.keys()
 nlist.sort()
@@ -246,96 +256,169 @@
 
     parseddev = parser.getContentHandler().dev
 
-    # Find any interrupt vector definitions, and rewrite them.
-    endcount = len(lines)
-    idx = 0
-    while idx < endcount:
-        line = lines[idx]
-        try:
-            m = r.match(line)
-        except TypeError:
-            print line
-            exit(0)
-        if m != None:
-            firstidx = idx
-            key = m.group(4)            # this is the vector number
-            ele = parseddev.interrupts[key]
-
-            if lines[idx - 1].find(ele.description.data) >= 0:
-                # there is a /* description */ comment in the previous line,
-                # drop it
-                if idx - 1 < firstidx:
-                    firstidx = idx - 1
-
-            lastidx = idx + 1
-            while r.match(lines[lastidx]) and r.match(lines[lastidx]).group(4) == key:
-                # more vector definitions follow, skip them
-                lastidx += 1
-
-            while re.match('^$', lines[lastidx]):
-                # blank lines follow, skip them, too
-                lastidx += 1
-
-            # Now, lastidx points to the first line not belonging
-            # to our current vector definition.  lastidx - firtidx
-            # is the number of lines affected.
-
-            count = lastidx - firstidx
-            del lines[firstidx:lastidx]
-
-            # now, build a new vector entry
-            vecttext = []
-            newcount = 0
-            if len(ele.description.data) > 0:
-                vecttext.append("/* " + ele.description.data + " */\n")
-                newcount += 1
-            vecttext.append("#define " + ele.sig_name.data +
-                            create_tabs(ele.sig_name.data) +
-                            "_VECTOR(" + key + ")\n")
-            newcount += 1
+    if(doVectorPatch == "yes"):
+        # Find any interrupt vector definitions, and rewrite them.
+        endcount = len(lines)
+        idx = 0
+        while idx < endcount:
+            line = lines[idx]
             try:
-                for x in ele.alt_name.data:
-                    vecttext.append("#define " + x +
-                                    create_tabs(x) + "_VECTOR(" + key + ")\n")
+                m = r.match(line)
+            except TypeError:
+                print line
+                exit(0)
+            if m != None:
+                firstidx = idx
+                key = m.group(4)            # this is the vector number
+                ele = parseddev.interrupts[key]
+    
+                if lines[idx - 1].find(ele.description.data) >= 0:
+                    # there is a /* description */ comment in the previous line,
+                    # drop it
+                    if idx - 1 < firstidx:
+                        firstidx = idx - 1
+    
+                lastidx = idx + 1
+                while r.match(lines[lastidx]) and r.match(lines[lastidx]).group(4) == key:
+                    # more vector definitions follow, skip them
+                    lastidx += 1
+    
+                while re.match('^$', lines[lastidx]):
+                    # blank lines follow, skip them, too
+                    lastidx += 1
+    
+                # Now, lastidx points to the first line not belonging
+                # to our current vector definition.  lastidx - firtidx
+                # is the number of lines affected.
+    
+                count = lastidx - firstidx
+                del lines[firstidx:lastidx]
+    
+                # now, build a new vector entry
+                vecttext = []
+                newcount = 0
+                if len(ele.description.data) > 0:
+                    vecttext.append("/* " + ele.description.data + " */\n")
                     newcount += 1
-            except AttributeError:
-                # no alt_name present
-                pass
-            vecttext.append('\n')
-            newcount += 1
-
-            # insert new vector entry
-            lines[firstidx:firstidx] = vecttext
-
-            endcount += newcount - count
-            # back off beyond what we've just been working on
-            idx = firstidx + newcount
-
-            # collect documentation for this vector
-            try:
-                if type(devname) is TupleType:
-                    for d in devname:
-                        docs[ele.sig_name.data][2].append(d)
-                else:
-                    docs[ele.sig_name.data][2].append(devname)
-            except KeyError:
+                vecttext.append("#define " + ele.sig_name.data +
+                                create_tabs(ele.sig_name.data) +
+                                "_VECTOR(" + key + ")\n")
+                newcount += 1
+                try:
+                    for x in ele.alt_name.data:
+                        vecttext.append("#define " + x +
+                                        create_tabs(x) + "_VECTOR(" + key + ")\n")
+                        newcount += 1
+                except AttributeError:
+                    # no alt_name present
+                    pass
+                vecttext.append('\n')
+                newcount += 1
+    
+                # insert new vector entry
+                lines[firstidx:firstidx] = vecttext
+    
+                endcount += newcount - count
+                # back off beyond what we've just been working on
+                idx = firstidx + newcount
+    
+                # collect documentation for this vector
                 try:
                     if type(devname) is TupleType:
-                        docs[ele.sig_name.data] = (ele.alt_name.data,
-                                                   ele.description.data,
-                                                   [])
                         for d in devname:
                             docs[ele.sig_name.data][2].append(d)
                     else:
-                        docs[ele.sig_name.data] = (ele.alt_name.data,
-                                                   ele.description.data,
-                                                   [devname])
-                except AttributeError:
-                    # no alt name
-                    pass
-        else:
-            # no match, increment index
-            idx += 1
+                        docs[ele.sig_name.data][2].append(devname)
+                except KeyError:
+                    try:
+                        if type(devname) is TupleType:
+                            docs[ele.sig_name.data] = (ele.alt_name.data,
+                                                       ele.description.data,
+                                                       [])
+                            for d in devname:
+                                docs[ele.sig_name.data][2].append(d)
+                        else:
+                            docs[ele.sig_name.data] = (ele.alt_name.data,
+                                                       ele.description.data,
+                                                       [devname])
+                    except AttributeError:
+                        # no alt name
+                        pass
+            else:
+                # no match, increment index
+                idx += 1
+    
+    if(doPinDescPatch == "yes"):
+        
+        #check if already done
+        done = 0
+        for i in range(lines.__len__()):
+            if re.search("Device Pin Definitions", lines[i]):
+                done = 1
+                break
+        
+        if done != 1:
+        
+            # Add copyright
+            idxLast = -1
+            for i in range(lines.__len__()):
+                if re.match("   All rights reserved.", lines[i]):
+                    idxLast = i
+                    break
+            
+            if idxLast > 0:
+                lines.insert(idxLast, '   Copyright (c) 2009, Frédéric Nadeau\n')
+            
+            
+            #Now add device info
+            #Find last #endif
+            idxLast = -1
+            for i in range(lines.__len__()):
+                if re.match("#endif", lines[i]):
+                    idxLast = i
+            
+            idxLast -= 1
+            
+            if idxLast > 0:
+                lines.insert(idxLast, '\n/* Device Pin Definitions */\n')
+                idxLast += 1
+                #Try to short pin definition
+                shorted = []
+                for element in parseddev.pin_definition:
+                    pin = parseddev.pin_definition[element]
+                    done = 0
+                    for index, shortedElement in enumerate(shorted):
+                        if str(shortedElement.name) > str(pin.name):
+                            shorted.insert(index,pin)
+                            done = 1
+                            break
+                    if done == 0:
+                        shorted.append(pin)
+                    
+                    
+                
+                for i in range(shorted.__len__()):
+                    element = shorted[i]
+                    for subElement in str(element.alt_name.data).split(':'):
+                        pinString = '#define DDR_%s  \tDDR%c\n#define PORT_%s \tPORT%c\n#define PIN_%s  \tPIN%c\n#define %s_IDX  \t%c\n\n' % (subElement, element.port, subElement, element.port, subElement, element.port, subElement, element.idx)
+                        lines.insert(idxLast, pinString)
+                        idxLast += 1
+                    continue
+    
+    if doVector2Patch == 'yes':
+        
+        r2 = re.compile(r'#\s*define\s+(([A-Z0-9_])+(_vect))\s+_VECTOR[(](\d+)[)]')
+        
+        for i in range(lines.__len__()):
+            try:
+                m = r2.match(lines[i])
+            except TypeError:
+                print lines[i]
+                exit(0)
+            if m != None:
+                newVectString = '%s_num %s%s\n' % (m.group(0).split('_vect')[0],m.group(0).split('_vect')[1].split('_VECTOR')[0], m.group(4))
+                lines[i] = newVectString + lines[i] 
+        
 
     newh = open(header, "w")
     for line in lines:
@@ -352,7 +435,6 @@
     if re.match('^[A-Z][a-z]* [A-Z][a-z]*', x):
         # if at least two capitalized words are present, trust that
         user = x
-
 sys.stdout.write("Writing documentation to " + docfilename + "... ")
 savedstdout = sys.stdout
 sys.stdout = open(docfilename, "w")
Index: xml/Atmel2libc.py
===================================================================
RCS file: /sources/avr-libc/avr-libc/xml/Atmel2libc.py,v
retrieving revision 1.12
diff -u -r1.12 Atmel2libc.py
--- xml/Atmel2libc.py	20 Dec 2007 20:43:54 -0000	1.12
+++ xml/Atmel2libc.py	26 Mar 2009 20:14:03 -0000
@@ -1,6 +1,8 @@
 #! /usr/bin/env python
+# -*- coding: UTF-8 -*-
 #
 # Copyright (c) 2004,2005  Theodore A. Roth
+# Copyright (c) 2009, Frédéric Nadeau
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -35,6 +37,8 @@
 
 import string
 import re
+import sys
+
 from xml.parsers import expat
 
 class Element:
@@ -501,6 +505,213 @@
 
         print '  </bootloader>'
 
+def dump_pin_info (root):
+    # Find package information.
+    # Most files have only one package. In the event that we do have more than one package
+    # use the package with biggest pin-count.
+    path = ['AVRPART', 'PACKAGE']
+    info = root.getSubTree (path)
+    
+    biggestPinCount = 0
+    biggestPkgName = None
+    
+    if info:
+        # Under <PACKAGE>, there is <PACKAGES> and one for every package like <DIP>
+        for element in info.children:
+            # We are not interested in element <PACKAGES>
+          if (element.name != "PACKAGES"):
+              for subElement in element.children:
+                  # Packages like <DIP> containt <NMB_PIN> and a one element for each pin <PINx>
+                  if (subElement.name == "NMB_PIN"):
+                      if (subElement.cdata > biggestPinCount):
+                          biggestPinCount = subElement.cdata
+                          biggestPkgName = element.name
+                      break #we found the <NMB_PIN> all the others are <PINx>
+    else:
+        print '  <pin_definition/>'
+        sys.stderr.write(' Pin information not found! ')
+        return
+        
+    path = ['AVRPART', 'PACKAGE', biggestPkgName]
+    info = root.getSubTree (path)
+    
+    if info:
+        print '  <pin_definition>'
+        
+        for element in info.children:
+             if (element.name != "NMB_PIN"):
+                # Check if using <NAME> or <ALT_NAME> + <PIN_NAME>
+                
+                pinName = None
+                altName = None
+                
+                for subElement in element.children:
+                    if (subElement.name == "NAME"):
+                        # Pxy can be either at the beginning or at the end
+                        list = parsePinName(subElement.cdata)
+                        
+                        # Remove unwanted pin name here
+                        removeUnwantedPinName(list)
+                        
+                        # if len==0 there is nothing
+                        # if len==1 there is only Pxy, VCC, GND, etc
+                        if(list.__len__() < 2):
+                            continue
+                        
+                        # Pxy can is usually the first one, sometimes the last one
+                        # It might even append that it is in the middle.
+                        for subList in list:
+                            if (subList[0] == 'P') and (subList.__len__() == 3):
+                                pinName = [subList]
+                                list.remove(subList)
+                                altName = list
+                                break
+                        
+                    elif (subElement.name == "PIN_NAME"):
+                        # Element in PIN_NAME and ALT_NAME are sometimes inverted
+                        list = parsePinName(subElement.cdata)
+                        
+                        ##Remove unwanted pin name here
+                        removeUnwantedPinName(list)
+                        
+                        if(list.__len__() == 0):
+                            continue
+                        
+                        pinName = list
+                        
+                    elif (subElement.name == "ALT_NAME"):
+                        list = parsePinName(subElement.cdata)
+                        
+                        ##Remove unwanted pin name here
+                        removeUnwantedPinName(list)
+                        
+                        if(list.__len__() == 0):
+                            continue
+                        
+                        altName = list
+              
+                if (altName != None) and (pinName != None):
+                    #check if PIN_NAME and ALT_NAME as been reverse
+                    #Pxy should be in PIN_NAME and alone!
+                    if(altName.__len__() == 1) and (altName[0][0] == 'P') and (altName[0].__len__() == 3):
+                        #swap pinName and altName
+                        tmp = altName
+                        altName = pinName
+                        pinName = tmp
+                    
+                    print '    <pin name="%s" idx="%c" port="%c" >' % (pinName[0], pinName[0][2], pinName[0][1])
+                    altNamePrint = ''
+                    for item in altName:
+                        altNamePrint = altNamePrint + modAltPinName(item) + ':'
+                            
+                    altNamePrint = altNamePrint[:-1]
+                    print '      <alt_name>%s</alt_name>' % altNamePrint
+                    print '    </pin>'
+                 
+        print '  </pin_definition>'
+    else:
+        print '  <pin_definition/>'
+    
+# Pass a sting like:
+#    [PB3]
+#    [PB3:RX]
+#    PB3:RX
+# and will return a list of string:
+#    return [ "PB3" ]
+#    return [ "PB3", "RX" ]
+#    return [ "PB3", "RX" ]
+# make sure that what ever it returns is a list!
+def parsePinName (element):
+    
+    if(element == ''):
+        return ''.split()
+    
+    #first remove leading [ or ( or {
+    if (element[0] == '[') or (element[0] == '('):
+        element = element[1:]
+        
+    #now remove trailing ones
+    if (element[-1] == ']') or (element[-1] == ')'):
+        element = element[:-1]
+        
+    # check if list is separated by : or ;
+    if ';' in element: 
+        element = element.split(';')
+    elif ':' in element: 
+        element = element.split(':')
+    else:
+        element = element.split()
+    
+    return element
+
+# This will take a string list and remove unwanted pin name such as:
+# RESET XTAL1 XTAL2 VCC GND NC AREF AVCC
+def removeUnwantedPinName(list):
+    for item in list:
+        # Sometime RESET has a leading ', sometimes not
+        # No need for alim pins, VCC, GND
+        # No need for No Connection pins, NC
+        # No need for ADC alim pins, AVCC, AREF, AGND
+        # No need for JTAG pins, TCK, TMS, TDO, TDI, TD0 Quite a few have a typo
+        # No need for Timer Oscillator pins, TOSC1, TOSC2
+        # Programming data input/output PDI, PDO
+        # Hardware boot loader pin HWB
+        # Some device has PWMx
+        if(item== "RESET") or \
+        (item== "'RESET") or \
+        (item== "NC") or \
+        (item == "XTAL1") or \
+        (item == "XTAL2") or \
+        (item == "VCC") or \
+        (item == "GND") or \
+        (item == "AREF") or \
+        (item == "AVCC") or \
+        (item == "AGND") or \
+        (item == "TCK") or \
+        (item == "TMS") or \
+        (item == "TDO") or \
+        (item == "TD0") or \
+        (item == "TDI") or \
+        (item == "TOSC1") or \
+        (item == "TOSC2") or \
+        (item == "PDI") or \
+        (item == "PDO")or \
+        (item == "PWM0")or \
+        (item == "PWM1")or \
+        (item == "PWM2")or \
+        (item == "PWM3")or \
+        (item == "PWM4")or \
+        (item == "PWM5")or \
+        (item == "PWM6")or \
+        (item == "PWM7")or \
+        (item == "PWM8")or \
+        (item == "HWB"):
+            list.remove(item)
+    
+    return list
+
+# this function correct AVR Studio anomaly 
+# and apply some modification so that it can be define in c
+def modAltPinName(pinName):
+    
+    # Remove leading ' that indicate that the pin is active low
+    if (pinName[0] == '\''):
+        pinName = pinName[1:]
+        
+    # remove ending + and replace by a _P
+    if (pinName[-1] == '+'):
+        pinName = '%s_P' % pinName[:-1]
+    
+    # remove ending - and replace by a _N
+    if (pinName[-1] == '-'):
+        pinName = '%s_N' % pinName[:-1]
+        
+    # change CLK0 for CLKO
+    if (pinName == "CLK0"):
+        pinName = "CLKO"
+    
+    return pinName
+
 class HeaderToVec:
     'Parse header file for traditional vector names'
 
Index: xml/Descparser.py
===================================================================
RCS file: /sources/avr-libc/avr-libc/xml/Descparser.py,v
retrieving revision 1.1
diff -u -r1.1 Descparser.py
--- xml/Descparser.py	21 Oct 2005 21:00:01 -0000	1.1
+++ xml/Descparser.py	26 Mar 2009 20:14:03 -0000
@@ -1,6 +1,8 @@
 #! /usr/bin/env python
+# -*- coding: UTF-8 -*-
 #
 # Copyright (c) 2004  Theodore A. Roth
+# Copyright (c) 2009, Frédéric Nadeau
 # All rights reserved.
 #
 # Redistribution and use in source and binary forms, with or without
@@ -169,6 +171,26 @@
             raise 'Duplicate boot mode entry', obj
 
         self[obj.num] = obj
+        
+class Pin (XML_Mixin):
+    children = {
+        'alt_name': PCData,
+        }
+        
+class PinDefinition (dict, XML_Mixin):
+    children = {
+        'pin': Pin
+        }
+
+    def __init__ (self, attrs):
+        dict.__init__ (self)
+        XML_Mixin.__init__ (self, attrs)
+
+    def add_child (self, name, obj):
+        # Use the Pin 'name' attr as the key for the child object.
+        if self.has_key (obj.name):
+            raise 'Duplicate io register entry', obj
+        self[obj.name] = obj
 
 class Device (XML_Mixin):
     children = {
@@ -177,7 +199,8 @@
         'memory_sizes': MemorySizes,
         'interrupts': Interrupts,
         'ioregisters': IORegisterDict,
-        'bootloader': BootLoader
+        'bootloader': BootLoader,
+        'pin_definition' : PinDefinition
         }
 
 class DescHandler (ContentHandler):
