| Index: grit/format/rc_header.py
|
| ===================================================================
|
| --- grit/format/rc_header.py (revision 0)
|
| +++ grit/format/rc_header.py (revision 0)
|
| @@ -0,0 +1,180 @@
|
| +#!/usr/bin/python2.4
|
| +# Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +'''Item formatters for RC headers.
|
| +'''
|
| +
|
| +import re
|
| +
|
| +from grit.format import interface
|
| +from grit import exception
|
| +from grit import util
|
| +
|
| +from grit.extern import FP
|
| +
|
| +
|
| +class TopLevel(interface.ItemFormatter):
|
| + '''Writes the necessary preamble for a resource.h file.'''
|
| +
|
| + def Format(self, item, lang='', begin_item=True, output_dir='.'):
|
| + if not begin_item:
|
| + return ''
|
| + else:
|
| + header_string = '''// Copyright (c) Google Inc. %d
|
| +// All rights reserved.
|
| +// This file is automatically generated by GRIT. Do not edit.
|
| +
|
| +#pragma once
|
| +''' % (util.GetCurrentYear())
|
| + # Check for emit nodes under the rc_header. If any emit node
|
| + # is present, we assume it means the GRD file wants to override
|
| + # the default header, with no includes.
|
| + for output_node in item.GetOutputFiles():
|
| + if output_node.GetType() == 'rc_header':
|
| + for child in output_node.children:
|
| + if child.name == 'emit':
|
| + if child.attrs['emit_type'] == 'prepend':
|
| + return header_string
|
| + # else print out the default header with include
|
| + return header_string + '''
|
| +#include <atlres.h>
|
| +
|
| +'''
|
| +
|
| +
|
| +class EmitAppender(interface.ItemFormatter):
|
| + '''Adds the content of the <emit> nodes to the RC header file.'''
|
| +
|
| + def Format(self, item, lang='', begin_item=True, output_dir='.'):
|
| + if not begin_item:
|
| + return ''
|
| + else:
|
| + return '%s\n' % (item.GetCdata())
|
| +
|
| +class Item(interface.ItemFormatter):
|
| + '''Writes the #define line(s) for a single item in a resource.h file. If
|
| + your node has multiple IDs that need to be defined (as is the case e.g. for
|
| + dialog resources) it should define a function GetTextIds(self) that returns
|
| + a list of textual IDs (strings). Otherwise the formatter will use the
|
| + 'name' attribute of the node.'''
|
| +
|
| + # All IDs allocated so far, mapped to the textual ID they represent.
|
| + # Used to detect and resolve collisions.
|
| + ids_ = {}
|
| +
|
| + # All textual IDs allocated so far, mapped to the numerical ID they
|
| + # represent. Used when literal IDs are being defined in the 'identifiers'
|
| + # section of the GRD file to define other message IDs.
|
| + tids_ = {}
|
| +
|
| + def _VerifyId(self, id, tid, msg_if_error):
|
| + if id in self.ids_ and self.ids_[id] != tid:
|
| + raise exception.IdRangeOverlap(msg_if_error +
|
| + '\nUse the first_id attribute on grouping nodes (<structures>,\n'
|
| + '<includes>, <messages> and <ids>) to fix this problem.')
|
| + if id < 101:
|
| + print ('WARNING: Numeric resource IDs should be greater than 100 to avoid\n'
|
| + 'conflicts with system-defined resource IDs.')
|
| +
|
| + def Format(self, item, lang='', begin_item=True, output_dir='.'):
|
| + if not begin_item:
|
| + return ''
|
| +
|
| + # Resources that use the RES protocol don't need
|
| + # any numerical ids generated, so we skip them altogether.
|
| + # This is accomplished by setting the flag 'generateid' to false
|
| + # in the GRD file.
|
| + if 'generateid' in item.attrs:
|
| + if item.attrs['generateid'] == 'false':
|
| + return ''
|
| +
|
| + text_ids = item.GetTextualIds()
|
| +
|
| + # We consider the "parent" of the item to be the GroupingNode containing
|
| + # the item, as its immediate parent may be an <if> node.
|
| + item_parent = item.parent
|
| + import grit.node.empty
|
| + while item_parent and not isinstance(item_parent,
|
| + grit.node.empty.GroupingNode):
|
| + item_parent = item_parent.parent
|
| +
|
| + lines = []
|
| + for tid in text_ids:
|
| + if util.SYSTEM_IDENTIFIERS.match(tid):
|
| + # Don't emit a new ID for predefined IDs
|
| + continue
|
| +
|
| + # Some identifier nodes can provide their own id,
|
| + # and we use that id in the generated header in that case.
|
| + if hasattr(item, 'GetId') and item.GetId():
|
| + id = long(item.GetId())
|
| +
|
| + elif ('offset' in item.attrs and item_parent and
|
| + 'first_id' in item_parent.attrs and item_parent.attrs['first_id'] != ''):
|
| + offset_text = item.attrs['offset']
|
| + parent_text = item_parent.attrs['first_id']
|
| +
|
| + try:
|
| + offset_id = long(offset_text)
|
| + except ValueError:
|
| + offset_id = self.tids_[offset_text]
|
| +
|
| + try:
|
| + parent_id = long(parent_text)
|
| + except ValueError:
|
| + parent_id = self.tids_[parent_text]
|
| +
|
| + id = parent_id + offset_id
|
| +
|
| + # We try to allocate IDs sequentially for blocks of items that might
|
| + # be related, for instance strings in a stringtable (as their IDs might be
|
| + # used e.g. as IDs for some radio buttons, in which case the IDs must
|
| + # be sequential).
|
| + #
|
| + # We do this by having the first item in a section store its computed ID
|
| + # (computed from a fingerprint) in its parent object. Subsequent children
|
| + # of the same parent will then try to get IDs that sequentially follow
|
| + # the currently stored ID (on the parent) and increment it.
|
| + elif not item_parent or not hasattr(item_parent, '_last_id_'):
|
| + # First check if the starting ID is explicitly specified by the parent.
|
| + if (item_parent and 'first_id' in item_parent.attrs and
|
| + item_parent.attrs['first_id'] != ''):
|
| + id = long(item_parent.attrs['first_id'])
|
| + self._VerifyId(id, tid,
|
| + 'Explicitly specified numeric first_id %d conflicts with one of the\n'
|
| + 'ID ranges already used.' % id)
|
| + else:
|
| + # Automatically generate the ID based on the first clique from the
|
| + # first child of the first child node of our parent (i.e. when we
|
| + # first get to this location in the code).
|
| +
|
| + # According to
|
| + # http://msdn.microsoft.com/en-us/library/t2zechd4(VS.71).aspx
|
| + # the safe usable range for resource IDs in Windows is from decimal
|
| + # 101 to 0x7FFF.
|
| +
|
| + id = FP.UnsignedFingerPrint(tid)
|
| + id = id % (0x7FFF - 101)
|
| + id += 101
|
| +
|
| + self._VerifyId(id, tid,
|
| + 'Automatic (fingerprint-based) numeric ID for %s (%d) overlapped\n'
|
| + 'with a previously allocated range.' % (tid, id))
|
| +
|
| + if item_parent:
|
| + item_parent._last_id_ = id
|
| + else:
|
| + assert hasattr(item_parent, '_last_id_')
|
| + id = item_parent._last_id_ = item_parent._last_id_ + 1
|
| + self._VerifyId(id, tid,
|
| + 'Wanted to make numeric value for ID %s (%d) follow the numeric value of\n'
|
| + 'the previous ID in the .grd file, but it was already used.' % (tid, id))
|
| +
|
| + if tid not in self.ids_.values():
|
| + self.ids_[id] = tid
|
| + self.tids_[tid] = id
|
| + lines.append('#define %s %d\n' % (tid, id))
|
| + return ''.join(lines)
|
| +
|
|
|
| Property changes on: grit/format/rc_header.py
|
| ___________________________________________________________________
|
| Added: svn:eol-style
|
| + LF
|
|
|
|
|