Merged changes in the trunk up to revision 45133.

Conflicts resolved:
source/blender/blenloader/intern/readfile.c
source/blender/blenloader/intern/writefile.c
source/blender/bmesh/intern/bmesh_construct.c
source/blender/bmesh/intern/bmesh_mesh_conv.c
source/blender/bmesh/intern/bmesh_mesh_conv.h
source/blender/editors/interface/interface_templates.c
source/blender/editors/interface/resources.c
source/blender/editors/mesh/bmesh_select.c
source/blender/editors/mesh/bmesh_tools.c
source/blender/editors/space_view3d/drawobject.c
source/blender/render/intern/source/shadeoutput.c
This commit is contained in:
Tamito Kajiyama 2012-03-25 08:20:19 +00:00
commit 3b711a6ed0
1200 changed files with 77004 additions and 63870 deletions

@ -124,7 +124,7 @@ mark_as_advanced(WITH_PYTHON) # dont want people disabling this unless they rea
mark_as_advanced(WITH_PYTHON_SECURITY) # some distrobutions see this as a security issue, rather than have them patch it, make a build option.
option(WITH_PYTHON_SAFETY "Enable internal API error checking to track invalid data to prevent crash on access (at the expense of some effeciency, only enable for development)." OFF)
option(WITH_PYTHON_MODULE "Enable building as a python module (experemental, only enable for development)" OFF)
option(WITH_PYTHON_MODULE "Enable building as a python module (experimental, only enable for development)" OFF)
option(WITH_BUILDINFO "Include extra build details (only disable for development & faster builds)" ON)
option(WITH_IK_ITASC "Enable ITASC IK solver (only disable for development & for incompatible C++ compilers)" ON)
option(WITH_FFTW3 "Enable FFTW3 support (Used for smoke and audio effects)" OFF)
@ -176,7 +176,7 @@ option(WITH_MOD_SMOKE "Enable Smoke Modifier (Smoke Simulation)" ON)
option(WITH_MOD_DECIMATE "Enable Decimate Modifier" ON)
option(WITH_MOD_BOOLEAN "Enable Boolean Modifier" ON)
option(WITH_MOD_REMESH "Enable Remesh Modifier" ON)
option(WITH_MOD_CLOTH_ELTOPO "Enable Experemental cloth solver" OFF)
option(WITH_MOD_CLOTH_ELTOPO "Enable Experimental cloth solver" OFF)
mark_as_advanced(WITH_MOD_CLOTH_ELTOPO)
option(WITH_MOD_OCEANSIM "Enable Ocean Modifier" OFF)
@ -262,25 +262,23 @@ if(APPLE)
endif()
message(STATUS "Detected system-version: " ${OSX_SYSTEM})
if(${OSX_SYSTEM} GREATER 10.6)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.6" CACHE STRING "" FORCE) # 10.7 does not have 10.5sdk !!!
else()
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our minimum target
if(NOT CMAKE_OSX_DEPLOYMENT_TARGET)
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.5" CACHE STRING "" FORCE) # 10.5 is our minimum target, if you have higher sdk, weak linking happens
endif()
if(${CMAKE_GENERATOR} MATCHES "Xcode")
if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4)
##### workaround for actual official cmake incompatibility with xcode 4.3 #####
if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var
message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip")
endif()
### end workaround for actual official cmake incompatibility with xcode 4.3 ###
if(${XCODE_VERSION} VERSION_EQUAL 4 OR ${XCODE_VERSION} VERSION_GREATER 4 AND ${XCODE_VERSION} VERSION_LESS 4.3)
# Xcode 4 defaults to the Apple LLVM Compiler.
# Override the default compiler selection because Blender only compiles with gcc
# Override the default compiler selection because Blender only compiles with gcc up to xcode 4.2
set(CMAKE_XCODE_ATTRIBUTE_GCC_VERSION "com.apple.compilers.llvmgcc42")
message(STATUS "Setting compiler to: " ${CMAKE_XCODE_ATTRIBUTE_GCC_VERSION})
##### workaround for actual official cmake incompatibility with xcode 4.3 #####
if(${XCODE_VERSION} MATCHES '') # cmake fails due looking for xcode in the wrong path, thus will be empty var
message("Official cmake does not yet support Xcode 4.3, get a patched version here: http://www.jensverwiebe.de/Blender/CMake%202.8-7patched.zip")
endif()
##### end workaround for actual official cmake incompatibility with xcode 4.3 #####
endif()
else() # unix makefile generator does not fill XCODE_VERSION var, so we get it with a command
execute_process(COMMAND xcodebuild -version OUTPUT_VARIABLE XCODE_VERS_BUILDNR )
@ -294,6 +292,7 @@ if(APPLE)
option(WITH_LIBS10.5 "Use 10.5 libs (needed for 64bit builds)" OFF)
endif()
#-----------------------------------------------------------------------------
# Check for conflicting/unsupported configurations
@ -353,13 +352,39 @@ if(WITH_CYCLES OR WITH_CARVE)
set(WITH_BOOST ON)
endif()
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
# don't store paths to libs for portable distrobution
if(WITH_INSTALL_PORTABLE)
set(CMAKE_SKIP_BUILD_RPATH TRUE)
endif()
if(WITH_GHOST_SDL OR WITH_HEADLESS)
set(WITH_GHOST_XDND OFF)
endif()
TEST_SSE_SUPPORT(COMPILER_SSE_FLAG COMPILER_SSE2_FLAG)
#-----------------------------------------------------------------------------
# Check for valid directories
# ... svn extern paths can be missing because of svn-git.
if(WITH_INTERNATIONAL)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/release/datafiles/locale")
message(WARNING "Translation path '${CMAKE_SOURCE_DIR}/release/datafiles/locale' is missing, "
"This is an 'svn external', which are known not to work with bridges to other version "
"control systems, disabling 'WITH_INTERNATIONAL'.")
set(WITH_INTERNATIONAL OFF)
endif()
endif()
if(WITH_PYTHON)
if(NOT EXISTS "${CMAKE_SOURCE_DIR}/release/scripts/addons")
message(WARNING "Addons path '${CMAKE_SOURCE_DIR}/release/scripts/addons' is missing, "
"This is an 'svn external', which are known not to work with bridges to other version "
"control systems: * CONTINUING WITHOUT ADDONS *")
endif()
endif()
#-----------------------------------------------------------------------------
# Initialize un-cached vars, avoid unused warning
@ -1097,12 +1122,12 @@ elseif(APPLE)
endif()
if(${XCODE_VERSION} LESS 4.3)
SET(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${CMAKE_OSX_DEPLOYMENT_TARGET}.sdk CACHE PATH "" FORCE )
SET(CMAKE_OSX_SYSROOT /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk CACHE PATH "" FORCE ) # use guaranteed existing sdk
else()
# note: i don't use xcode-select path on purpose, cause also /Applications/Xcode.app would be allowed
# absolute pathes are more foolproof here !
SET(OSX_SYSROOT_PREFIX /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform)
SET(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${CMAKE_OSX_DEPLOYMENT_TARGET}.sdk)
SET(OSX_DEVELOPER_PREFIX /Developer/SDKs/MacOSX${OSX_SYSTEM}.sdk) # use guaranteed existing sdk
SET(CMAKE_OSX_SYSROOT ${OSX_SYSROOT_PREFIX}/${OSX_DEVELOPER_PREFIX} CACHE PATH "" FORCE)
endif()
@ -1533,14 +1558,6 @@ if(MSVC10)
endif()
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
if(WITH_LIBMV)
message(WARNING "Using Clang as CXX compiler: disabling WITH_LIBMV, this feature will be missing.")
set(WITH_LIBMV OFF)
endif()
endif()
# ensure python header is found since detection can fail, this could happen
# with _any_ library but since we used a fixed python version this tends to
# be most problematic.

@ -95,7 +95,7 @@ if XCODE_CUR_VER >= '4.3': ## since version 4.3, XCode and developer dir are bu
#Defaults openMP to true if compiler handles it ( only gcc 4.6.1 and newer )
# if your compiler does not have accurate suffix you may have to enable it by hand !
if CC.endswith('4.6.1'):
if CC[:-2].endswith('4.6'):
WITH_BF_OPENMP = True # multithreading for fluids, cloth, sculpt and smoke
else:
WITH_BF_OPENMP = False

@ -340,6 +340,7 @@ def creator(env):
if env['OURPLATFORM'] in ('win32-vc', 'win32-mingw', 'linuxcross', 'win64-vc'):
incs.append(env['BF_PTHREADS_INC'])
incs.append('#/intern/utfconv')
env.Append(CPPDEFINES=defs)
env.Append(CPPPATH=incs)
@ -617,7 +618,7 @@ def AppIt(target=None, source=None, env=None):
commands.getoutput(cmd)
cmd = 'find %s/%s.app -name __MACOSX -exec rm -rf {} \;'%(installdir, binary)
commands.getoutput(cmd)
if env['CC'].endswith('4.6.1'): # for correct errorhandling with gcc 4.6.1 we need the gcc.dylib to link, thus distribute in app-bundle
if env['CC'][:-2].endswith('4.6'): # for correct errorhandling with gcc 4.6.x we need the gcc.dylib to link, thus distribute in app-bundle
cmd = 'mkdir %s/%s.app/Contents/MacOS/lib'%(installdir, binary)
commands.getoutput(cmd)
instname = env['BF_CXX']

@ -1806,9 +1806,9 @@ Game Types (bge.types)
object = cont.owner
for mesh in object.meshes:
for material in mesh.materials:
for v_index in range(mesh.getVertexArrayLength(mat)):
vertex = mesh.getVertex(mat, v_index)
for m_index in range(len(mesh.materials)):
for v_index in range(mesh.getVertexArrayLength(m_index)):
vertex = mesh.getVertex(m_index, v_index)
# Do something with vertex here...
# ... eg: colour the vertex red.
vertex.colour = [1.0, 0.0, 0.0, 1.0]

@ -0,0 +1,134 @@
..
This document is appended to the auto generated bmesh api doc to avoid clogging up the C files with details.
to test this run:
./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py -- --partial bmesh* ; cd doc/python_api ; sphinx-build sphinx-in sphinx-out ; cd ../../
Intro
-----
This API gives access the blenders internal mesh editing api, featuring geometry connectivity data and
access to editing operations such as split, separate, collapse and dissolve.
The features exposed closely follow the C API,
giving python access to the functions used by blenders own mesh editing tools.
For an overview of BMesh data types and how they reference each other see:
`BMesh Design Document <http://wiki.blender.org/index.php/Dev:2.6/Source/Modeling/BMesh/Design>`_ .
.. note::
**Disk** and **Radial** data is not exposed by the python api since this is for internal use only.
.. warning::
This API is still in development and experimental, while we don't expect to see large changes,
many areas are not well tested yet and so its possible changes will be made that break scripts.
*Campbell Barton, 13, March 2012*
.. warning::
TODO Items Are
* add access to BMesh **walkers**
* add a way to re-tessellate an editmode bmesh.
* add deform vert custom-data access.
Example Script
--------------
.. literalinclude:: ../../../release/scripts/templates/bmesh_simple.py
Stand-Alone Module
^^^^^^^^^^^^^^^^^^
The bmesh module is written to be standalone except for :mod:`mathutils`
which is used for vertex locations and normals.
The only other exception to this are when converting mesh data to and from :class:`bpy.types.Mesh`.
Mesh Access
-----------
There are 2 ways to access BMesh data, you can create a new BMesh by converting a mesh from
:class:`bpy.types.BlendData.meshes` or by accessing the current edit mode mesh.
see: :class:`bmesh.types.BMesh.from_mesh` and :mod:`bmesh.from_edit_mesh` respectively.
When explicitly converting from mesh data python **owns** the data, that is to say - that the mesh only exists while
python holds a reference to it, and the script is responsible for putting it back into a mesh data-block when the edits
are done.
Note that unlike :mod:`bpy`, a BMesh does not necessarily correspond to data in the currently open blend file,
a BMesh can be created, edited and freed without the user ever seeing or having access to it.
Unlike edit mode, the bmesh module can use multiple BMesh instances at once.
Take care when dealing with multiple BMesh instances since the mesh data can use a lot of memory, while a mesh that
python owns will be freed in when the script holds no references to it,
its good practice to call :class:`bmesh.types.BMesh.free` which will remove all the mesh data immediately and disable
further access.
CustomData Access
-----------------
BMesh has a unified way to access mesh attributes such as UV's vertex colors, shape keys, edge crease etc.
This works by having a **layers** property on bmesh data sequences to access the custom data layers which can then be
used to access the actual data on each vert/edge/face/loop.
Here are some examples ...
.. code-block:: python
uv_lay = bm.loops.layers.uv.active
for face in bm.faces:
for loop in f.loops:
uv = loop[uv_lay]
print("Loop UV: %f, %f" % (uv.x, uv.y))
.. code-block:: python
shape_lay = bm.verts.layers.shape["Key.001"]
for vert in bm.verts:
shape = vert[shape_lay]
print("Vert Shape: %f, %f, %f" % (shape.x, shape.y, shape.z))
Keeping a Correct State
-----------------------
When modeling in blender there are certain assumptions made about the state of the mesh.
* hidden geometry isn't selected.
* when an edge is selected, its vertices are selected too.
* when a face is selected, its edges and vertices are selected.
* duplicate edges / faces don't exist.
* faces have at least 3 vertices.
To give developers flexibility these conventions are not enforced,
however tools must leave the mesh in a valid state else other tools may behave incorrectly.
Any errors that arise from not following these conventions is considered a bug in the script,
not a bug in blender.
Selection / Flushing
^^^^^^^^^^^^^^^^^^^^
As mentioned above, it is possible to create an invalid selection state
(by selecting a state and then de-selecting one of its vertices's for example), mostly the best way to solve this is to
flush the selection after performing a series of edits. this validates the selection state.
Module Functions
----------------

@ -268,7 +268,7 @@ The **try** statement is useful to save time writing error checking code.
However **try** is significantly slower then an **if** since an exception has to be set each time, so avoid using **try** in areas of your code that execute in a loop and runs many times.
There are cases where using **try** is faster than checking weather the condition will raise an error, so it is worth experimenting.
There are cases where using **try** is faster than checking whether the condition will raise an error, so it is worth experimenting.
Value Comparison

@ -132,6 +132,91 @@ write useful tools in python which are also fast to execute while in edit-mode.
For the time being this limitation just has to be worked around but we're aware its frustrating needs to be addressed.
NGons and Tessellation Faces
============================
Since 2.63 NGons are supported, this adds some complexity since in some cases you need to access triangles still (some exporters for example).
There are now 3 ways to access faces:
* :class:`bpy.types.MeshPolygon` - this is the data stricture which now stores faces in object mode (access as ``mesh.polygons`` rather then ``mesh.faces``).
* :class:`bpy.types.MeshTessFace` - the result of triangulating (tessellated) polygons, the main method of face access in 2.62 or older (access as ``mesh.tessfaces``).
* :class:`bmesh.types.BMFace` - the polygons as used in editmode.
For the purpose of the following documentation, these will be referred to as polygons, tessfaces and bmesh-faces respectively.
5+ sided faces will be referred to as ``ngons``.
Support Overview
----------------
+--------------+------------------------------+--------------------------------+--------------------------------+
|Usage |:class:`bpy.types.MeshPolygon`|:class:`bpy.types.MeshTessFace` |:class:`bmesh.types.BMFace` |
+==============+==============================+================================+================================+
|Import/Create |Bad (inflexible) |Fine (supported as upgrade path)|Best |
+--------------+------------------------------+--------------------------------+--------------------------------+
|Manipulate |Bad (inflexible) |Bad (loses ngons) |Best |
+--------------+------------------------------+--------------------------------+--------------------------------+
|Export/Output |Good (ngons) |Good (When ngons can't be used) |Good (ngons, memory overhead) |
+--------------+------------------------------+--------------------------------+--------------------------------+
.. note::
Using the :mod:`bmesh` api is completely separate api from :mod:`bpy`, typically you would would use one or the other based on the level of editing needed, not simply for a different way to access faces.
Creating
--------
All 3 datatypes can be used for face creation.
* polygons are the most efficient way to create faces but the data structure is _very_ rigid and inflexible, you must have all your vertes and faces ready and create them all at once. This is further complicated by the fact that each polygon does not store its own verts (as with tessfaces), rather they reference an index and size in :class:`bpy.types.Mesh.loops` which are a fixed array too.
* tessfaces ideally should not be used for creating faces since they are really only tessellation cache of polygons, however for scripts upgrading from 2.62 this is by far the most straightforward option. This works by creating tessfaces and when finished - they can be converted into polygons by calling :class:`bpy.types.Mesh.update`. The obvious limitation is ngons can't be created this way.
* bmesh-faces are most likely the easiest way for new scripts to create faces, since faces can be added one by one and the api has features intended for mesh manipulation. While :class:`bmesh.types.BMesh` uses more memory it can be managed by only operating on one mesh at a time.
Editing
-------
Editing is where the 3 data types vary most.
* polygons are very limited for editing, changing materials and options like smooth works but for anything else they are too inflexible and are only intended for storage.
* tessfaces should not be used for editing geometry because doing so will cause existing ngons to be tessellated.
* bmesh-faces are by far the best way to manipulate geometry.
Exporting
---------
All 3 data types can be used for exporting, the choice mostly depends on whether the target format supports ngons or not.
* polygons are the most direct & efficient way to export providing they convert into the output format easily enough.
* tessfaces work well for exporting to formats which dont support ngons, in fact this is the only place where their use is encouraged.
* bmesh-faces can work for exporting too but may not be necessary if polygons can be used since using bmesh gives some overhead because its not the native storage format in object mode.
Upgrading Importers from 2.62
-----------------------------
Importers can be upgraded to work with only minor changes.
The main change to be made is used the tessellation versions of each attribute.
* mesh.faces --> :class:`bpy.types.Mesh.tessfaces`
* mesh.uv_textures --> :class:`bpy.types.Mesh.tessface_uv_textures`
* mesh.vertex_colors --> :class:`bpy.types.Mesh.tessface_vertex_colors`
Once the data is created call :class:`bpy.types.Mesh.update` to convert the tessfaces into polygons.
Upgrading Exporters from 2.62
-----------------------------
For exporters the most direct way to upgrade is to use tessfaces as with importing however its important to know that tessfaces may **not** exist for a mesh, the array will be empty as if there are no faces.
So before accessing tessface data call: :class:`bpy.types.Mesh.update` ``(calc_tessface=True)``.
EditBones, PoseBones, Bone... Bones
===================================

@ -26,16 +26,17 @@ API dump in RST files
---------------------
Run this script from blenders root path once you have compiled blender
./blender.bin -b -noaudio -P doc/python_api/sphinx_doc_gen.py
./blender.bin --background -noaudio --python doc/python_api/sphinx_doc_gen.py
This will generate python files in doc/python_api/sphinx-in/
providing ./blender.bin is or links to the blender executable
To choose sphinx-in directory:
./blender.bin -b -P doc/python_api/sphinx_doc_gen.py -- -o ../python_api
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --output ../python_api
For quick builds:
./blender.bin -b -P doc/python_api/sphinx_doc_gen.py -- -q
./blender.bin --background --python doc/python_api/sphinx_doc_gen.py -- --partial
Sphinx: HTML generation
-----------------------
@ -47,6 +48,7 @@ Sphinx: HTML generation
This requires sphinx 1.0.7 to be installed.
Sphinx: PDF generation
----------------------
After you have built doc/python_api/sphinx-in (see above),
@ -73,6 +75,7 @@ import os
import sys
import inspect
import shutil
import logging
from platform import platform
PLATFORM = platform().split('-')[0].lower() # 'linux', 'darwin', 'windows'
@ -93,6 +96,30 @@ def handle_args():
)
# optional arguments
parser.add_argument("-p", "--partial",
dest="partial",
type=str,
default="",
help="Use a wildcard to only build specific module(s)\n"
"Example: --partial bmesh*\n",
required=False)
parser.add_argument("-f", "--fullrebuild",
dest="full_rebuild",
default=False,
action='store_true',
help="Rewrite all rst files in sphinx-in/ "
"(default=False)",
required=False)
parser.add_argument("-b", "--bpy",
dest="bpy",
default=False,
action='store_true',
help="Write the rst file of the bpy module "
"(default=False)",
required=False)
parser.add_argument("-o", "--output",
dest="output_dir",
type=str,
@ -100,25 +127,11 @@ def handle_args():
help="Path of the API docs (default=<script dir>)",
required=False)
parser.add_argument("-B", "--sphinx-build",
dest="sphinx_build",
default=False,
action='store_true',
help="Run sphinx-build SPHINX_IN SPHINX_OUT (default=False)",
required=False)
parser.add_argument("-N", "--sphinx-named-output",
dest="sphinx_named_output",
default=False,
action='store_true',
help="Add the theme name to the html dir name (default=False)",
required=False)
parser.add_argument("-T", "--sphinx-theme",
dest="sphinx_theme",
type=str,
default='default',
help=
help =
# see SPHINX_THEMES below
"Sphinx theme (default='default')\n"
"Available themes\n"
@ -132,25 +145,53 @@ def handle_args():
# 'sphinxdoc', 'traditional'], # sphinx
required=False)
parser.add_argument("-f", "--fullrebuild",
dest="full_rebuild",
parser.add_argument("-N", "--sphinx-named-output",
dest="sphinx_named_output",
default=False,
action='store_true',
help="Rewrite all rst files in sphinx-in/ (default=False)",
help="Add the theme name to the html dir name.\n"
"Example: \"sphinx-out_haiku\" (default=False)",
required=False)
parser.add_argument("-t", "--testdump",
dest="test_dump",
parser.add_argument("-B", "--sphinx-build",
dest="sphinx_build",
default=False,
action='store_true',
help="Dumps a small part of the API (default=False)",
help="Build the html docs by running:\n"
"sphinx-build SPHINX_IN SPHINX_OUT\n"
"(default=False; does not depend on -P)",
required=False)
parser.add_argument("-b", "--bpy",
dest="bpy",
parser.add_argument("-P", "--sphinx-build-pdf",
dest="sphinx_build_pdf",
default=False,
action='store_true',
help="Write the rst file of the bpy module (default=False)",
help="Build the pdf by running:\n"
"sphinx-build -b latex SPHINX_IN SPHINX_OUT_PDF\n"
"(default=False; does not depend on -B)",
required=False)
parser.add_argument("-R", "--pack-reference",
dest="pack_reference",
default=False,
action='store_true',
help="Pack all necessary files in the deployed dir.\n"
"(default=False; use with -B and -P)",
required=False)
parser.add_argument("-l", "--log",
dest="log",
default=False,
action='store_true',
help=(
"Log the output of the api dump and sphinx|latex "
"warnings and errors (default=False).\n"
"If given, save logs in:\n"
"* OUTPUT_DIR/.bpy.log\n"
"* OUTPUT_DIR/.sphinx-build.log\n"
"* OUTPUT_DIR/.sphinx-build_pdf.log\n"
"* OUTPUT_DIR/.latex_make.log",
),
required=False)
# parse only the args passed after '--'
@ -165,15 +206,22 @@ ARGS = handle_args()
# ----------------------------------BPY-----------------------------------------
BPY_LOGGER = logging.getLogger('bpy')
BPY_LOGGER.setLevel(logging.DEBUG)
"""
# for quick rebuilds
rm -rf /b/doc/python_api/sphinx-* && \
./blender.bin --background -noaudio --factory-startup --python doc/python_api/sphinx_doc_gen.py && \
./blender.bin -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py && \
sphinx-build doc/python_api/sphinx-in doc/python_api/sphinx-out
or
./blender.bin -b -noaudio --factory-startup -P doc/python_api/sphinx_doc_gen.py -- -f -B
"""
# Switch for quick testing so doc-builds don't take so long
if not ARGS.test_dump:
if not ARGS.partial:
# full build
FILTER_BPY_OPS = None
FILTER_BPY_TYPES = None
@ -181,6 +229,7 @@ if not ARGS.test_dump:
EXCLUDE_MODULES = ()
else:
# can manually edit this too:
FILTER_BPY_OPS = ("import.scene", ) # allow
FILTER_BPY_TYPES = ("bpy_struct", "Operator", "ID") # allow
EXCLUDE_INFO_DOCS = True
@ -195,9 +244,9 @@ else:
"bge.types",
"bgl",
"blf",
#"bmesh",
#"bmesh.types",
#"bmesh.utils",
"bmesh",
"bmesh.types",
"bmesh.utils",
"bpy.app",
"bpy.app.handlers",
"bpy.context",
@ -215,10 +264,29 @@ else:
"Freestyle",
)
# ------
# Filter
#
# TODO, support bpy.ops and bpy.types filtering
import fnmatch
m = None
EXCLUDE_MODULES = tuple([m for m in EXCLUDE_MODULES if not fnmatch.fnmatchcase(m, ARGS.partial)])
EXCLUDE_INFO_DOCS = (not fnmatch.fnmatchcase("info", ARGS.partial))
del m
del fnmatch
BPY_LOGGER.debug("Partial Doc Build, Skipping: %s\n" % "\n ".join(sorted(EXCLUDE_MODULES)))
#
# done filtering
# --------------
try:
__import__("aud")
except ImportError:
print("Warning: Built without 'aud' module, docs incomplete...")
BPY_LOGGER.debug("Warning: Built without 'aud' module, docs incomplete...")
EXCLUDE_MODULES = EXCLUDE_MODULES + ("aud", )
# examples
@ -229,7 +297,7 @@ for f in os.listdir(EXAMPLES_DIR):
EXAMPLE_SET.add(os.path.splitext(f)[0])
EXAMPLE_SET_USED = set()
#rst files dir
# rst files dir
RST_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "rst"))
# extra info, not api reference docs
@ -248,10 +316,66 @@ RNA_BLACKLIST = {
"UserPreferencesSystem": {"language", }
}
MODULE_GROUPING = {
"bmesh.types": (
("Base Mesh Type", '-'),
"BMesh",
("Mesh Elements", '-'),
"BMVert",
"BMEdge",
"BMFace",
"BMLoop",
("Sequence Accessors", '-'),
"BMElemSeq",
"BMVertSeq",
"BMEdgeSeq",
"BMFaceSeq",
"BMLoopSeq",
"BMIter",
("Selection History", '-'),
"BMEditSelSeq",
"BMEditSelIter",
("Custom-Data Layer Access", '-'),
"BMLayerAccessVert",
"BMLayerAccessEdge",
"BMLayerAccessFace",
"BMLayerAccessLoop",
"BMLayerCollection",
"BMLayerItem",
("Custom-Data Layer Types", '-'),
"BMLoopUV"
)
}
# --------------------configure compile time options----------------------------
# -------------------------------BLENDER----------------------------------------
blender_version_strings = [str(v) for v in bpy.app.version]
# converting bytes to strings, due to #30154
BLENDER_REVISION = str(bpy.app.build_revision, 'utf_8')
BLENDER_DATE = str(bpy.app.build_date, 'utf_8')
BLENDER_VERSION_DOTS = ".".join(blender_version_strings) # '2.62.1'
if BLENDER_REVISION != "Unknown":
BLENDER_VERSION_DOTS += " r" + BLENDER_REVISION # '2.62.1 r44584'
BLENDER_VERSION_PATH = "_".join(blender_version_strings) # '2_62_1'
if bpy.app.version_cycle == "release":
BLENDER_VERSION_PATH = "%s%s_release" % ("_".join(blender_version_strings[:2]),
bpy.app.version_char) # '2_62_release'
# --------------------------DOWNLOADABLE FILES----------------------------------
REFERENCE_NAME = "blender_python_reference_%s" % BLENDER_VERSION_PATH
REFERENCE_PATH = os.path.join(ARGS.output_dir, REFERENCE_NAME)
BLENDER_PDF_FILENAME = "%s.pdf" % REFERENCE_NAME
BLENDER_ZIP_FILENAME = "%s.zip" % REFERENCE_NAME
# -------------------------------SPHINX-----------------------------------------
SPHINX_THEMES = {'bf': ['blender-org'], # , 'naiad',
SPHINX_THEMES = {'bf': ['blender-org'], # , 'naiad',
'sphinx': ['agogo',
'basic',
'default',
@ -267,37 +391,43 @@ if ARGS.sphinx_theme not in available_themes:
print ("Please choose a theme among: %s" % ', '.join(available_themes))
sys.exit()
if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
SPHINX_THEME_DIR = os.path.join(ARGS.output_dir, ARGS.sphinx_theme)
SPHINX_THEME_SVN_DIR = os.path.join(SCRIPT_DIR, ARGS.sphinx_theme)
SPHINX_IN = os.path.join(ARGS.output_dir, "sphinx-in")
SPHINX_IN_TMP = SPHINX_IN + "-tmp"
SPHINX_OUT = os.path.join(ARGS.output_dir, "sphinx-out")
if ARGS.sphinx_named_output:
SPHINX_OUT += "_%s" % ARGS.sphinx_theme
if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
SPHINX_THEME_DIR = os.path.join(ARGS.output_dir, ARGS.sphinx_theme)
SPHINX_THEME_SVN_DIR = os.path.join(SCRIPT_DIR, ARGS.sphinx_theme)
# html build
if ARGS.sphinx_build:
SPHINX_BUILD = ["sphinx-build", SPHINX_IN, SPHINX_OUT]
# ------------------------------------------------------------------------------
if ARGS.log:
SPHINX_BUILD_LOG = os.path.join(ARGS.output_dir, ".sphinx-build.log")
SPHINX_BUILD = ["sphinx-build",
"-w", SPHINX_BUILD_LOG,
SPHINX_IN, SPHINX_OUT]
# configure compile time options
# pdf build
if ARGS.sphinx_build_pdf:
SPHINX_OUT_PDF = os.path.join(ARGS.output_dir, "sphinx-out_pdf")
SPHINX_BUILD_PDF = ["sphinx-build",
"-b", "latex",
SPHINX_IN, SPHINX_OUT_PDF]
SPHINX_MAKE_PDF = ["make", "-C", SPHINX_OUT_PDF]
SPHINX_MAKE_PDF_STDOUT = None
# -------------------------------BLENDER----------------------------------------
'''
blender version
'''
version_strings = [str(v) for v in bpy.app.version]
BLENDER_VERSION_DOTS = ".".join(version_strings) # '2.62.1'
if bpy.app.build_revision != b"Unknown":
# converting bytes to strings, due to #30154
BLENDER_VERSION_DOTS += " r" + str(bpy.app.build_revision, 'utf_8') # '2.62.1 r44584'
BLENDER_VERSION_PDF = "_".join(version_strings) # '2_62_1'
if bpy.app.version_cycle == "release":
BLENDER_VERSION_PDF = "%s%s_release" % ("_".join(version_strings[:2]),
bpy.app.version_char) # '2_62_release'
if ARGS.log:
SPHINX_BUILD_PDF_LOG = os.path.join(ARGS.output_dir, ".sphinx-build_pdf.log")
SPHINX_BUILD_PDF = ["sphinx-build", "-b", "latex",
"-w", SPHINX_BUILD_PDF_LOG,
SPHINX_IN, SPHINX_OUT_PDF]
sphinx_make_pdf_log = os.path.join(ARGS.output_dir, ".latex_make.log")
SPHINX_MAKE_PDF_STDOUT = open(sphinx_make_pdf_log, "w", encoding="utf-8")
# --------------------------------API DUMP--------------------------------------
@ -326,13 +456,13 @@ def undocumented_message(module_name, type_name, identifier):
preloadtitle = '%s.%s' % (module_name, identifier)
else:
preloadtitle = '%s.%s.%s' % (module_name, type_name, identifier)
message = "Undocumented (`contribute "\
"<http://wiki.blender.org/index.php/"\
"Dev:2.5/Py/API/Generating_API_Reference/Contribute/Howto-message"\
"?action=edit"\
"&section=new"\
"&preload=Dev:2.5/Py/API/Documentation/Contribute/Howto-message"\
"&preloadtitle=%s>`_)\n\n" % preloadtitle
message = ("Undocumented (`contribute "
"<http://wiki.blender.org/index.php/"
"Dev:2.5/Py/API/Generating_API_Reference/Contribute"
"?action=edit"
"&section=new"
"&preload=Dev:2.5/Py/API/Generating_API_Reference/Contribute/Howto-message"
"&preloadtitle=%s>`_)\n\n" % preloadtitle)
return message
@ -374,15 +504,20 @@ def example_extract_docstring(filepath):
return "\n".join(text), line_no
def write_title(fw, text, heading_char):
fw("%s\n%s\n\n" % (text, len(text) * heading_char))
def title_string(text, heading_char, double=False):
filler = len(text) * heading_char
if double:
return "%s\n%s\n%s\n\n" % (filler, text, filler)
else:
return "%s\n%s\n\n" % (text, filler)
def write_example_ref(ident, fw, example_id, ext="py"):
if example_id in EXAMPLE_SET:
# extract the comment
filepath = os.path.join(EXAMPLES_DIR, "%s.%s" % (example_id, ext))
filepath = os.path.join("..", "examples", "%s.%s" % (example_id, ext))
filepath_full = os.path.join(os.path.dirname(fw.__self__.name), filepath)
text, line_no = example_extract_docstring(filepath_full)
@ -398,7 +533,7 @@ def write_example_ref(ident, fw, example_id, ext="py"):
EXAMPLE_SET_USED.add(example_id)
else:
if bpy.app.debug:
print("\tskipping example:", example_id)
BPY_LOGGER.debug("\tskipping example: " + example_id)
# Support for numbered files bpy.types.Operator -> bpy.types.Operator.1.py
i = 1
@ -557,11 +692,34 @@ def pymodule2sphinx(basepath, module_name, module, title):
if module_all:
module_dir = module_all
# TODO - currently only used for classes
# grouping support
module_grouping = MODULE_GROUPING.get(module_name)
def module_grouping_index(name):
if module_grouping is not None:
try:
return module_grouping.index(name)
except ValueError:
pass
return -1
def module_grouping_heading(name):
if module_grouping is not None:
i = module_grouping_index(name) - 1
if i >= 0 and type(module_grouping[i]) == tuple:
return module_grouping[i]
return None, None
def module_grouping_sort_key(name):
return module_grouping_index(name)
# done grouping support
file = open(filepath, "w", encoding="utf-8")
fw = file.write
write_title(fw, "%s (%s)" % (title, module_name), "=")
fw(title_string("%s (%s)" % (title, module_name), "="))
fw(".. module:: %s\n\n" % module_name)
@ -685,7 +843,7 @@ def pymodule2sphinx(basepath, module_name, module, title):
write_indented_lines(" ", fw, "constant value %s" % repr(value), False)
fw("\n")
else:
print("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
BPY_LOGGER.debug("\tnot documenting %s.%s of %r type" % (module_name, attribute, value_type.__name__))
continue
attribute_set.add(attribute)
@ -693,7 +851,7 @@ def pymodule2sphinx(basepath, module_name, module, title):
del module_dir_value_type
# TODO, bpy_extras does this already, mathutils not.
"""
'''
if submodules:
fw("\n"
"**********\n"
@ -704,10 +862,19 @@ def pymodule2sphinx(basepath, module_name, module, title):
for attribute, submod in submodules:
fw("* :mod:`%s.%s`\n" % (module_name, attribute))
fw("\n")
"""
'''
if module_grouping is not None:
classes.sort(key=lambda pair: module_grouping_sort_key(pair[0]))
# write collected classes now
for (type_name, value) in classes:
if module_grouping is not None:
heading, heading_char = module_grouping_heading(type_name)
if heading:
fw(title_string(heading, heading_char))
# May need to be its own function
fw(".. class:: %s\n\n" % type_name)
if value.__doc__:
@ -746,8 +913,7 @@ def pycontext2sphinx(basepath):
filepath = os.path.join(basepath, "bpy.context.rst")
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("Context Access (bpy.context)\n")
fw("============================\n\n")
fw(title_string("Context Access (bpy.context)", "="))
fw(".. module:: bpy.context\n")
fw("\n")
fw("The context members available depend on the area of blender which is currently being accessed.\n")
@ -950,7 +1116,7 @@ def pyrna2sphinx(basepath):
else:
title = struct_id
write_title(fw, title, "=")
fw(title_string(title, "="))
fw(".. module:: bpy.types\n\n")
@ -1161,7 +1327,7 @@ def pyrna2sphinx(basepath):
file = open(filepath, "w", encoding="utf-8")
fw = file.write
write_title(fw, class_name, "=")
fw(title_string(class_name, "="))
fw(".. module:: bpy.types\n")
fw("\n")
@ -1214,7 +1380,7 @@ def pyrna2sphinx(basepath):
title = "%s Operators" % op_module_name.replace("_", " ").title()
write_title(fw, title, "=")
fw(title_string(title, "="))
fw(".. module:: bpy.ops.%s\n\n" % op_module_name)
@ -1297,38 +1463,30 @@ def write_rst_contents(basepath):
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
fw(" Blender Documentation contents\n")
fw("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%\n")
fw(title_string("Blender Documentation Contents", "%", double=True))
fw("\n")
fw("Welcome, this document is an API reference for Blender %s. built %s.\n" % (BLENDER_VERSION_DOTS, str(bpy.app.build_date, 'utf_8')))
fw("Welcome, this document is an API reference for Blender %s, built %s.\n" % (BLENDER_VERSION_DOTS, BLENDER_DATE))
fw("\n")
# fw("`A PDF version of this document is also available <blender_python_reference_%s.pdf>`_\n" % BLENDER_VERSION_PDF)
fw("`A compressed ZIP file of this site is available <blender_python_reference_%s.zip>`_\n" % BLENDER_VERSION_PDF)
# fw("`A PDF version of this document is also available <%s>`_\n" % BLENDER_PDF_FILENAME)
fw("`A compressed ZIP file of this site is available <%s>`_\n" % BLENDER_ZIP_FILENAME)
fw("\n")
if not EXCLUDE_INFO_DOCS:
fw("============================\n")
fw("Blender/Python Documentation\n")
fw("============================\n")
fw("\n")
fw("\n")
fw(title_string("Blender/Python Documentation", "=", double=True))
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
for info, info_desc in INFO_DOCS:
fw(" %s <%s>\n\n" % (info_desc, info))
fw("\n")
fw("===================\n")
fw("Application Modules\n")
fw("===================\n")
fw("\n")
fw(title_string("Application Modules", "=", double=True))
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
app_modules = [
app_modules = (
"bpy.context", # note: not actually a module
"bpy.data", # note: not actually a module
"bpy.ops",
@ -1341,37 +1499,33 @@ def write_rst_contents(basepath):
"bpy.app.handlers",
# C modules
"bpy.props"
]
"bpy.props",
)
for mod in app_modules:
if mod not in EXCLUDE_MODULES:
fw(" %s\n\n" % mod)
fw("==================\n")
fw("Standalone Modules\n")
fw("==================\n")
fw("\n")
fw(title_string("Standalone Modules", "=", double=True))
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
standalone_modules = [
standalone_modules = (
# mathutils
"mathutils", "mathutils.geometry", "mathutils.noise",
# misc
"Freestyle", "bgl", "blf", "gpu", "aud", "bpy_extras",
# bmesh
"bmesh", "bmesh.types", "bmesh.utils"
]
"bmesh", "bmesh.types", "bmesh.utils",
)
for mod in standalone_modules:
if mod not in EXCLUDE_MODULES:
fw(" %s\n\n" % mod)
# game engine
if "bge" not in EXCLUDE_MODULES:
fw("===================\n")
fw("Game Engine Modules\n")
fw("===================\n")
fw("\n")
fw(title_string("Game Engine Modules", "=", double=True))
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
fw(" bge.types.rst\n\n")
@ -1382,10 +1536,7 @@ def write_rst_contents(basepath):
fw(" bge.constraints.rst\n\n")
# rna generated change log
fw("========\n")
fw("API Info\n")
fw("========\n")
fw("\n")
fw(title_string("API Info", "=", double=True))
fw(".. toctree::\n")
fw(" :maxdepth: 1\n\n")
fw(" change_log.rst\n\n")
@ -1421,7 +1572,7 @@ def write_rst_bpy(basepath):
title = ":mod:`bpy` --- Blender Python Module"
write_title(fw, title, "=")
fw(title_string(title, "="))
fw(".. module:: bpy.types\n\n")
file.close()
@ -1435,8 +1586,7 @@ def write_rst_types_index(basepath):
filepath = os.path.join(basepath, "bpy.types.rst")
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("Types (bpy.types)\n")
fw("=================\n\n")
fw(title_string("Types (bpy.types)", "="))
fw(".. toctree::\n")
fw(" :glob:\n\n")
fw(" bpy.types.*\n\n")
@ -1451,8 +1601,7 @@ def write_rst_ops_index(basepath):
filepath = os.path.join(basepath, "bpy.ops.rst")
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("Operators (bpy.ops)\n")
fw("===================\n\n")
fw(title_string("Operators (bpy.ops)", "="))
write_example_ref("", fw, "bpy.ops")
fw(".. toctree::\n")
fw(" :glob:\n\n")
@ -1470,8 +1619,7 @@ def write_rst_data(basepath):
filepath = os.path.join(basepath, "bpy.data.rst")
file = open(filepath, "w", encoding="utf-8")
fw = file.write
fw("Data Access (bpy.data)\n")
fw("======================\n\n")
fw(title_string("Data Access (bpy.data)", "="))
fw(".. module:: bpy\n")
fw("\n")
fw("This module is used for all blender/python access.\n")
@ -1536,6 +1684,9 @@ def copy_handwritten_rsts(basepath):
"bge.constraints",
"bgl", # "Blender OpenGl wrapper"
"gpu", # "GPU Shader Module"
# includes...
"include__bmesh",
]
for mod_name in handwritten_modules:
if mod_name not in EXCLUDE_MODULES:
@ -1590,7 +1741,7 @@ def align_sphinx_in_to_sphinx_in_tmp():
# remove deprecated files that have been removed
for f in sorted(sphinx_in_files):
if f not in sphinx_in_tmp_files:
print("\tdeprecated: %s" % f)
BPY_LOGGER.debug("\tdeprecated: %s" % f)
os.remove(os.path.join(SPHINX_IN, f))
# freshen with new files.
@ -1604,53 +1755,142 @@ def align_sphinx_in_to_sphinx_in_tmp():
do_copy = False
if do_copy:
print("\tupdating: %s" % f)
BPY_LOGGER.debug("\tupdating: %s" % f)
shutil.copy(f_from, f_to)
def refactor_sphinx_log(sphinx_logfile):
refactored_log = []
with open(sphinx_logfile, "r", encoding="utf-8") as original_logfile:
lines = set(original_logfile.readlines())
for line in lines:
if 'warning' in line.lower() or 'error' in line.lower():
line = line.strip().split(None, 2)
if len(line) == 3:
location, kind, msg = line
location = os.path.relpath(location, start=SPHINX_IN)
refactored_log.append((kind, location, msg))
with open(sphinx_logfile, "w", encoding="utf-8") as refactored_logfile:
for log in sorted(refactored_log):
refactored_logfile.write("%-12s %s\n %s\n" % log)
def main():
# dirs preparation
# eventually, create the dirs
for dir_path in [ARGS.output_dir, SPHINX_IN]:
if not os.path.exists(dir_path):
os.mkdir(dir_path)
# eventually, log in files
if ARGS.log:
bpy_logfile = os.path.join(ARGS.output_dir, ".bpy.log")
bpy_logfilehandler = logging.FileHandler(bpy_logfile, mode="w")
bpy_logfilehandler.setLevel(logging.DEBUG)
BPY_LOGGER.addHandler(bpy_logfilehandler)
# using a FileHandler seems to disable the stdout, so we add a StreamHandler
bpy_log_stdout_handler = logging.StreamHandler(stream=sys.stdout)
bpy_log_stdout_handler.setLevel(logging.DEBUG)
BPY_LOGGER.addHandler(bpy_log_stdout_handler)
# in case of out-of-source build, copy the needed dirs
if ARGS.output_dir != SCRIPT_DIR:
# examples dir
examples_dir_copy = os.path.join(ARGS.output_dir, "examples")
if os.path.exists(examples_dir_copy):
shutil.rmtree(examples_dir_copy, True)
shutil.copytree(EXAMPLES_DIR,
examples_dir_copy,
ignore=shutil.ignore_patterns(*(".svn",)),
copy_function=shutil.copy)
# eventually, copy the theme dir
if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
if os.path.exists(SPHINX_THEME_DIR):
shutil.rmtree(SPHINX_THEME_DIR, True)
shutil.copytree(SPHINX_THEME_SVN_DIR,
SPHINX_THEME_DIR,
ignore=shutil.ignore_patterns(*(".svn",)),
copy_function=shutil.copy)
# dump the api in rst files
if os.path.exists(SPHINX_IN_TMP):
shutil.rmtree(SPHINX_IN_TMP, True)
rna2sphinx(SPHINX_IN_TMP)
if ARGS.full_rebuild:
# only for full updates
shutil.rmtree(SPHINX_IN, True)
shutil.rmtree(SPHINX_OUT, True)
rna2sphinx(SPHINX_IN_TMP)
shutil.copytree(SPHINX_IN_TMP,
SPHINX_IN,
copy_function=shutil.copy)
if ARGS.sphinx_build and os.path.exists(SPHINX_OUT):
shutil.rmtree(SPHINX_OUT, True)
if ARGS.sphinx_build_pdf and os.path.exists(SPHINX_OUT_PDF):
shutil.rmtree(SPHINX_OUT_PDF, True)
else:
# write here, then move
shutil.rmtree(SPHINX_IN_TMP, True)
rna2sphinx(SPHINX_IN_TMP)
# move changed files in SPHINX_IN
align_sphinx_in_to_sphinx_in_tmp()
# report which example files weren't used
EXAMPLE_SET_UNUSED = EXAMPLE_SET - EXAMPLE_SET_USED
if EXAMPLE_SET_UNUSED:
print("\nUnused examples found in '%s'..." % EXAMPLES_DIR)
for f in EXAMPLE_SET_UNUSED:
print(" %s.py" % f)
print(" %d total\n" % len(EXAMPLE_SET_UNUSED))
BPY_LOGGER.debug("\nUnused examples found in '%s'..." % EXAMPLES_DIR)
for f in sorted(EXAMPLE_SET_UNUSED):
BPY_LOGGER.debug(" %s.py" % f)
BPY_LOGGER.debug(" %d total\n" % len(EXAMPLE_SET_UNUSED))
# eventually, copy the theme in the output directory
if ARGS.sphinx_theme in SPHINX_THEMES['bf']:
if not os.path.exists(SPHINX_THEME_DIR):
shutil.copytree(SPHINX_THEME_SVN_DIR,
SPHINX_THEME_DIR,
copy_function=shutil.copy)
# eventually, build the docs
# eventually, build the html docs
if ARGS.sphinx_build:
import subprocess
sphinx_build_command = "sphinx-build %s %s" % (SPHINX_IN, SPHINX_OUT)
print ('\n%s\n' % sphinx_build_command)
subprocess.call(sphinx_build_command, shell=True)
subprocess.call(SPHINX_BUILD)
# sphinx-build log cleanup+sort
if ARGS.log:
if os.stat(SPHINX_BUILD_LOG).st_size:
refactor_sphinx_log(SPHINX_BUILD_LOG)
# eventually, build the pdf docs
if ARGS.sphinx_build_pdf:
import subprocess
subprocess.call(SPHINX_BUILD_PDF)
subprocess.call(SPHINX_MAKE_PDF, stdout=SPHINX_MAKE_PDF_STDOUT)
# sphinx-build log cleanup+sort
if ARGS.log:
if os.stat(SPHINX_BUILD_PDF_LOG).st_size:
refactor_sphinx_log(SPHINX_BUILD_PDF_LOG)
# eventually, prepare the dir to be deployed online (REFERENCE_PATH)
if ARGS.pack_reference:
if ARGS.sphinx_build:
# delete REFERENCE_PATH
if os.path.exists(REFERENCE_PATH):
shutil.rmtree(REFERENCE_PATH, True)
# copy SPHINX_OUT to the REFERENCE_PATH
ignores = ('.doctrees', 'objects.inv', '.buildinfo')
shutil.copytree(SPHINX_OUT,
REFERENCE_PATH,
ignore=shutil.ignore_patterns(*ignores))
shutil.copy(os.path.join(REFERENCE_PATH, "contents.html"),
os.path.join(REFERENCE_PATH, "index.html"))
# zip REFERENCE_PATH
basename = os.path.join(ARGS.output_dir, REFERENCE_NAME)
tmp_path = shutil.make_archive(basename, 'zip',
root_dir=ARGS.output_dir,
base_dir=REFERENCE_NAME)
final_path = os.path.join(REFERENCE_PATH, BLENDER_ZIP_FILENAME)
os.rename(tmp_path, final_path)
if ARGS.sphinx_build_pdf:
# copy the pdf to REFERENCE_PATH
shutil.copy(os.path.join(SPHINX_OUT_PDF, "contents.pdf"),
os.path.join(REFERENCE_PATH, BLENDER_PDF_FILENAME))
sys.exit()

@ -35,115 +35,115 @@ set(INC_SYS
)
set(SRC
lib/carve.cpp
lib/mesh.cpp
lib/intersect_group.cpp
lib/intersect_classify_edge.cpp
lib/intersect_classify_group.cpp
lib/polyhedron.cpp
lib/geom3d.cpp
lib/polyline.cpp
lib/csg_collector.cpp
lib/triangulator.cpp
lib/intersect_face_division.cpp
lib/intersect_half_classify_group.cpp
lib/edge.cpp
lib/math.cpp
lib/geom2d.cpp
lib/tag.cpp
lib/intersection.cpp
lib/convex_hull.cpp
lib/csg.cpp
lib/intersect.cpp
lib/face.cpp
lib/triangulator.cpp
lib/convex_hull.cpp
lib/polyhedron.cpp
lib/polyline.cpp
lib/pointset.cpp
lib/timing.cpp
lib/octree.cpp
lib/geom2d.cpp
lib/math.cpp
lib/intersect_half_classify_group.cpp
lib/intersect_face_division.cpp
lib/tag.cpp
lib/aabb.cpp
lib/intersect_classify_group.cpp
lib/mesh.cpp
lib/timing.cpp
lib/geom3d.cpp
lib/intersect_group.cpp
lib/carve.cpp
lib/intersect_classify_edge.cpp
lib/csg.cpp
lib/face.cpp
lib/csg_collector.cpp
lib/intersect_debug.cpp
lib/edge.cpp
lib/octree.cpp
lib/intersect_classify_common.hpp
lib/csg_data.hpp
lib/csg_collector.hpp
lib/intersect_common.hpp
lib/intersect_classify_common_impl.hpp
lib/csg_detail.hpp
lib/intersect_debug.hpp
lib/csg_collector.hpp
lib/csg_data.hpp
lib/intersect_classify_common.hpp
lib/intersect_common.hpp
lib/csg_detail.hpp
lib/intersect_classify_common_impl.hpp
include/carve/polyhedron_decl.hpp
include/carve/geom2d.hpp
include/carve/exact.hpp
include/carve/triangulator_impl.hpp
include/carve/collection.hpp
include/carve/pointset.hpp
include/carve/djset.hpp
include/carve/kd_node.hpp
include/carve/polyline.hpp
include/carve/polyline_iter.hpp
include/carve/geom3d.hpp
include/carve/edge_decl.hpp
include/carve/face_decl.hpp
include/carve/vertex_impl.hpp
include/carve/aabb_impl.hpp
include/carve/colour.hpp
include/carve/pointset_iter.hpp
include/carve/polyline_decl.hpp
include/carve/rescale.hpp
include/carve/mesh_impl.hpp
include/carve/classification.hpp
include/carve/util.hpp
include/carve/triangulator.hpp
include/carve/polyhedron_base.hpp
include/carve/rtree.hpp
include/carve/math.hpp
include/carve/math_constants.hpp
include/carve/octree_decl.hpp
include/carve/input.hpp
include/carve/mesh_ops.hpp
include/carve/debug_hooks.hpp
include/carve/mesh_simplify.hpp
include/carve/interpolator.hpp
include/carve/poly_decl.hpp
include/carve/csg.hpp
include/carve/pointset_iter.hpp
include/carve/debug_hooks.hpp
include/carve/mesh.hpp
include/carve/carve.hpp
include/carve/gnu_cxx.h
include/carve/polyhedron_impl.hpp
include/carve/poly_impl.hpp
include/carve/aabb.hpp
include/carve/convex_hull.hpp
include/carve/vertex_decl.hpp
include/carve/win32.h
include/carve/edge_impl.hpp
include/carve/tag.hpp
include/carve/tree.hpp
include/carve/heap.hpp
include/carve/matrix.hpp
include/carve/poly.hpp
include/carve/vector.hpp
include/carve/intersection.hpp
include/carve/faceloop.hpp
include/carve/geom_impl.hpp
include/carve/octree_impl.hpp
include/carve/spacetree.hpp
include/carve/collection/unordered/std_impl.hpp
include/carve/triangulator_impl.hpp
include/carve/edge_decl.hpp
include/carve/collection/unordered.hpp
include/carve/collection/unordered/tr1_impl.hpp
include/carve/collection/unordered/fallback_impl.hpp
include/carve/collection/unordered/std_impl.hpp
include/carve/collection/unordered/vcpp_impl.hpp
include/carve/collection/unordered/libstdcpp_impl.hpp
include/carve/collection/unordered/boost_impl.hpp
include/carve/collection/unordered/vcpp_impl.hpp
include/carve/collection/unordered/fallback_impl.hpp
include/carve/collection/unordered.hpp
include/carve/face_impl.hpp
include/carve/pointset_impl.hpp
include/carve/cbrt.h
include/carve/vcpp_config.h
include/carve/convex_hull.hpp
include/carve/geom.hpp
include/carve/vertex_impl.hpp
include/carve/polyline_impl.hpp
include/carve/pointset_decl.hpp
include/carve/timing.hpp
include/carve/csg_triangulator.hpp
include/carve/iobj.hpp
include/carve/collection_types.hpp
include/carve/cbrt.h
include/carve/util.hpp
include/carve/iobj.hpp
include/carve/polyline_decl.hpp
include/carve/polyline_impl.hpp
include/carve/win32.h
include/carve/edge_impl.hpp
include/carve/carve.hpp
include/carve/polyline.hpp
include/carve/face_decl.hpp
include/carve/matrix.hpp
include/carve/classification.hpp
include/carve/geom_impl.hpp
include/carve/faceloop.hpp
include/carve/mesh_ops.hpp
include/carve/tree.hpp
include/carve/geom2d.hpp
include/carve/face_impl.hpp
include/carve/polyhedron_decl.hpp
include/carve/interpolator.hpp
include/carve/poly_decl.hpp
include/carve/mesh_impl.hpp
include/carve/gnu_cxx.h
include/carve/mesh_simplify.hpp
include/carve/triangulator.hpp
include/carve/pointset_impl.hpp
include/carve/rtree.hpp
include/carve/math_constants.hpp
include/carve/vector.hpp
include/carve/octree_impl.hpp
include/carve/pointset.hpp
include/carve/math.hpp
include/carve/intersection.hpp
include/carve/colour.hpp
include/carve/kd_node.hpp
include/carve/input.hpp
include/carve/geom3d.hpp
include/carve/exact.hpp
include/carve/rescale.hpp
include/carve/polyhedron_base.hpp
include/carve/heap.hpp
include/carve/spacetree.hpp
include/carve/polyhedron_impl.hpp
include/carve/vcpp_config.h
include/carve/aabb.hpp
include/carve/polyline_iter.hpp
include/carve/djset.hpp
include/carve/vertex_decl.hpp
include/carve/csg_triangulator.hpp
include/carve/poly.hpp
include/carve/timing.hpp
include/carve/octree_decl.hpp
include/carve/pointset_decl.hpp
include/carve/tag.hpp
include/carve/collection.hpp
include/carve/poly_impl.hpp
)
if(WITH_BOOST)

@ -47,7 +47,7 @@ cat > CMakeLists.txt << EOF
#
# 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.
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2006, Blender Foundation
# All rights reserved.

@ -639,9 +639,11 @@ namespace carve {
}
// XXX: not implemented yet
//exact_t operator+(const exact_t &a, const exact_t &b) {
//}
exact_t operator+(const exact_t &a, const exact_t &b) {
exact_t r;
sum_zeroelim(a, b, r);
return r;
}

@ -230,7 +230,7 @@ namespace carve {
}
// distance_t must provide:
// double operator()(kd_node::data_t, vector<ndim>);
// double operator()(data_t, vector<ndim>);
// double operator()(axis_pos, vector<ndim>);
template<typename distance_t>
struct near_point_query {
@ -238,7 +238,7 @@ namespace carve {
// q_t - the priority queue value type.
// q_t.first: distance from object to query point.
// q_t.second: pointer to object
typedef std::pair<double, const typename kd_node::data_t *> q_t;
typedef std::pair<double, const data_t *> q_t;
// the queue priority should sort from smallest distance to largest, and on equal distance, by object pointer.
struct pcmp {
@ -266,7 +266,7 @@ namespace carve {
}
}
const typename kd_node::data_t *next() {
const data_t *next() {
while (1) {
if (pq.size()) {
q_t t = pq.top();

@ -624,8 +624,7 @@ namespace carve {
CARVE_ASSERT(e->rev != NULL);
e = e->rev->next;
CARVE_ASSERT(e->v1() == emin->v1());
CARVE_ASSERT(e->v1()->v < e->v2()->v);
CARVE_ASSERT(e->v1()->v.x <= e->v2()->v.x);
CARVE_ASSERT(e->v1()->v <= e->v2()->v);
} while (e != emin);
double max_abs_x = 0.0;

@ -88,9 +88,9 @@ namespace carve {
*(*result)++ = f;
int r = 1;
for (size_t i = 0; i < f->edges.size(); ++i) {
const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(f->edges[i])];
const face_t *f2 = connectedFace(f, f->edges[i]);
for (size_t i = 0; i < f->nEdges(); ++i) {
const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(f->edge(i))];
const face_t *f2 = connectedFace(f, f->edge(i));
if (f2) {
r += _faceNeighbourhood(f2, depth - 1, (*result));
}
@ -116,7 +116,7 @@ namespace carve {
int r = 0;
const std::vector<const face_t *> &edge_faces = connectivity.edge_to_face[edgeToIndex_fast(e)];
for (size_t i = 0; i < edge_faces.size(); ++i) {
face_t *f = edge_faces[i];
const face_t *f = edge_faces[i];
if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
}
return r;
@ -131,7 +131,7 @@ namespace carve {
int r = 0;
const std::vector<const face_t *> &vertex_faces = connectivity.vertex_to_face[vertexToIndex_fast(v)];
for (size_t i = 0; i < vertex_faces.size(); ++i) {
face_t *f = vertex_faces[i];
const face_t *f = vertex_faces[i];
if (f && f->manifold_id == m_id) { r += _faceNeighbourhood(f, depth, &result); }
}
return r;
@ -142,7 +142,7 @@ namespace carve {
// accessing connectivity information.
template<typename T>
int Geometry<3>::vertexToEdges(const vertex_t *v, T result) const {
std::vector<const edge_t *> &e = connectivity.vertex_to_edge[vertexToIndex_fast(v)];
const std::vector<const edge_t *> &e = connectivity.vertex_to_edge[vertexToIndex_fast(v)];
std::copy(e.begin(), e.end(), result);
return e.size();
}

@ -9,30 +9,6 @@ diff -r 47dfdaff1dd5 include/carve/csg_triangulator.hpp
}
carve::mesh::MeshSet<3>::face_t *mergeQuad(edge_map_t::iterator i, edge_map_t &edge_map) {
diff -r 47dfdaff1dd5 include/carve/exact.hpp
--- a/include/carve/exact.hpp Thu Jan 12 15:49:04 2012 -0500
+++ b/include/carve/exact.hpp Fri Jan 13 03:13:32 2012 +0600
@@ -379,7 +379,7 @@
prod_2_1(b, a, r);
}
- static inline double prod_4_1(const double *a, const double *b, double *r) {
+ static inline void prod_4_1(const double *a, const double *b, double *r) {
double b_sp[2]; split(b[0], b_sp);
double t1[2]; prod_1_1s(a+0, b, b_sp, t1);
r[0] = t1[0];
@@ -639,8 +639,9 @@
}
- exact_t operator+(const exact_t &a, const exact_t &b) {
- }
+ // XXX: not implemented yet
+ //exact_t operator+(const exact_t &a, const exact_t &b) {
+ //}
diff -r 47dfdaff1dd5 src/selfintersect.cpp
--- a/src/selfintersect.cpp Thu Jan 12 15:49:04 2012 -0500
+++ b/src/selfintersect.cpp Fri Jan 13 03:13:32 2012 +0600

@ -39,6 +39,19 @@ set(INC_SYS
${ZLIB_INCLUDE_DIRS}
)
# XXX - FIXME
# this is a momentary hack to find unwind.h in 10.6.sdk
if(APPLE)
if(${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6")
list(APPEND INC_SYS
${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include
)
endif()
endif()
# XXX - END
set(SRC
libmv-capi.cpp
libmv/image/array_nd.cc
@ -129,9 +142,11 @@ set(SRC
third_party/fast/fast.h
third_party/gflags/config.h
third_party/gflags/gflags_completions.h
third_party/gflags/gflags.h
third_party/gflags/gflags/gflags_completions.h
third_party/gflags/gflags/gflags_declare.h
third_party/gflags/gflags/gflags.h
third_party/gflags/mutex.h
third_party/gflags/util.h
third_party/ldl/Include/ldl.h
third_party/msinttypes/inttypes.h
third_party/msinttypes/stdint.h

@ -1,3 +1,69 @@
commit 9fe49c32e990f28c83f2bbb1d18057aed8879af7
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Mon Mar 12 09:36:15 2012 +0600
Code cleanup: convert line endings to Unix style (native on my platform) so it
wouldn't confuse other versioning systems used for project where libmv is bundled to,
Also change mode to +x for glog's windows-related script.
commit fe74ae2b53769389b0ed9d7e604c8e60be81077d
Author: Sergey I. Sharybin <g.ulairi@gmail.com>
Date: Sun Mar 11 20:34:15 2012 +0600
Replace "third_party/glog/src/glog/logging.h" with <glog/logging.h>
It was needed because of how build systems is setup in Blender but think
this will be helpful change for other applications too because it makes
it's easier to move libraries around and even use libraries installed
on the operation system.
commit 37fc726701479f2d321d6af878fa93f3176278d5
Author: Sergey I. Sharybin <g.ulairi@gmail.com>
Date: Sun Mar 11 19:27:41 2012 +0600
Upgrade gflags and glog libraries - stage 2 (final)
Changes to upstream code which are needed to make libmv compile smooth on all platforms
* Replace <gflags/gflags.h> with "third_party/gflags/gflags/gflags.h" which is easier
to setup things in libmv and also helps with setting up building libmv into
external applications.
* Replace "glog/logging.h" and "glog/logging.h" with <glog/logging.h> and <glog/logging.h>
which is needed on Windows platform because otherwise files like logging.cc will be using
relative path which points to headers used by linux instead of headers need to be used
on Windows.
* Replace _asm int 3 with __debugbreak(). Such assembler code is obsolete and doesn't work
with 64bit versions of MSVC compilers.
* Do not use stacktrace for MinGW and FreeBSD because it leads into issues accessing
some specific data on this platforms.
* Define HAVE_LIB_GFLAGS for Windows builds.
* Do not define __declspec(dllimport) for MinGW platforms.
* Setup proper includes and datatypes for int32, uint32, int64 and uint64 for MinGW
* Do not define va_copy for MinGW platforms (it's already defined there).
* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
of lack of needed functions.
commit 8ed07abfa49d1e0511752021c972e0715e5a1383
Author: Sergey I. Sharybin <g.ulairi@gmail.com>
Date: Sun Mar 11 19:06:33 2012 +0600
Upgrade gflags and glog libraries - stage 1
This commit copies sources from latest original release of gflags and glog
over currently bundled versions of this libraries without any modifications.
This revision can't b compiled, all needed changes to make new libraries working
fine will be done with next commit to make it clear which changes were necessary
for easier bundling further newer version and extract patches and put them to
gflags/glog upstream repo.
Such upgrade of libraries is needed to make it able to compile libmv
with clang compilers. Currently used versions:
- gflags is version 2.0
- glog is version 0.3.2
commit 75b9af405964ff2c7d3f0a44500e27e63b37c91b
Author: Sergey Sharybin <sergey.vfx@gmail.com>
Date: Fri Feb 17 23:29:11 2012 +0600
@ -423,27 +489,3 @@ Date: Fri Aug 19 00:02:12 2011 +0200
Document coordinate descent method in affine SAD matcher.
Add heuristic to prevent high distortions.
commit 75520f4bc4ccbb272a1b4149d3b8d05a90f7f896
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Thu Aug 18 23:14:17 2011 +0200
Fix affine iteration.
commit 4e8e0aa6018e3eb2fbebdad7f1cbd6c909d26e79
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Thu Aug 18 23:03:26 2011 +0200
Handle rotations.
commit 3ce41cf3c1b5c136a61d8f4c63ccae3cafbdb8da
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Thu Aug 18 22:24:47 2011 +0200
Slow brute-force affine diamond search implementation.
commit 1c4acd03e030c1c50dc6fc36c419c72ea69a0713
Author: Matthias Fauconneau <matthias.fauconneau@gmail.com>
Date: Thu Aug 18 20:51:43 2011 +0200
Fix detect.cc.

@ -131,6 +131,19 @@ set(INC_SYS
\${ZLIB_INCLUDE_DIRS}
)
# XXX - FIXME
# this is a momentary hack to find unwind.h in 10.6.sdk
if(APPLE)
if(\${CMAKE_OSX_DEPLOYMENT_TARGET} STREQUAL "10.6")
list(APPEND INC_SYS
\${CMAKE_OSX_SYSROOT}/Developer/usr/llvm-gcc-4.2/lib/gcc/i686-apple-darwin10/4.2.1/include
)
endif()
endif()
# XXX - END
set(SRC
libmv-capi.cpp
${sources}

@ -78,14 +78,20 @@ third_party/fast/LICENSE
third_party/fast/nonmax.c
third_party/fast/README
third_party/fast/README.libmv
third_party/gflags/AUTHORS
third_party/gflags/ChangeLog
third_party/gflags/config.h
third_party/gflags/COPYING
third_party/gflags/gflags.cc
third_party/gflags/gflags_completions.cc
third_party/gflags/gflags_completions.h
third_party/gflags/gflags.h
third_party/gflags/gflags/gflags_completions.h
third_party/gflags/gflags/gflags_declare.h
third_party/gflags/gflags/gflags.h
third_party/gflags/gflags_reporting.cc
third_party/gflags/mutex.h
third_party/gflags/NEWS
third_party/gflags/README.libmv
third_party/gflags/util.h
third_party/glog/AUTHORS
third_party/glog/ChangeLog
third_party/glog/COPYING

@ -30,6 +30,7 @@
#include "libmv-capi.h"
#include "third_party/gflags/gflags/gflags.h"
#include "glog/logging.h"
#include "libmv/logging/logging.h"

@ -21,7 +21,7 @@
#ifndef LIBMV_LOGGING_LOGGING_H
#define LIBMV_LOGGING_LOGGING_H
#include "glog/logging.h"
#include <glog/logging.h>
#define LG LOG(INFO)
#define V0 LOG(INFO)

@ -280,6 +280,25 @@ double InternalReprojectionError(const Tracks &image_tracks,
double ex = reprojected_marker.x - markers[i].x;
double ey = reprojected_marker.y - markers[i].y;
const int N = 100;
char line[N];
snprintf(line, N,
"image %-3d track %-3d "
"x %7.1f y %7.1f "
"rx %7.1f ry %7.1f "
"ex %7.1f ey %7.1f"
" e %7.1f",
markers[i].image,
markers[i].track,
markers[i].x,
markers[i].y,
reprojected_marker.x,
reprojected_marker.y,
ex,
ey,
sqrt(ex*ex + ey*ey));
LG << line;
total_error += sqrt(ex*ex + ey*ey);
}
LG << "Skipped " << num_skipped << " markers.";

@ -1,152 +0,0 @@
diff --git a/src/libmv/logging/logging.h b/src/libmv/logging/logging.h
index 067da52..af86c4b 100644
--- a/src/libmv/logging/logging.h
+++ b/src/libmv/logging/logging.h
@@ -21,7 +21,7 @@
#ifndef LIBMV_LOGGING_LOGGING_H
#define LIBMV_LOGGING_LOGGING_H
-#include "third_party/glog/src/glog/logging.h"
+#include "glog/logging.h"
#define LG LOG(INFO)
#define V0 LOG(INFO)
diff --git a/src/libmv/simple_pipeline/pipeline.cc b/src/libmv/simple_pipeline/pipeline.cc
index 2459d05..2e4e5a6 100644
--- a/src/libmv/simple_pipeline/pipeline.cc
+++ b/src/libmv/simple_pipeline/pipeline.cc
@@ -280,25 +280,6 @@ double InternalReprojectionError(const Tracks &image_tracks,
double ex = reprojected_marker.x - markers[i].x;
double ey = reprojected_marker.y - markers[i].y;
- const int N = 100;
- char line[N];
- snprintf(line, N,
- "image %-3d track %-3d "
- "x %7.1f y %7.1f "
- "rx %7.1f ry %7.1f "
- "ex %7.1f ey %7.1f"
- " e %7.1f",
- markers[i].image,
- markers[i].track,
- markers[i].x,
- markers[i].y,
- reprojected_marker.x,
- reprojected_marker.y,
- ex,
- ey,
- sqrt(ex*ex + ey*ey));
- LG << line;
-
total_error += sqrt(ex*ex + ey*ey);
}
LG << "Skipped " << num_skipped << " markers.";
diff --git a/src/third_party/glog/src/glog/logging.h b/src/third_party/glog/src/glog/logging.h
index 57615ef..a58d478 100644
--- a/src/third_party/glog/src/glog/logging.h
+++ b/src/third_party/glog/src/glog/logging.h
@@ -33,6 +33,7 @@
// Pretty much everybody needs to #include this file so that they can
// log various happenings.
//
+
#ifndef _LOGGING_H_
#define _LOGGING_H_
diff --git a/src/third_party/glog/src/logging.cc b/src/third_party/glog/src/logging.cc
index 868898f..1bb3867 100644
--- a/src/third_party/glog/src/logging.cc
+++ b/src/third_party/glog/src/logging.cc
@@ -58,8 +58,8 @@
#include <errno.h> // for errno
#include <sstream>
#include "base/commandlineflags.h" // to get the program name
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
#include "base/googleinit.h"
#ifdef HAVE_STACKTRACE
@@ -1232,7 +1232,9 @@ void LogMessage::RecordCrashReason(
}
static void logging_fail() {
-#if defined(_DEBUG) && defined(_MSC_VER)
+// #if defined(_DEBUG) && defined(_MSC_VER)
+// doesn't work for my laptop (sergey)
+#if 0
// When debugging on windows, avoid the obnoxious dialog and make
// it possible to continue past a LOG(FATAL) in the debugger
_asm int 3
diff --git a/src/third_party/glog/src/raw_logging.cc b/src/third_party/glog/src/raw_logging.cc
index 50c6a71..b179a1e 100644
--- a/src/third_party/glog/src/raw_logging.cc
+++ b/src/third_party/glog/src/raw_logging.cc
@@ -42,8 +42,8 @@
#include <fcntl.h> // for open()
#include <time.h>
#include "config.h"
-#include "glog/logging.h" // To pick up flag settings etc.
-#include "glog/raw_logging.h"
+#include <glog/logging.h> // To pick up flag settings etc.
+#include <glog/raw_logging.h>
#include "base/commandlineflags.h"
#ifdef HAVE_STACKTRACE
diff --git a/src/third_party/glog/src/utilities.h b/src/third_party/glog/src/utilities.h
index c4ae256..5c841a0 100644
--- a/src/third_party/glog/src/utilities.h
+++ b/src/third_party/glog/src/utilities.h
@@ -79,7 +79,7 @@
#endif
#include "config.h"
-#include "glog/logging.h"
+#include <glog/logging.h>
// There are three different ways we can try to get the stack trace:
//
diff --git a/src/third_party/glog/src/vlog_is_on.cc b/src/third_party/glog/src/vlog_is_on.cc
index ee0e412..ed88514 100644
--- a/src/third_party/glog/src/vlog_is_on.cc
+++ b/src/third_party/glog/src/vlog_is_on.cc
@@ -40,8 +40,8 @@
#include <cstdio>
#include <string>
#include "base/commandlineflags.h"
-#include "glog/logging.h"
-#include "glog/raw_logging.h"
+#include <glog/logging.h>
+#include <glog/raw_logging.h>
#include "base/googleinit.h"
// glog doesn't have annotation
diff --git a/src/third_party/glog/src/windows/config.h b/src/third_party/glog/src/windows/config.h
index 114762e..682a1b9 100755
--- a/src/third_party/glog/src/windows/config.h
+++ b/src/third_party/glog/src/windows/config.h
@@ -19,7 +19,7 @@
#undef HAVE_LIBUNWIND_H
/* define if you have google gflags library */
-#undef HAVE_LIB_GFLAGS
+#define HAVE_LIB_GFLAGS 1
/* define if you have libunwind */
#undef HAVE_LIB_UNWIND
diff --git a/src/third_party/glog/src/windows/glog/logging.h b/src/third_party/glog/src/windows/glog/logging.h
index 4257375..2f41681 100755
--- a/src/third_party/glog/src/windows/glog/logging.h
+++ b/src/third_party/glog/src/windows/glog/logging.h
@@ -82,8 +82,8 @@
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
-#if 0
-#include <gflags/gflags.h>
+#if 1
+#include "third_party/gflags/gflags.h"
#endif
#ifdef __MINGW32__

@ -1,49 +0,0 @@
Index: third_party/glog/src/utilities.h
===================================================================
--- third_party/glog/src/utilities.h (revision 44501)
+++ third_party/glog/src/utilities.h (working copy)
@@ -105,7 +105,7 @@
# undef STACKTRACE_H
#elif defined(HAVE_LIB_UNWIND)
# define STACKTRACE_H "stacktrace_libunwind-inl.h"
-#elif !defined(NO_FRAME_POINTER)
+#elif !defined(NO_FRAME_POINTER) && !defined(__clang__)
# if defined(__i386__) && __GNUC__ >= 2
# define STACKTRACE_H "stacktrace_x86-inl.h"
# elif defined(__x86_64__) && __GNUC__ >= 2
Index: third_party/glog/src/logging.cc
===================================================================
--- third_party/glog/src/logging.cc (revision 44501)
+++ third_party/glog/src/logging.cc (working copy)
@@ -1231,6 +1231,14 @@
#endif
}
+#if defined(HAVE___ATTRIBUTE__)
+typedef void (*fail_func_t)() __attribute__((noreturn));
+static void logging_fail() __attribute__((noreturn));
+#else
+typedef void (*fail_func_t)();
+static void logging_fail();
+#endif
+
static void logging_fail() {
// #if defined(_DEBUG) && defined(_MSC_VER)
// doesn't work for my laptop (sergey)
@@ -1243,14 +1251,9 @@
#endif
}
-#ifdef HAVE___ATTRIBUTE__
-GOOGLE_GLOG_DLL_DECL
-void (*g_logging_fail_func)() __attribute__((noreturn)) = &logging_fail;
-#else
-GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)() = &logging_fail;
-#endif
+GOOGLE_GLOG_DLL_DECL fail_func_t g_logging_fail_func = &logging_fail;
-void InstallFailureFunction(void (*fail_func)()) {
+void InstallFailureFunction(fail_func_t fail_func) {
g_logging_fail_func = fail_func;
}

@ -1,3 +1 @@
v3d_verbosity.patch
bundle_tweaks.patch
clang-3.diff

@ -0,0 +1,2 @@
google-gflags@googlegroups.com

28
extern/libmv/third_party/gflags/COPYING vendored Normal file

@ -0,0 +1,28 @@
Copyright (c) 2006, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

@ -0,0 +1,195 @@
Wed Jan 25 15:09:14 2012 Google Inc. <google-gflags@googlegroups.com>
* gflags: version 2.0
* Changed the 'official' gflags email in setup.py/etc
* Renamed google-gflags.sln to gflags.sln
* Changed copyright text to reflect Google's relinquished ownership
Tue Dec 20 19:48:57 2011 Google Inc. <opensource@google.com>
* google-gflags: version 1.7
* Add CommandLineFlagInfo::flag_ptr pointing to current storage (musji)
* PORTING: flush after writing to stderr, needed on cygwin
* PORTING: Clean up the GFLAGS_DLL_DECL stuff better
* Fix a bug in StringPrintf() that affected large strings (csilvers)
* Die at configure-time when g++ isn't installed
Fri Jul 29 19:05:21 2011 Google Inc. <opensource@google.com>
* google-gflags: version 1.6
* BUGFIX: Fix a bug where we were leaving out a required $(top_srcdir)
* Fix definition of clstring (jyrki)
* Split up flag declares into its own file (jyrki)
* Add --version support (csilvers)
* Update the README for gflags with static libs
* Update acx_pthread.m4 for nostdlib
* Change ReparseCommandLineFlags to return void (csilvers)
* Some doc typofixes and example augmentation (various)
Mon Jan 24 16:11:35 2011 Google Inc. <opensource@google.com>
* google-gflags: version 1.5
* Better reporting of current vs default value (handler)
* Add API for cleaning up of memory at program-exit (jmarantz)
* Fix macros to work inside namespaces (csilvers)
* Use our own string typedef in case string is redefined (csilvers)
* Updated to autoconf 2.65
Wed Oct 13 17:40:12 2010 Google Inc. <opensource@google.com>
* google-gflags: version 1.4
* Add a check to prevent passing 0 to DEFINE_string (jorg)
* Reduce compile (.o) size (jyrki)
* Some small changes to quiet debug compiles (alexk)
* PORTING: better support static linking on windows (csilvers)
* DOCUMENTATION: change default values, use validators, etc.
* Update the NEWS file to be non-empty
* Add pkg-config (.pc) files for libgflags and libgflags_nothreads
Mon Jan 4 18:09:30 2010 Google Inc. <opensource@google.com>
* google-gflags: version 1.3
* PORTABILITY: can now build and run tests under MSVC (csilvers)
* Remove the python gflags code, which is now its own package (tansell)
* Clarify that "last flag wins" in the docs (csilvers)
* Comment danger of using GetAllFlags in validators (wojtekm)
* PORTABILITY: Some fixes necessary for c++0x (mboerger)
* Makefile fix: $(srcdir) -> $(top_srcdir) in one place (csilvres)
* INSTALL: autotools to autoconf v2.64 + automake v1.11 (csilvers)
Thu Sep 10 12:53:04 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.2
* PORTABILITY: can now build and run tests under mingw (csilvers)
* Using a string arg for a bool flag is a compile-time error (rbayardo)
* Add --helpxml to gflags.py (salcianu)
* Protect against a hypothetical global d'tor mutex problem (csilvers)
* BUGFIX: can now define a flag after 'using namespace google' (hamaji)
Tue Apr 14 12:35:25 2009 Google Inc. <opensource@google.com>
* google-gflags: version 1.1
* Add both foo and nofoo for boolean flags, with --undefok (andychu)
* Better document how validators work (wojtekm)
* Improve binary-detection for bash-completion (mtamsky)
* Python: Add a concept of "key flags", used with --help (salcianu)
* Python: Robustify flag_values (salcianu)
* Python: Add a new DEFINE_bool alias (keir, andrewliu)
* Python: Do module introspection based on module name (dsturtevant)
* Fix autoconf a bit better, especially on windows and solaris (ajenjo)
* BUG FIX: gflags_nothreads was linking against the wrong lib (ajenjo)
* BUG FIX: threads-detection failed on FreeBSD; replace it (ajenjo)
* PORTABILITY: Quiet an internal compiler error with SUSE 10 (csilvers)
* PORTABILITY: Update deb.sh for more recenty debuilds (csilvers)
* PORTABILITY: #include more headers to satify new gcc's (csilvers)
* INSTALL: Updated to autoconf 2.61 and libtool 1.5.26 (csilvers)
Fri Oct 3 15:16:46 2008 Google Inc. <opensource@google.com>
* google-gflags: version 1.0
* Add a missing newline to an error string (bcmills)
* (otherwise exactly the same as gflags 1.0rc2)
Thu Sep 18 12:58:05 2008 Google Inc. <opensource@google.com>
* google-gflags: version 1.0rc2
* Report current flag values in --helpxml (hdn)
* Fix compilation troubles with gcc 4.3.3 (simonb)
* BUG FIX: I was missing a std:: in DECLARE_string (csilvers)
* BUG FIX: Clarify in docs how to specify --bool flags (csilvers)
* BUG FIX: Fix --helpshort for source files not in a subdir (csilvers)
* BUG FIX: Fix python unittest for 64-bit builds (bcmills)
Tue Aug 19 16:15:48 2008
* google-gflags: version 1.0rc1
* Move #include files from google/ to gflags/ (csilvers)
* Small optimizations to reduce binary (library) size (jyrki)
* BUGFIX: forgot a std:: in one of the .h files (csilvers)
* Speed up locking by making sure calls are inlined (ajenjo)
* 64-BIT COMPATIBILITY: Use %PRId64 instead of %lld (csilvers)
* PORTABILITY: fix Makefile to work with Cygwin (ajenjo)
* PORTABILITY: fix code to compile under Visual Studio (ajenjo)
* PORTABILITY: fix code to compile under Solaris 10 with CC (csilvers)
Mon Jul 21 23:01:38 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.9
* Add the ability to validate a command-line flag (csilvers)
* Add completion support for commandline flags in bash (daven)
* Add -W compile flags to Makefile, when using gcc (csilvers)
* Allow helpstring to be NULL (cristianoc)
* Improved documentation of classes in the .cc file (csilvers)
* Fix python bug with AppendFlagValues + shortnames (jjtswan)
* Use bool instead of int for boolean flags in gflags.py (bcmills)
* Simplify the way we declare flags, now more foolproof (csilvers)
* Better error messages when bool flags collide (colohan)
* Only evaluate DEFINE_foo macro args once (csilvers)
Wed Mar 26 15:20:18 2008 Google Inc. <opensource@google.com>
* google-gflags: version 0.8
* Export DescribeOneFlag() in the API
* Add support for automatic line wrapping at 80 cols for gflags.py
* Bugfix: do not treat an isolated "-" the same as an isolated "--"
* Update rpm spec to point to Google Code rather than sourceforge (!)
* Improve documentation (including documenting thread-safety)
* Improve #include hygiene
* Improve testing
Thu Oct 18 11:33:20 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.7
* Deal even more correctly with libpthread not linked in (csilvers)
* Add STRIP_LOG, an improved DO_NOT_SHOW_COMMANDLINE_HELP (sioffe)
* Be more accurate printing default flag values in --help (dsturtevant)
* Reduce .o file size a bit by using shorter namespace names (jeff)
* Use relative install path, so 'setup.py --home' works (csilvers)
* Notice when a boolean flag has a non-boolean default (bnmouli)
* Broaden --helpshort to match foo-main.cc and foo_main.cc (hendrie)
* Fix "no modules match" message for --helpshort, etc (hendrie)
Wed Aug 15 07:35:51 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.6
* Deal correctly with case that libpthread is not linked in (csilvers)
* Update Makefile/tests so we pass "make distcheck" (csilvers)
* Document and test that last assignment to a flag wins (wan)
Tue Jun 12 15:23:42 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.5
* Include all m4 macros in the distribution (csilvers)
* Python: Fix broken data_files field in setup.py (sidlon)
* Python: better string serliaizing and unparsing (abo, csimmons)
* Fix checks for NaN and inf to work with Mac OS X (csilvers)
Thu Apr 19 15:15:07 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.4
* Remove is_default from GetCommandLineFlagInfo (csilvers)
* Portability fixes: includes, strtoll, gcc4.3 errors (csilvers)
* A few doc typo cleanups (csilvers)
Wed Mar 28 12:15:56 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.3
* python portability fix: use popen instead of subprocess (csilvers)
* Add is_default to CommandLineFlagInfo (pchien)
* Make docs a bit prettier (csilvers)
* Actually include the python files in the distribution! :-/ (csilvers)
Mon Jan 22 15:33:06 2007 Google Inc. <opensource@google.com>
* google-gflags: version 0.2
* added support for python commandlineflags, as well as c++
* gflags2man, a script to turn flags into a man page (dchristian)
Wed Dec 13 12:37:19 2006 Google Inc. <opensource@google.com>
* google-gflags: initial release:
The gflags package contains a library that implements commandline
flags processing. As such it's a replacement for getopt(). It
has increased flexibility, including built-in support for C++
types like string, and the ability to define flags in the source
file in which they're used.

158
extern/libmv/third_party/gflags/NEWS vendored Normal file

@ -0,0 +1,158 @@
== 25 January 2012 ==
I've just released gflags 2.0.
The `google-gflags` project has been renamed to `gflags`. I
(csilvers) am stepping down as maintainer, to be replaced by Andreas
Schuh. Welcome to the team, Andreas! I've seen the energy you have
around gflags and the ideas you have for the project going forward,
and look forward to having you on the team.
I bumped the major version number up to 2 to reflect the new community
ownership of the project. All the
[http://gflags.googlecode.com/svn/tags/gflags-2.0/ChangeLog changes]
are related to the renaming. There are no functional changes from
gflags 1.7. In particular, I've kept the code in the namespace
`google`, though in a future version it should be renamed to `gflags`.
I've also kept the `/usr/local/include/google/` subdirectory as
synonym of `/usr/local/include/gflags/`, though the former name has
been obsolete for some time now.
=== 18 January 2011 ===
The `google-gflags` Google Code page has been renamed to
`gflags`, in preparation for the project being renamed to
`gflags`. In the coming weeks, I'll be stepping down as
maintainer for the gflags project, and as part of that Google is
relinquishing ownership of the project; it will now be entirely
community run. The name change reflects that shift.
=== 20 December 2011 ===
I've just released gflags 1.7. This is a minor release; the major
change is that `CommandLineFlagInfo` now exports the address in memory
where the flag is located. There has also been a bugfix involving
very long --help strings, and some other minor
[http://code.google.com/p/google-gflags/source/browse/tags/gflags-1.7/ChangeLog changes].
=== 29 July 2011 ===
I've just released gflags 1.6. The major new feature in this release
is support for setting version info, so that --version does something
useful.
One minor change has required bumping the library number:
`ReparseCommandlineFlags` now returns `void` instead of `int` (the int
return value was always meaningless). Though I doubt anyone ever used
this (meaningless) return value, technically it's a change to the ABI
that requires a version bump. A bit sad.
There's also a procedural change with this release: I've changed the
internal tools used to integrate Google-supplied patches for gflags
into the opensource release. These new tools should result in more
frequent updates with better change descriptions. They will also
result in future `ChangeLog` entries being much more verbose (for better
or for worse).
See the
[http://code.google.com/p/google-gflags/source/browse/tags/gflags-1.6/ChangeLog ChangeLog]
for a full list of changes for this release.
=== 24 January 2011 ===
I've just released gflags 1.5. This release has only minor changes
from 1.4, including some slightly better reporting in --help, and
an new memory-cleanup function that can help when running gflags-using
libraries under valgrind. The major change is to fix up the macros
(`DEFINE_bool` and the like) to work more reliably inside namespaces.
If you have not had a problem with these macros, and don't need any of
the other changes described, there is no need to upgrade. See the
[http://code.google.com/p/google-gflags/source/browse/tags/gflags-1.5/ChangeLog ChangeLog]
for a full list of changes for this release.
=== 11 October 2010 ===
I've just released gflags 1.4. This release has only minor changes
from 1.3, including some documentation tweaks and some work to make
the library smaller. If 1.3 is working well for you, there's no
particular reason to upgrade.
=== 4 January 2010 ===
I've just released gflags 1.3. gflags now compiles under MSVC, and
all tests pass. I *really* never thought non-unix-y Windows folks
would want gflags, but at least some of them do.
The major news, though, is that I've separated out the python package
into its own library, [http://code.google.com/p/python-gflags python-gflags].
If you're interested in the Python version of gflags, that's the place to
get it now.
=== 10 September 2009 ==
I've just released gflags 1.2. The major change from gflags 1.1 is it
now compiles under MinGW (as well as cygwin), and all tests pass. I
never thought Windows folks would want unix-style command-line flags,
since they're so different from the Windows style, but I guess I was
wrong!
The other changes are minor, such as support for --htmlxml in the
python version of gflags.
=== 15 April 2009 ===
I've just released gflags 1.1. It has only minor changes fdrom gflags
1.0 (see the
[http://code.google.com/p/google-gflags/source/browse/tags/gflags-1.1/ChangeLog ChangeLog]
for details). The major change is that I moved to a new
system for creating .deb and .rpm files. This allows me to create
x86_64 deb and rpm files.
In the process of moving to this new system, I noticed an
inconsistency: the tar.gz and .rpm files created libraries named
libgflags.so, but the deb file created libgoogle-gflags.so. I have
fixed the deb file to create libraries like the others. I'm no expert
in debian packaging, but I believe this has caused the package name to
change as well. Please let me know (at
[mailto:google-gflags@googlegroups.com
google-gflags@googlegroups.com]) if this causes problems for you --
especially if you know of a fix! I would be happy to change the deb
packages to add symlinks from the old library name to the new
(libgoogle-gflags.so -> libgflags.so), but that is beyond my knowledge
of how to make .debs.
If you've tried to install a .rpm or .deb and it doesn't work for you,
let me know. I'm excited to finally have 64-bit package files, but
there may still be some wrinkles in the new system to iron out.
===1 October 2008===
gflags 1.0rc2 was out for a few weeks without any issues, so gflags
1.0 is now released. This is much like gflags 0.9. The major change
is that the .h files have been moved from `/usr/include/google` to
`/usr/include/gflags`. While I have backwards-compatibility
forwarding headeds in place, please rewrite existing code to say
{{{
#include <gflags/gflags.h>
}}}
instead of
{{{
#include <google/gflags.h>
}}}
I've kept the default namespace to google. You can still change with
with the appropriate flag to the configure script (`./configure
--help` to see the flags). If you have feedback as to whether the
default namespace should change to gflags, which would be a
non-backwards-compatible change, send mail to
`google-gflags@googlegroups.com`!
Version 1.0 also has some neat new features, like support for bash
commandline-completion of help flags. See the
[http://code.google.com/p/google-gflags/source/browse/tags/gflags-1.0rc2/ChangeLog
ChangeLog] for more details.
If I don't hear any bad news for a few weeks, I'll release 1.0-final.

@ -1,7 +1,7 @@
Project: Google Flags
URL: http://code.google.com/p/google-gflags/
License: New BSD
Upstream version: 1.5
Upstream version: 2.0
Local modifications:
- Flattened the tree and only included files needed for libmv. This involved

@ -15,7 +15,7 @@
#define HAVE_DLFCN_H 1
/* Define to 1 if you have the <fnmatch.h> header file. */
#undef HAVE_FNMATCH_H
/* #ubdef HAVE_FNMATCH_H 1 */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
@ -29,12 +29,6 @@
/* Define if you have POSIX threads libraries and header files. */
#define HAVE_PTHREAD 1
/* Define to 1 if you have the `putenv' function. */
#define HAVE_PUTENV 1
/* Define to 1 if you have the `setenv' function. */
#define HAVE_SETENV 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
@ -73,22 +67,19 @@
#define PACKAGE "gflags"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "opensource@google.com"
#define PACKAGE_BUGREPORT "google-gflags@googlegroups.com"
/* Define to the full name of this package. */
#define PACKAGE_NAME "gflags"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "gflags 1.5"
#define PACKAGE_STRING "gflags 2.0"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "gflags"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.5"
#define PACKAGE_VERSION "2.0"
/* Define to necessary symbol if this constant uses a non-standard name on
your system. */
@ -101,7 +92,7 @@
#define STL_NAMESPACE std
/* Version number of package */
#define VERSION "1.5"
#define VERSION "2.0"
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }

@ -1,4 +1,4 @@
// Copyright (c) 2006, Google Inc.
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This file contains the implementation of all our command line flags
@ -88,76 +87,35 @@
// other hand, hooks into CommandLineFlagParser. Other API functions
// are, similarly, mostly hooks into the functionality described above.
#include "config.h"
// This comes first to ensure we define __STDC_FORMAT_MACROS in time.
#ifdef HAVE_INTTYPES_H
#ifndef __STDC_FORMAT_MACROS
#include "config.h"
#if defined(HAVE_INTTYPES_H) && !defined(__STDC_FORMAT_MACROS)
# define __STDC_FORMAT_MACROS 1 // gcc requires this to get PRId64, etc.
#endif
#include <inttypes.h>
#endif // HAVE_INTTYPES_H
#include <stdio.h> // for snprintf
#include "gflags/gflags.h"
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdarg.h> // For va_list and related operations
#include <string.h>
#include <assert.h>
#ifdef HAVE_FNMATCH_H
#include <fnmatch.h>
#endif // HAVE_FNMATCH_H
#include <string>
#include <map>
#include <vector>
#include <utility> // for pair<>
# include <fnmatch.h>
#endif
#include <stdarg.h> // For va_list and related operations
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include "gflags.h"
#include <map>
#include <string>
#include <utility> // for pair<>
#include <vector>
#include "mutex.h"
#include "util.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
// Work properly if either strtoll or strtoq is on this system
#ifdef HAVE_STRTOLL
# define strtoint64 strtoll
# define strtouint64 strtoull
#elif HAVE_STRTOQ
# define strtoint64 strtoq
# define strtouint64 strtouq
#else
// Neither strtoll nor strtoq are defined. I hope strtol works!
# define strtoint64 strtol
# define strtouint64 strtoul
#endif
// If we have inttypes.h, it will have defined PRId32/etc for us. If
// not, take our best guess.
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
// Windows is missing random bits like strcasecmp, strtoll, strtoull, and
// snprintf in the usual locations. Put them somewhere sensible.
//
// TODO(keir): Get the upstream Windows port and use that instead.
#ifdef _MSC_VER
# define snprintf _snprintf
# undef strtoint64
# define strtoint64 _strtoi64
# undef strtouint64
# define strtouint64 _strtoui64
# define strcasecmp _stricmp
#endif
typedef signed char int8;
typedef unsigned char uint8;
// Special flags, type 1: the 'recursive' flags. They set another flag's val.
DEFINE_string(flagfile, "",
@ -183,20 +141,21 @@ using std::sort;
using std::string;
using std::vector;
// This is used by the unittest to test error-exit code
void GFLAGS_DLL_DECL (*gflags_exitfunc)(int) = &exit; // from stdlib.h
// The help message indicating that the commandline flag has been
// 'stripped'. It will not show up when doing "-help" and its
// variants. The flag is stripped if STRIP_FLAG_HELP is set to 1
// before including gflags/gflags.h.
// before including base/gflags.h
// This is used by this file, and also in commandlineflags_reporting.cc
// This is used by this file, and also in gflags_reporting.cc
const char kStrippedFlagHelp[] = "\001\002\003\004 (unknown) \004\003\002\001";
// This is used by the unittest to test error-exit code
void GFLAGS_DLL_DECL (*commandlineflags_exitfunc)(int) = &exit; // from stdlib.h
namespace {
// There are also 'reporting' flags, in commandlineflags_reporting.cc.
// There are also 'reporting' flags, in gflags_reporting.cc.
static const char kError[] = "ERROR: ";
@ -218,12 +177,14 @@ enum DieWhenReporting { DIE, DO_NOT_DIE };
// Report Error and exit if requested.
static void ReportError(DieWhenReporting should_die, const char* format, ...) {
char error_message[255];
va_list ap;
va_start(ap, format);
vfprintf(stderr, format, ap);
vsnprintf(error_message, sizeof(error_message), format, ap);
va_end(ap);
if (should_die == DIE)
commandlineflags_exitfunc(1); // almost certainly exit()
fprintf(stderr, "%s", error_message);
fflush(stderr); // should be unnecessary, but cygwin's rxvt buffers stderr
if (should_die == DIE) gflags_exitfunc(1);
}
@ -317,6 +278,7 @@ bool FlagValue::ParseFrom(const char* value) {
if (type_ == FV_BOOL) {
const char* kTrue[] = { "1", "t", "true", "y", "yes" };
const char* kFalse[] = { "0", "f", "false", "n", "no" };
COMPILE_ASSERT(sizeof(kTrue) == sizeof(kFalse), true_false_equal);
for (size_t i = 0; i < sizeof(kTrue)/sizeof(*kTrue); ++i) {
if (strcasecmp(value, kTrue[i]) == 0) {
SET_VALUE_AS(bool, true);
@ -346,7 +308,7 @@ bool FlagValue::ParseFrom(const char* value) {
switch (type_) {
case FV_INT32: {
const int64 r = strtoint64(value, &end, base);
const int64 r = strto64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
if (static_cast<int32>(r) != r) // worked, but number out of range
return false;
@ -354,7 +316,7 @@ bool FlagValue::ParseFrom(const char* value) {
return true;
}
case FV_INT64: {
const int64 r = strtoint64(value, &end, base);
const int64 r = strto64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(int64, r);
return true;
@ -362,7 +324,7 @@ bool FlagValue::ParseFrom(const char* value) {
case FV_UINT64: {
while (*value == ' ') value++;
if (*value == '-') return false; // negative number
const uint64 r = strtouint64(value, &end, base);
const uint64 r = strtou64(value, &end, base);
if (errno || end != value + strlen(value)) return false; // bad parse
SET_VALUE_AS(uint64, r);
return true;
@ -531,6 +493,7 @@ class CommandLineFlag {
string default_value() const { return defvalue_->ToString(); }
const char* type_name() const { return defvalue_->TypeName(); }
ValidateFnProto validate_function() const { return validate_fn_proto_; }
const void* flag_ptr() const { return current_->value_buffer_; }
void FillCommandLineFlagInfo(struct CommandLineFlagInfo* result);
@ -583,7 +546,6 @@ const char* CommandLineFlag::CleanFileName() const {
// search full path backwards.
// Stop going backwards at kRootDir; and skip by the first slash.
static const char kRootDir[] = ""; // can set this to root directory,
// e.g. "myproject"
if (sizeof(kRootDir)-1 == 0) // no prefix to strip
return filename();
@ -592,8 +554,7 @@ const char* CommandLineFlag::CleanFileName() const {
while ( clean_name > filename() ) {
if (*clean_name == PATH_SEPARATOR) {
if (strncmp(clean_name, kRootDir, sizeof(kRootDir)-1) == 0) {
// ".../myproject/base/logging.cc" ==> "base/logging.cc"
clean_name += sizeof(kRootDir)-1; // past "/myproject/"
clean_name += sizeof(kRootDir)-1; // past root-dir
break;
}
}
@ -614,6 +575,7 @@ void CommandLineFlag::FillCommandLineFlagInfo(
UpdateModifiedBit();
result->is_default = !modified_;
result->has_validator_fn = validate_function() != NULL;
result->flag_ptr = flag_ptr();
}
void CommandLineFlag::UpdateModifiedBit() {
@ -634,6 +596,7 @@ void CommandLineFlag::CopyFrom(const CommandLineFlag& src) {
}
bool CommandLineFlag::Validate(const FlagValue& value) const {
if (validate_function() == NULL)
return true;
else
@ -657,10 +620,14 @@ struct StringCmp { // Used by the FlagRegistry map class to compare char*'s
}
};
class FlagRegistry {
public:
FlagRegistry() { }
FlagRegistry() {
}
~FlagRegistry() {
// Not using STLDeleteElements as that resides in util and this
// class is base.
for (FlagMap::iterator p = flags_.begin(), e = flags_.end(); p != e; ++p) {
CommandLineFlag* flag = p->second;
delete flag;
@ -672,12 +639,12 @@ class FlagRegistry {
global_registry_ = NULL;
}
void Lock() { lock_.Lock(); }
void Unlock() { lock_.Unlock(); }
// Store a flag in this registry. Takes ownership of the given pointer.
void RegisterFlag(CommandLineFlag* flag);
void Lock() { lock_.Lock(); }
void Unlock() { lock_.Unlock(); }
// Returns the flag object for the specified name, or NULL if not found.
CommandLineFlag* FindFlagLocked(const char* name);
@ -718,26 +685,26 @@ class FlagRegistry {
typedef map<const void*, CommandLineFlag*> FlagPtrMap;
FlagPtrMap flags_by_ptr_;
Mutex lock_;
static FlagRegistry* global_registry_; // a singleton registry
static Mutex global_registry_lock_; // guards creation of global_registry_
Mutex lock_;
static Mutex global_registry_lock_;
static void InitGlobalRegistry();
// Disallow
FlagRegistry(const FlagRegistry&);
FlagRegistry& operator=(const FlagRegistry&);
};
FlagRegistry* FlagRegistry::global_registry_ = NULL;
Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
class FlagRegistryLock {
public:
explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
~FlagRegistryLock() { fr_->Unlock(); }
private:
FlagRegistry *const fr_;
};
FlagRegistry* FlagRegistry::GlobalRegistry() {
MutexLock acquire_lock(&global_registry_lock_);
if (!global_registry_) {
global_registry_ = new FlagRegistry;
}
return global_registry_;
}
void FlagRegistry::RegisterFlag(CommandLineFlag* flag) {
Lock();
@ -807,22 +774,22 @@ CommandLineFlag* FlagRegistry::SplitArgumentLocked(const char* arg,
// In that case, we want to return flag 'x'.
if (!(flag_name[0] == 'n' && flag_name[1] == 'o')) {
// flag-name is not 'nox', so we're not in the exception case.
*error_message = (string(kError) +
"unknown command line flag '" + *key + "'\n");
*error_message = StringPrintf("%sunknown command line flag '%s'\n",
kError, key->c_str());
return NULL;
}
flag = FindFlagLocked(flag_name+2);
if (flag == NULL) {
// No flag named 'x' exists, so we're not in the exception case.
*error_message = (string(kError) +
"unknown command line flag '" + *key + "'\n");
*error_message = StringPrintf("%sunknown command line flag '%s'\n",
kError, key->c_str());
return NULL;
}
if (strcmp(flag->type_name(), "bool") != 0) {
// 'x' exists but is not boolean, so we're not in the exception case.
*error_message = (string(kError) +
"boolean value (" + *key + ") specified for " +
flag->type_name() + " command line flag\n");
*error_message = StringPrintf(
"%sboolean value (%s) specified for %s command line flag\n",
kError, key->c_str(), flag->type_name());
return NULL;
}
// We're in the exception case!
@ -845,25 +812,27 @@ bool TryParseLocked(const CommandLineFlag* flag, FlagValue* flag_value,
FlagValue* tentative_value = flag_value->New();
if (!tentative_value->ParseFrom(value)) {
if (msg) {
*msg += (string(kError) + "illegal value '" + value +
+ "' specified for " + flag->type_name() + " flag '"
+ flag->name() + "'\n");
StringAppendF(msg,
"%sillegal value '%s' specified for %s flag '%s'\n",
kError, value,
flag->type_name(), flag->name());
}
delete tentative_value;
return false;
} else if (!flag->Validate(*tentative_value)) {
if (msg) {
*msg += (string(kError) + "failed validation of new value "
+ "'" + tentative_value->ToString() + "' for flag '" +
+ flag->name() + "'\n");
StringAppendF(msg,
"%sfailed validation of new value '%s' for flag '%s'\n",
kError, tentative_value->ToString().c_str(),
flag->name());
}
delete tentative_value;
return false;
} else {
flag_value->CopyFrom(*tentative_value);
if (msg) {
*msg += (string(flag->name()) + " set to " + flag_value->ToString()
+ "\n");
StringAppendF(msg, "%s set to %s\n",
flag->name(), flag_value->ToString().c_str());
}
delete tentative_value;
return true;
@ -890,7 +859,8 @@ bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
return false;
flag->modified_ = true;
} else {
*msg = string(flag->name()) + " set to " + flag->current_value();
*msg = StringPrintf("%s set to %s",
flag->name(), flag->current_value().c_str());
}
break;
}
@ -914,13 +884,17 @@ bool FlagRegistry::SetFlagLocked(CommandLineFlag* flag,
return true;
}
class FlagRegistryLock {
public:
explicit FlagRegistryLock(FlagRegistry* fr) : fr_(fr) { fr_->Lock(); }
~FlagRegistryLock() { fr_->Unlock(); }
private:
FlagRegistry *const fr_;
};
// Get the singleton FlagRegistry object
FlagRegistry* FlagRegistry::global_registry_ = NULL;
Mutex FlagRegistry::global_registry_lock_(Mutex::LINKER_INITIALIZED);
FlagRegistry* FlagRegistry::GlobalRegistry() {
MutexLock acquire_lock(&global_registry_lock_);
if (!global_registry_) {
global_registry_ = new FlagRegistry;
}
return global_registry_;
}
// --------------------------------------------------------------------
// CommandLineFlagParser
@ -1002,12 +976,12 @@ class CommandLineFlagParser {
static void ParseFlagList(const char* value, vector<string>* flags) {
for (const char *p = value; p && *p; value = p) {
p = strchr(value, ',');
int len;
size_t len;
if (p) {
len = static_cast<int>(p - value);
len = p - value;
p++;
} else {
len = static_cast<int>(strlen(value));
len = strlen(value);
}
if (len == 0)
@ -1023,7 +997,7 @@ static void ParseFlagList(const char* value, vector<string>* flags) {
// can do all the I/O in one place and not worry about it everywhere.
// Plus, it's convenient to have the whole file contents at hand.
// Adds a newline at the end of the file.
#define PFATAL(s) do { perror(s); commandlineflags_exitfunc(1); } while (0)
#define PFATAL(s) do { perror(s); gflags_exitfunc(1); } while (0)
static string ReadFileIntoString(const char* filename) {
const int kBufSize = 8092;
@ -1112,9 +1086,9 @@ uint32 CommandLineFlagParser::ParseNewCommandLineFlags(int* argc, char*** argv,
&& strcmp(flag->type_name(), "string") == 0
&& (strstr(flag->help(), "true")
|| strstr(flag->help(), "false"))) {
fprintf(stderr, "Did you really mean to set flag '%s'"
" to the value '%s'?\n",
flag->name(), value);
LOG(WARNING) << "Did you really mean to set flag '"
<< flag->name() << "' to the value '"
<< value << "'?";
}
}
}
@ -1165,9 +1139,10 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
const char* flagname = flaglist[i].c_str();
CommandLineFlag* flag = registry_->FindFlagLocked(flagname);
if (flag == NULL) {
error_flags_[flagname] = (string(kError) + "unknown command line flag"
+ " '" + flagname + "'"
+ " (via --fromenv or --tryfromenv)\n");
error_flags_[flagname] =
StringPrintf("%sunknown command line flag '%s' "
"(via --fromenv or --tryfromenv)\n",
kError, flagname);
undefined_names_[flagname] = "";
continue;
}
@ -1185,8 +1160,9 @@ string CommandLineFlagParser::ProcessFromenvLocked(const string& flagval,
// Avoid infinite recursion.
if ((strcmp(envval, "fromenv") == 0) ||
(strcmp(envval, "tryfromenv") == 0)) {
error_flags_[flagname] = (string(kError) + "infinite recursion on " +
"environment flag '" + envval + "'\n");
error_flags_[flagname] =
StringPrintf("%sinfinite recursion on environment flag '%s'\n",
kError, envval);
continue;
}
@ -1289,7 +1265,7 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
while (*flagfile_contents && isspace(*flagfile_contents))
++flagfile_contents;
line_end = strchr(flagfile_contents, '\n');
size_t len = line_end ? static_cast<size_t>(line_end - flagfile_contents)
size_t len = line_end ? line_end - flagfile_contents
: strlen(flagfile_contents);
string line(flagfile_contents, len);
@ -1340,17 +1316,17 @@ string CommandLineFlagParser::ProcessOptionsFromStringLocked(
space = word + strlen(word);
const string glob(word, space - word);
// We try matching both against the full argv0 and basename(argv0)
if (glob == ProgramInvocationName() // small optimization
|| glob == ProgramInvocationShortName()
#ifdef HAVE_FNMATCH_H
if (fnmatch(glob.c_str(),
ProgramInvocationName(),
FNM_PATHNAME) == 0 ||
fnmatch(glob.c_str(),
ProgramInvocationShortName(),
FNM_PATHNAME) == 0) {
#else // !HAVE_FNMATCH_H
if ((glob == ProgramInvocationName()) ||
(glob == ProgramInvocationShortName())) {
#endif // HAVE_FNMATCH_H
|| fnmatch(glob.c_str(),
ProgramInvocationName(),
FNM_PATHNAME) == 0
|| fnmatch(glob.c_str(),
ProgramInvocationShortName(),
FNM_PATHNAME) == 0
#endif
) {
flags_are_relevant = true;
}
}
@ -1391,14 +1367,14 @@ bool AddFlagValidator(const void* flag_ptr, ValidateFnProto validate_fn_proto) {
// This is the CommandLineFlag whose current_->value_buffer_ == flag
CommandLineFlag* flag = registry->FindFlagViaPtrLocked(flag_ptr);
if (!flag) {
// WARNING << "Ignoring RegisterValidateFunction() for flag pointer "
// << flag_ptr << ": no flag found at that address";
LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag pointer "
<< flag_ptr << ": no flag found at that address";
return false;
} else if (validate_fn_proto == flag->validate_function()) {
return true; // ok to register the same function over and over again
} else if (validate_fn_proto != NULL && flag->validate_function() != NULL) {
// WARNING << "Ignoring RegisterValidateFunction() for flag '"
// << flag->name() << "': validate-fn already registered";
LOG(WARNING) << "Ignoring RegisterValidateFunction() for flag '"
<< flag->name() << "': validate-fn already registered";
return false;
} else {
flag->validate_fn_proto_ = validate_fn_proto;
@ -1548,6 +1524,24 @@ const char* ProgramUsage() {
return "Warning: SetUsageMessage() never called";
}
// --------------------------------------------------------------------
// SetVersionString()
// VersionString()
// --------------------------------------------------------------------
static const char* version_string = NULL;
void SetVersionString(const string& version) {
if (version_string != NULL)
ReportError(DIE, "ERROR: SetVersionString() called twice\n");
version_string = strdup(version.c_str()); // small memory leak
}
const char* VersionString() {
return version_string ? version_string : "";
}
// --------------------------------------------------------------------
// GetCommandLineOption()
// GetCommandLineFlagInfo()
@ -1601,7 +1595,7 @@ CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name) {
CommandLineFlagInfo info;
if (!GetCommandLineFlagInfo(name, &info)) {
fprintf(stderr, "FATAL ERROR: flag name '%s' doesn't exist\n", name);
commandlineflags_exitfunc(1); // almost certainly exit()
gflags_exitfunc(1); // almost certainly gflags_exitfunc()
}
return info;
}
@ -1616,10 +1610,7 @@ string SetCommandLineOptionWithMode(const char* name, const char* value,
CommandLineFlagParser parser(registry);
result = parser.ProcessSingleOptionLocked(flag, value, set_mode);
if (!result.empty()) { // in the error case, we've already logged
// You could consider logging this change, if you wanted to know it:
//fprintf(stderr, "%sFLAGS_%s\n",
// (set_mode == SET_FLAGS_DEFAULT ? "default value of " : ""),
// result);
// Could consider logging this change
}
}
// The API of this function is that we return empty string on error
@ -1765,7 +1756,7 @@ bool ReadFlagsFromString(const string& flagfilecontents,
if (parser.ReportErrors()) {
// Error. Restore all global flags to their previous values.
if (errors_are_fatal)
commandlineflags_exitfunc(1); // almost certainly exit()
gflags_exitfunc(1);
saved_states.RestoreToRegistry();
return false;
}
@ -1917,7 +1908,7 @@ static uint32 ParseCommandLineFlagsInternal(int* argc, char*** argv,
parser.ValidateAllFlags();
if (parser.ReportErrors()) // may cause us to exit on illegal flags
commandlineflags_exitfunc(1); // almost certainly exit()
gflags_exitfunc(1);
return r;
}
@ -1947,7 +1938,7 @@ void AllowCommandLineReparsing() {
allow_command_line_reparsing = true;
}
uint32 ReparseCommandLineNonHelpFlags() {
void ReparseCommandLineNonHelpFlags() {
// We make a copy of argc and argv to pass in
const vector<string>& argvs = GetArgvs();
int tmp_argc = static_cast<int>(argvs.size());
@ -1955,13 +1946,11 @@ uint32 ReparseCommandLineNonHelpFlags() {
for (int i = 0; i < tmp_argc; ++i)
tmp_argv[i] = strdup(argvs[i].c_str()); // TODO(csilvers): don't dup
const int retval = ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
ParseCommandLineNonHelpFlags(&tmp_argc, &tmp_argv, false);
for (int i = 0; i < tmp_argc; ++i)
free(tmp_argv[i]);
delete[] tmp_argv;
return retval;
}
void ShutDownCommandLineFlags() {

@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
@ -52,8 +51,8 @@
// if (FLAGS_verbose) printf("Records %d-%d\n", FLAGS_start, FLAGS_end);
// }
//
// Then, at the command-line:
// ./foo --noverbose --start=5 --end=100
// Then, at the command-line:
// ./foo --noverbose --start=5 --end=100
//
// For more details, see
// doc/gflags.html
@ -76,48 +75,22 @@
// other thread is writing to the variable or calling non-const
// methods of this class.
#ifndef GOOGLE_GFLAGS_H_
#define GOOGLE_GFLAGS_H_
#ifndef BASE_COMMANDLINEFLAGS_H_
#define BASE_COMMANDLINEFLAGS_H_
#include <string>
#include <vector>
// We care a lot about number of bits things take up. Unfortunately,
// systems define their bit-specific ints in a lot of different ways.
// We use our own way, and have a typedef to get there.
// Note: these commands below may look like "#if 1" or "#if 0", but
// that's because they were constructed that way at ./configure time.
// Look at gflags.h.in to see how they're calculated (based on your config).
#if 1
#include <stdint.h> // the normal place uint16_t is defined
#endif
#if 1
#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if 1
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
#include "gflags_declare.h" // IWYU pragma: export
namespace google {
#if 1 // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 1 // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 0 // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
//
// NOTE: all functions below MUST have an explicit 'extern' before
// them. Our automated opensourcing tools use this as a signal to do
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
//
#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
#define GFLAGS_DLL_DEFINE_FLAG /* rewritten to be non-empty in windows dir */
// --------------------------------------------------------------------
// To actually define a flag in a file, use DEFINE_bool,
@ -148,18 +121,19 @@ typedef unsigned __int64 uint64;
// Returns true if successfully registered, false if not (because the
// first argument doesn't point to a command-line flag, or because a
// validator is already registered for this flag).
bool RegisterFlagValidator(const bool* flag,
bool (*validate_fn)(const char*, bool));
bool RegisterFlagValidator(const int32* flag,
bool (*validate_fn)(const char*, int32));
bool RegisterFlagValidator(const int64* flag,
bool (*validate_fn)(const char*, int64));
bool RegisterFlagValidator(const uint64* flag,
bool (*validate_fn)(const char*, uint64));
bool RegisterFlagValidator(const double* flag,
bool (*validate_fn)(const char*, double));
bool RegisterFlagValidator(const std::string* flag,
bool (*validate_fn)(const char*, const std::string&));
extern bool RegisterFlagValidator(const bool* flag,
bool (*validate_fn)(const char*, bool));
extern bool RegisterFlagValidator(const int32* flag,
bool (*validate_fn)(const char*, int32));
extern bool RegisterFlagValidator(const int64* flag,
bool (*validate_fn)(const char*, int64));
extern bool RegisterFlagValidator(const uint64* flag,
bool (*validate_fn)(const char*, uint64));
extern bool RegisterFlagValidator(const double* flag,
bool (*validate_fn)(const char*, double));
extern bool RegisterFlagValidator(const std::string* flag,
bool (*validate_fn)(const char*,
const std::string&));
// --------------------------------------------------------------------
@ -173,26 +147,27 @@ bool RegisterFlagValidator(const std::string* flag,
// name) and argv (the entire commandline), which we sock away a copy of.
// These variables are static, so you should only set them once.
struct CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on flag
bool is_default; // true if the flag has the default value and
// has not been set explicitly from the cmdline
// or via SetCommandLineOption
struct GFLAGS_DLL_DECL CommandLineFlagInfo {
std::string name; // the name of the flag
std::string type; // the type of the flag: int32, etc
std::string description; // the "help text" associated with the flag
std::string current_value; // the current value, as a string
std::string default_value; // the default value, as a string
std::string filename; // 'cleaned' version of filename holding the flag
bool has_validator_fn; // true if RegisterFlagValidator called on this flag
bool is_default; // true if the flag has the default value and
// has not been set explicitly from the cmdline
// or via SetCommandLineOption
const void* flag_ptr; // pointer to the flag's current value (i.e. FLAGS_foo)
};
// Using this inside of a validator is a recipe for a deadlock.
// TODO(wojtekm) Fix locking when validators are running, to make it safe to
// TODO(user) Fix locking when validators are running, to make it safe to
// call validators during ParseAllFlags.
// Also make sure then to uncomment the corresponding unit test in
// commandlineflags_unittest.sh
// gflags_unittest.sh
extern void GetAllFlags(std::vector<CommandLineFlagInfo>* OUTPUT);
// These two are actually defined in commandlineflags_reporting.cc.
// These two are actually defined in gflags_reporting.cc.
extern void ShowUsageWithFlags(const char *argv0); // what --help does
extern void ShowUsageWithFlagsRestrict(const char *argv0, const char *restrict);
@ -202,17 +177,24 @@ extern std::string DescribeOneFlag(const CommandLineFlagInfo& flag);
// Thread-hostile; meant to be called before any threads are spawned.
extern void SetArgv(int argc, const char** argv);
// The following functions are thread-safe as long as SetArgv() is
// only called before any threads start.
extern const std::vector<std::string>& GetArgvs(); // all of argv as a vector
extern const char* GetArgv(); // all of argv as a string
extern const char* GetArgv0(); // only argv0
extern uint32 GetArgvSum(); // simple checksum of argv
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern const std::vector<std::string>& GetArgvs();
extern const char* GetArgv(); // all of argv as a string
extern const char* GetArgv0(); // only argv0
extern uint32 GetArgvSum(); // simple checksum of argv
extern const char* ProgramInvocationName(); // argv0, or "UNKNOWN" if not set
extern const char* ProgramInvocationShortName(); // basename(argv0)
// ProgramUsage() is thread-safe as long as SetUsageMessage() is only
// called before any threads start.
extern const char* ProgramUsage(); // string set by SetUsageMessage()
extern const char* ProgramUsage(); // string set by SetUsageMessage()
// VersionString() is thread-safe as long as SetVersionString() is only
// called before any threads start.
extern const char* VersionString(); // string set by SetVersionString()
// --------------------------------------------------------------------
@ -237,7 +219,7 @@ extern bool GetCommandLineFlagInfo(const char* name,
// if (GetCommandLineFlagInfoOrDie("foo").is_default) ...
extern CommandLineFlagInfo GetCommandLineFlagInfoOrDie(const char* name);
enum FlagSettingMode {
enum GFLAGS_DLL_DECL FlagSettingMode {
// update the flag's value (can call this multiple times).
SET_FLAGS_VALUE,
// update the flag's value, but *only if* it has not yet been updated
@ -259,7 +241,7 @@ enum FlagSettingMode {
// SetCommandLineOption uses set_mode == SET_FLAGS_VALUE (the common case)
extern std::string SetCommandLineOption(const char* name, const char* value);
extern std::string SetCommandLineOptionWithMode(const char* name, const char* value,
FlagSettingMode set_mode);
FlagSettingMode set_mode);
// --------------------------------------------------------------------
@ -280,14 +262,17 @@ extern std::string SetCommandLineOptionWithMode(const char* name, const char* va
// // without worrying about restoring the FLAG values.
// }
//
// Note: This class is marked with __attribute__((unused)) because all the
// Note: This class is marked with ATTRIBUTE_UNUSED because all the
// work is done in the constructor and destructor, so in the standard
// usage example above, the compiler would complain that it's an
// unused variable.
//
// This class is thread-safe.
// This class is thread-safe. However, its destructor writes to
// exactly the set of flags that have changed value during its
// lifetime, so concurrent _direct_ access to those flags
// (i.e. FLAGS_foo instead of {Get,Set}CommandLineOption()) is unsafe.
class FlagSaver {
class GFLAGS_DLL_DECL FlagSaver {
public:
FlagSaver();
~FlagSaver();
@ -311,12 +296,11 @@ extern std::string CommandlineFlagsIntoString();
// Usually where this is used, a FlagSaver should be used instead.
extern bool ReadFlagsFromString(const std::string& flagfilecontents,
const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
bool errors_are_fatal); // uses SET_FLAGS_VALUE
// These let you manually implement --flagfile functionality.
// DEPRECATED.
extern bool AppendFlagsIntoFile(const std::string& filename, const char* prog_name);
extern bool SaveCommandFlags(); // actually defined in google.cc !
extern bool ReadFromFlagsFile(const std::string& filename, const char* prog_name,
bool errors_are_fatal); // uses SET_FLAGS_VALUE
@ -338,7 +322,7 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
// --------------------------------------------------------------------
// The next two functions parse commandlineflags from main():
// The next two functions parse gflags from main():
// Set the "usage" message for this program. For example:
// string usage("This program does nothing. Sample usage:\n");
@ -348,6 +332,12 @@ extern const char *StringFromEnv(const char *varname, const char *defval);
// Thread-hostile; meant to be called before any threads are spawned.
extern void SetUsageMessage(const std::string& usage);
// Sets the version string, which is emitted with --version.
// For instance: SetVersionString("1.3");
// Thread-hostile; meant to be called before any threads are spawned.
extern void SetVersionString(const std::string& version);
// Looks for flags in argv and parses them. Rearranges argv to put
// flags first, or removes them entirely if remove_flags is true.
// If a flag is defined more than once in the command line or flag
@ -355,8 +345,7 @@ extern void SetUsageMessage(const std::string& usage);
// of the first non-flag argument.
// See top-of-file for more details on this function.
#ifndef SWIG // In swig, use ParseCommandLineFlagsScript() instead.
extern uint32 ParseCommandLineFlags(int *argc, char*** argv,
bool remove_flags);
extern uint32 ParseCommandLineFlags(int *argc, char*** argv, bool remove_flags);
#endif
@ -372,10 +361,10 @@ extern uint32 ParseCommandLineFlags(int *argc, char*** argv,
// non-flag argument. (If remove_flags is true, will always return 1.)
extern uint32 ParseCommandLineNonHelpFlags(int *argc, char*** argv,
bool remove_flags);
// This is actually defined in commandlineflags_reporting.cc.
// This is actually defined in gflags_reporting.cc.
// This function is misnamed (it also handles --version, etc.), but
// it's too late to change that now. :-(
extern void HandleCommandLineHelpFlags(); // in commandlineflags_reporting.cc
extern void HandleCommandLineHelpFlags(); // in gflags_reporting.cc
// Allow command line reparsing. Disables the error normally
// generated when an unknown flag is found, since it may be found in a
@ -389,18 +378,17 @@ extern void AllowCommandLineReparsing();
// separate command line argument that follows the flag argument.
// Intended for handling flags from dynamically loaded libraries,
// since their flags are not registered until they are loaded.
// Returns the index (into the original argv) of the first non-flag
// argument. (If remove_flags is true, will always return 1.)
extern uint32 ReparseCommandLineNonHelpFlags();
extern void ReparseCommandLineNonHelpFlags();
// Clean up memory allocated by flags. This is only needed to reduce
// the quantity of "potentially leaked" reports emitted by memory
// debugging tools such as valgrind. It is not required for normal
// operation, or for the perftools heap-checker. It must only be called
// when the process is about to exit, and all threads that might
// access flags are quiescent. Referencing flags after this is called
// will have unexpected consequences. This is not safe to run when
// multiple threads might be running: the function is thread-hostile.
// operation, or for the google perftools heap-checker. It must only
// be called when the process is about to exit, and all threads that
// might access flags are quiescent. Referencing flags after this is
// called will have unexpected consequences. This is not safe to run
// when multiple threads might be running: the function is
// thread-hostile.
extern void ShutDownCommandLineFlags();
@ -441,15 +429,13 @@ extern void ShutDownCommandLineFlags();
// people can't DECLARE_int32 something that they DEFINE_bool'd
// elsewhere.
class FlagRegisterer {
class GFLAGS_DLL_DECL FlagRegisterer {
public:
FlagRegisterer(const char* name, const char* type,
const char* help, const char* filename,
void* current_storage, void* defvalue_storage);
};
extern bool FlagsTypeWarn(const char *name);
// If your application #defines STRIP_FLAG_HELP to a non-zero value
// before #including this file, we remove the help message from the
// binary file. This can reduce the size of the resulting binary
@ -463,7 +449,8 @@ extern const char kStrippedFlagHelp[];
#if defined(STRIP_FLAG_HELP) && STRIP_FLAG_HELP > 0
// Need this construct to avoid the 'defined but not used' warning.
#define MAYBE_STRIPPED_HELP(txt) (false ? (txt) : ::google::kStrippedFlagHelp)
#define MAYBE_STRIPPED_HELP(txt) \
(false ? (txt) : ::google::kStrippedFlagHelp)
#else
#define MAYBE_STRIPPED_HELP(txt) txt
#endif
@ -479,21 +466,16 @@ extern const char kStrippedFlagHelp[];
// FLAGS_no<name>. This serves the second purpose of assuring a
// compile error if someone tries to define a flag named no<name>
// which is illegal (--foo and --nofoo both affect the "foo" flag).
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static ::google::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
#define DECLARE_VARIABLE(type, shorttype, name) \
namespace fL##shorttype { \
extern type FLAGS_##name; \
} \
#define DEFINE_VARIABLE(type, shorttype, name, value, help) \
namespace fL##shorttype { \
static const type FLAGS_nono##name = value; \
/* We always want to export defined variables, dll or no */ \
GFLAGS_DLL_DEFINE_FLAG type FLAGS_##name = FLAGS_nono##name; \
type FLAGS_no##name = FLAGS_nono##name; \
static ::google::FlagRegisterer o_##name( \
#name, #type, MAYBE_STRIPPED_HELP(help), __FILE__, \
&FLAGS_##name, &FLAGS_no##name); \
} \
using fL##shorttype::FLAGS_##name
// For DEFINE_bool, we want to do the extra check that the passed-in
@ -503,34 +485,39 @@ extern const char kStrippedFlagHelp[];
// We'll use 'sizeof(IsBool(val))' to distinguish. This code requires
// that the compiler have different sizes for bool & double. Since
// this is not guaranteed by the standard, we check it with a
// compile-time assert (msg[-1] will give a compile-time error).
// COMPILE_ASSERT.
namespace fLB {
struct CompileAssert {};
typedef CompileAssert expected_sizeof_double_neq_sizeof_bool[
(sizeof(double) != sizeof(bool)) ? 1 : -1];
template<typename From> double IsBoolFlag(const From& from);
bool IsBoolFlag(bool from);
template<typename From> double GFLAGS_DLL_DECL IsBoolFlag(const From& from);
GFLAGS_DLL_DECL bool IsBoolFlag(bool from);
} // namespace fLB
#define DECLARE_bool(name) DECLARE_VARIABLE(bool, B, name)
#define DEFINE_bool(name, val, txt) \
namespace fLB { \
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
// Here are the actual DEFINE_*-macros. The respective DECLARE_*-macros
// are in a separate include, gflags_declare.h, for reducing
// the physical transitive size for DECLARE use.
#define DEFINE_bool(name, val, txt) \
namespace fLB { \
typedef ::fLB::CompileAssert FLAG_##name##_value_is_not_a_bool[ \
(sizeof(::fLB::IsBoolFlag(val)) != sizeof(double)) ? 1 : -1]; \
} \
} \
DEFINE_VARIABLE(bool, B, name, val, txt)
#define DECLARE_int32(name) DECLARE_VARIABLE(::google::int32, I, name)
#define DEFINE_int32(name,val,txt) DEFINE_VARIABLE(::google::int32, I, name, val, txt)
#define DEFINE_int32(name, val, txt) \
DEFINE_VARIABLE(::google::int32, I, \
name, val, txt)
#define DECLARE_int64(name) DECLARE_VARIABLE(::google::int64, I64, name)
#define DEFINE_int64(name,val,txt) DEFINE_VARIABLE(::google::int64, I64, name, val, txt)
#define DEFINE_int64(name, val, txt) \
DEFINE_VARIABLE(::google::int64, I64, \
name, val, txt)
#define DECLARE_uint64(name) DECLARE_VARIABLE(::google::uint64, U64, name)
#define DEFINE_uint64(name,val,txt) DEFINE_VARIABLE(::google::uint64, U64, name, val, txt)
#define DEFINE_uint64(name,val, txt) \
DEFINE_VARIABLE(::google::uint64, U64, \
name, val, txt)
#define DECLARE_double(name) DECLARE_VARIABLE(double, D, name)
#define DEFINE_double(name, val, txt) DEFINE_VARIABLE(double, D, name, val, txt)
#define DEFINE_double(name, val, txt) \
DEFINE_VARIABLE(double, D, name, val, txt)
// Strings are trickier, because they're not a POD, so we can't
// construct them at static-initialization time (instead they get
@ -540,11 +527,6 @@ bool IsBoolFlag(bool from);
// into it later. It's not perfect, but the best we can do.
namespace fLS {
// The meaning of "string" might be different between now and when the
// macros below get invoked (e.g., if someone is experimenting with
// other string implementations that get defined after this file is
// included). Save the current meaning now and use it in the macros.
typedef std::string clstring;
inline clstring* dont_pass0toDEFINE_string(char *stringspot,
const char *value) {
@ -558,9 +540,6 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
int value);
} // namespace fLS
#define DECLARE_string(name) namespace fLS { extern ::fLS::clstring& FLAGS_##name; } \
using fLS::FLAGS_##name
// We need to define a var named FLAGS_no##name so people don't define
// --string and --nostring. And we need a temporary place to put val
// so we don't have to evaluate it twice. Two great needs that go
@ -575,10 +554,10 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
clstring* const FLAGS_no##name = ::fLS:: \
dont_pass0toDEFINE_string(s_##name[0].s, \
val); \
static ::google::FlagRegisterer o_##name( \
static ::google::FlagRegisterer o_##name( \
#name, "string", MAYBE_STRIPPED_HELP(txt), __FILE__, \
s_##name[0].s, new (s_##name[1].s) clstring(*FLAGS_no##name)); \
extern clstring& FLAGS_##name; \
extern GFLAGS_DLL_DEFINE_FLAG clstring& FLAGS_##name; \
using fLS::FLAGS_##name; \
clstring& FLAGS_##name = *FLAGS_no##name; \
} \
@ -586,4 +565,4 @@ inline clstring* dont_pass0toDEFINE_string(char *stringspot,
#endif // SWIG
#endif // GOOGLE_GFLAGS_H_
#endif // BASE_COMMANDLINEFLAGS_H_

@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Dave Nicponski
//
// Implement helpful bash-style command line flag completions
//
@ -88,8 +88,8 @@
// file would be (your path to gflags_completions.sh file may differ):
/*
$ complete -o bashdefault -o default -o nospace -C \
'/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
$ complete -o bashdefault -o default -o nospace -C \
'/home/build/eng/bash/bash_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
@ -109,13 +109,22 @@ $ complete -o bashdefault -o default -o nospace -C \
// produce the expected completion output.
#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
#define GOOGLE_GFLAGS_COMPLETIONS_H_
#ifndef BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
#define BASE_COMMANDLINEFLAGS_COMPLETIONS_H_
// Annoying stuff for windows -- makes sure clients can import these functions
//
// NOTE: all functions below MUST have an explicit 'extern' before
// them. Our automated opensourcing tools use this as a signal to do
// appropriate munging for windows, which needs to add GFLAGS_DLL_DECL.
//
#define GFLAGS_DLL_DECL /* rewritten to be non-empty in windows dir */
namespace google {
void HandleCommandLineCompletions(void);
extern void HandleCommandLineCompletions(void);
}
#endif // GOOGLE_GFLAGS_COMPLETIONS_H_
#endif // BASE_COMMANDLINEFLAGS_COMPLETIONS_H_

@ -0,0 +1,112 @@
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Revamped and reorganized by Craig Silverstein
//
// This is the file that should be included by any file which declares
// command line flag.
#ifndef BASE_COMMANDLINEFLAGS_DECLARE_H_
#define BASE_COMMANDLINEFLAGS_DECLARE_H_
#include <string>
#if 1
#include <stdint.h> // the normal place uint16_t is defined
#endif
#if 1
#include <sys/types.h> // the normal place u_int16_t is defined
#endif
#if 1
#include <inttypes.h> // a third place for uint16_t or u_int16_t
#endif
namespace google {
#if 1 // the C99 format
typedef int32_t int32;
typedef uint32_t uint32;
typedef int64_t int64;
typedef uint64_t uint64;
#elif 1 // the BSD format
typedef int32_t int32;
typedef u_int32_t uint32;
typedef int64_t int64;
typedef u_int64_t uint64;
#elif 0 // the windows (vc7) format
typedef __int32 int32;
typedef unsigned __int32 uint32;
typedef __int64 int64;
typedef unsigned __int64 uint64;
#else
#error Do not know how to define a 32-bit integer quantity on your system
#endif
}
#define GFLAGS_DLL_DECLARE_FLAG /* rewritten to be non-empty in windows dir */
namespace fLS {
// The meaning of "string" might be different between now and when the
// macros below get invoked (e.g., if someone is experimenting with
// other string implementations that get defined after this file is
// included). Save the current meaning now and use it in the macros.
typedef std::string clstring;
}
#define DECLARE_VARIABLE(type, shorttype, name) \
/* We always want to import declared variables, dll or no */ \
namespace fL##shorttype { extern GFLAGS_DLL_DECLARE_FLAG type FLAGS_##name; } \
using fL##shorttype::FLAGS_##name
#define DECLARE_bool(name) \
DECLARE_VARIABLE(bool, B, name)
#define DECLARE_int32(name) \
DECLARE_VARIABLE(::google::int32, I, name)
#define DECLARE_int64(name) \
DECLARE_VARIABLE(::google::int64, I64, name)
#define DECLARE_uint64(name) \
DECLARE_VARIABLE(::google::uint64, U64, name)
#define DECLARE_double(name) \
DECLARE_VARIABLE(double, D, name)
#define DECLARE_string(name) \
namespace fLS { \
using ::fLS::clstring; \
extern GFLAGS_DLL_DECLARE_FLAG ::fLS::clstring& FLAGS_##name; \
} \
using fLS::FLAGS_##name
#endif // BASE_COMMANDLINEFLAGS_DECLARE_H_

@ -28,8 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Dave Nicponski
//
// Bash-style command line flag completion for C++ binaries
//
// This module implements bash-style completions. It achieves this
@ -58,7 +57,12 @@
#include <utility>
#include <vector>
#include "gflags.h"
#include "gflags/gflags.h"
#include "util.h"
using std::set;
using std::string;
using std::vector;
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
@ -74,11 +78,6 @@ DEFINE_int32(tab_completion_columns, 80,
_START_GOOGLE_NAMESPACE_
namespace {
using std::set;
using std::string;
using std::vector;
// Function prototypes and Type forward declarations. Code may be
// more easily understood if it is roughly ordered according to
// control flow, rather than by C's "declare before use" ordering
@ -210,12 +209,12 @@ static void PrintFlagCompletionInfo(void) {
&canonical_token,
&options);
//VLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
DVLOG(1) << "Identified canonical_token: '" << canonical_token << "'";
vector<CommandLineFlagInfo> all_flags;
set<const CommandLineFlagInfo *> matching_flags;
GetAllFlags(&all_flags);
//VLOG(2) << "Found " << all_flags.size() << " flags overall";
DVLOG(2) << "Found " << all_flags.size() << " flags overall";
string longest_common_prefix;
FindMatchingFlags(
@ -224,28 +223,28 @@ static void PrintFlagCompletionInfo(void) {
canonical_token,
&matching_flags,
&longest_common_prefix);
//VLOG(1) << "Identified " << matching_flags.size() << " matching flags";
//VLOG(1) << "Identified " << longest_common_prefix
// << " as longest common prefix.";
DVLOG(1) << "Identified " << matching_flags.size() << " matching flags";
DVLOG(1) << "Identified " << longest_common_prefix
<< " as longest common prefix.";
if (longest_common_prefix.size() > canonical_token.size()) {
// There's actually a shared common prefix to all matching flags,
// so may as well output that and quit quickly.
//VLOG(1) << "The common prefix '" << longest_common_prefix
// << "' was longer than the token '" << canonical_token
// << "'. Returning just this prefix for completion.";
DVLOG(1) << "The common prefix '" << longest_common_prefix
<< "' was longer than the token '" << canonical_token
<< "'. Returning just this prefix for completion.";
fprintf(stdout, "--%s", longest_common_prefix.c_str());
return;
}
if (matching_flags.empty()) {
//VLOG(1) << "There were no matching flags, returning nothing.";
VLOG(1) << "There were no matching flags, returning nothing.";
return;
}
string module;
string package_dir;
TryFindModuleAndPackageDir(all_flags, &module, &package_dir);
//VLOG(1) << "Identified module: '" << module << "'";
//VLOG(1) << "Identified package_dir: '" << package_dir << "'";
DVLOG(1) << "Identified module: '" << module << "'";
DVLOG(1) << "Identified package_dir: '" << package_dir << "'";
NotableFlags notable_flags;
CategorizeAllMatchingFlags(
@ -254,12 +253,12 @@ static void PrintFlagCompletionInfo(void) {
module,
package_dir,
&notable_flags);
//VLOG(2) << "Categorized matching flags:";
//VLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
//VLOG(2) << " module: " << notable_flags.module_flags.size();
//VLOG(2) << " package: " << notable_flags.package_flags.size();
//VLOG(2) << " most common: " << notable_flags.most_common_flags.size();
//VLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
DVLOG(2) << "Categorized matching flags:";
DVLOG(2) << " perfect_match: " << notable_flags.perfect_match_flag.size();
DVLOG(2) << " module: " << notable_flags.module_flags.size();
DVLOG(2) << " package: " << notable_flags.package_flags.size();
DVLOG(2) << " most common: " << notable_flags.most_common_flags.size();
DVLOG(2) << " subpackage: " << notable_flags.subpackage_flags.size();
vector<string> completions;
FinalizeCompletionOutput(
@ -271,13 +270,13 @@ static void PrintFlagCompletionInfo(void) {
if (options.force_no_update)
completions.push_back("~");
//VLOG(1) << "Finalized with " << completions.size()
// << " chosen completions";
DVLOG(1) << "Finalized with " << completions.size()
<< " chosen completions";
for (vector<string>::const_iterator it = completions.begin();
it != completions.end();
++it) {
//VLOG(9) << " Completion entry: '" << *it << "'";
DVLOG(9) << " Completion entry: '" << *it << "'";
fprintf(stdout, "%s\n", it->c_str());
}
}
@ -397,7 +396,7 @@ static bool DoesSingleFlagMatch(
flag.filename.find(match_token) != string::npos)
return true;
// TODO(daven): All searches should probably be case-insensitive
// TODO(user): All searches should probably be case-insensitive
// (especially this one...)
if (options.flag_description_substring_search &&
flag.description.find(match_token) != string::npos)
@ -426,8 +425,8 @@ static void CategorizeAllMatchingFlags(
all_matches.begin();
it != all_matches.end();
++it) {
//VLOG(2) << "Examining match '" << (*it)->name << "'";
//VLOG(7) << " filename: '" << (*it)->filename << "'";
DVLOG(2) << "Examining match '" << (*it)->name << "'";
DVLOG(7) << " filename: '" << (*it)->filename << "'";
string::size_type pos = string::npos;
if (!package_dir.empty())
pos = (*it)->filename.find(package_dir);
@ -440,36 +439,34 @@ static void CategorizeAllMatchingFlags(
if ((*it)->name == search_token) {
// Exact match on some flag's name
notable_flags->perfect_match_flag.insert(*it);
//VLOG(3) << "Result: perfect match";
DVLOG(3) << "Result: perfect match";
} else if (!module.empty() && (*it)->filename == module) {
// Exact match on module filename
notable_flags->module_flags.insert(*it);
//VLOG(3) << "Result: module match";
DVLOG(3) << "Result: module match";
} else if (!package_dir.empty() &&
pos != string::npos && slash == string::npos) {
// In the package, since there was no slash after the package portion
notable_flags->package_flags.insert(*it);
//VLOG(3) << "Result: package match";
DVLOG(3) << "Result: package match";
} else if (false) {
// In the list of the XXX most commonly supplied flags overall
// TODO(daven): Compile this list.
//VLOG(3) << "Result: most-common match";
// TODO(user): Compile this list.
DVLOG(3) << "Result: most-common match";
} else if (!package_dir.empty() &&
pos != string::npos && slash != string::npos) {
// In a subdirectory of the package
notable_flags->subpackage_flags.insert(*it);
//VLOG(3) << "Result: subpackage match";
DVLOG(3) << "Result: subpackage match";
}
//VLOG(3) << "Result: not special match";
DVLOG(3) << "Result: not special match";
}
}
static void PushNameWithSuffix(vector<string>* suffixes, const char* suffix) {
string s("/");
s += ProgramInvocationShortName();
s += suffix;
suffixes->push_back(s);
suffixes->push_back(
StringPrintf("/%s%s", ProgramInvocationShortName(), suffix));
}
static void TryFindModuleAndPackageDir(
@ -480,7 +477,7 @@ static void TryFindModuleAndPackageDir(
package_dir->clear();
vector<string> suffixes;
// TODO(daven): There's some inherant ambiguity here - multiple directories
// TODO(user): There's some inherant ambiguity here - multiple directories
// could share the same trailing folder and file structure (and even worse,
// same file names), causing us to be unsure as to which of the two is the
// actual package for this binary. In this case, we'll arbitrarily choose.
@ -499,7 +496,7 @@ static void TryFindModuleAndPackageDir(
for (vector<string>::const_iterator suffix = suffixes.begin();
suffix != suffixes.end();
++suffix) {
// TODO(daven): Make sure the match is near the end of the string
// TODO(user): Make sure the match is near the end of the string
if (it->filename.find(*suffix) != string::npos) {
*module = it->filename;
string::size_type sep = it->filename.rfind(PATH_SEPARATOR);
@ -696,12 +693,14 @@ static void OutputSingleGroupWithLimit(
static string GetShortFlagLine(
const string &line_indentation,
const CommandLineFlagInfo &info) {
string prefix =
line_indentation + "--" + info.name + " [" +
(info.type == "string" ?
("'" + info.default_value + "'") :
info.default_value)
+ "] ";
string prefix;
bool is_string = (info.type == "string");
SStringPrintf(&prefix, "%s--%s [%s%s%s] ",
line_indentation.c_str(),
info.name.c_str(),
(is_string ? "'" : ""),
info.default_value.c_str(),
(is_string ? "'" : ""));
int remainder =
FLAGS_tab_completion_columns - static_cast<int>(prefix.size());
string suffix;
@ -731,8 +730,12 @@ static string GetLongFlagLine(
static const char kNewlineWithIndent[] = "\n ";
output.replace(output.find(" type:"), 1, string(kNewlineWithIndent));
output.replace(output.find(" default:"), 1, string(kNewlineWithIndent));
output = line_indentation + " Details for '--" + info.name + "':\n" +
output + " defined: " + info.filename;
output = StringPrintf("%s Details for '--%s':\n"
"%s defined: %s",
line_indentation.c_str(),
info.name.c_str(),
output.c_str(),
info.filename.c_str());
// Eliminate any doubled newlines that crept in. Specifically, if
// DescribeOneFlag() decided to break the line just before "type"
@ -759,7 +762,7 @@ static string GetLongFlagLine(
void HandleCommandLineCompletions(void) {
if (FLAGS_tab_completion_word.empty()) return;
PrintFlagCompletionInfo();
exit(0);
gflags_exitfunc(0);
}
_END_GOOGLE_NAMESPACE_

@ -1,4 +1,4 @@
// Copyright (c) 2006, Google Inc.
// Copyright (c) 1999, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@ -28,7 +28,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
// Author: Ray Sidney
//
// Revamped and reorganized by Craig Silverstein
//
// This file contains code for handling the 'reporting' flags. These
@ -40,7 +40,7 @@
// HandleCommandLineHelpFlags(). (Well, actually, ShowUsageWithFlags(),
// ShowUsageWithFlagsRestrict(), and DescribeOneFlag() can be called
// externally too, but there's little need for it.) These are all
// declared in the main commandlineflags.h header file.
// declared in the main gflags.h header file.
//
// HandleCommandLineHelpFlags() will check what 'reporting' flags have
// been defined, if any -- the "help" part of the function name is a
@ -55,14 +55,15 @@
#include <assert.h>
#include <string>
#include <vector>
#include "gflags.h"
#include "gflags_completions.h"
#include "gflags/gflags.h"
#include "gflags/gflags_completions.h"
#include "util.h"
#ifndef PATH_SEPARATOR
#define PATH_SEPARATOR '/'
#endif
// The 'reporting' flags. They all call exit().
// The 'reporting' flags. They all call gflags_exitfunc().
DEFINE_bool(help, false,
"show help on all flags [tip: all flags can have two dashes]");
DEFINE_bool(helpfull, false,
@ -85,11 +86,12 @@ _START_GOOGLE_NAMESPACE_
using std::string;
using std::vector;
// --------------------------------------------------------------------
// DescribeOneFlag()
// DescribeOneFlagInXML()
// Routines that pretty-print info about a flag. These use
// a CommandLineFlagInfo, which is the way the commandlineflags
// a CommandLineFlagInfo, which is the way the gflags
// API exposes static info about a flag.
// --------------------------------------------------------------------
@ -114,17 +116,19 @@ static string PrintStringFlagsWithQuotes(const CommandLineFlagInfo& flag,
const char* c_string = (current ? flag.current_value.c_str() :
flag.default_value.c_str());
if (strcmp(flag.type.c_str(), "string") == 0) { // add quotes for strings
return text + ": \"" + c_string + "\"";
return StringPrintf("%s: \"%s\"", text.c_str(), c_string);
} else {
return text + ": " + c_string;
return StringPrintf("%s: %s", text.c_str(), c_string);
}
}
// Create a descriptive string for a flag.
// Goes to some trouble to make pretty line breaks.
string DescribeOneFlag(const CommandLineFlagInfo& flag) {
string main_part = (string(" -") + flag.name +
" (" + flag.description + ')');
string main_part;
SStringPrintf(&main_part, " -%s (%s)",
flag.name.c_str(),
flag.description.c_str());
const char* c_string = main_part.c_str();
int chars_left = static_cast<int>(main_part.length());
string final_string = "";
@ -164,7 +168,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
}
if (*c_string == '\0')
break;
final_string += "\n ";
StringAppendF(&final_string, "\n ");
chars_in_line = 6;
}
@ -173,7 +177,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
// The listed default value will be the actual default from the flag
// definition in the originating source file, unless the value has
// subsequently been modified using SetCommandLineOptionWithMode() with mode
// SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before initializing.
// SET_FLAGS_DEFAULT, or by setting FLAGS_foo = bar before ParseCommandLineFlags().
AddString(PrintStringFlagsWithQuotes(flag, "default", false), &final_string,
&chars_in_line);
if (!flag.is_default) {
@ -181,7 +185,7 @@ string DescribeOneFlag(const CommandLineFlagInfo& flag) {
&final_string, &chars_in_line);
}
final_string += '\n';
StringAppendF(&final_string, "\n");
return final_string;
}
@ -196,15 +200,10 @@ static string XMLText(const string& txt) {
}
static void AddXMLTag(string* r, const char* tag, const string& txt) {
*r += ('<');
*r += (tag);
*r += ('>');
*r += (XMLText(txt));
*r += ("</");
*r += (tag);
*r += ('>');
StringAppendF(r, "<%s>%s</%s>", tag, XMLText(txt).c_str(), tag);
}
static string DescribeOneFlagInXML(const CommandLineFlagInfo& flag) {
// The file and flagname could have been attributes, but default
// and meaning need to avoid attribute normalization. This way it
@ -265,9 +264,9 @@ static bool FileMatchesSubstring(const string& filename,
// Show help for every filename which matches any of the target substrings.
// If substrings is empty, shows help for every file. If a flag's help message
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1' before
// including gflags/gflags.h), then this flag will not be displayed by
// '--help' and its variants.
// has been stripped (e.g. by adding '#define STRIP_FLAG_HELP 1'
// before including gflags/gflags.h), then this flag will not be displayed
// by '--help' and its variants.
static void ShowUsageWithFlagsMatching(const char *argv0,
const vector<string> &substrings) {
fprintf(stdout, "%s: %s\n", Basename(argv0), ProgramUsage());
@ -347,10 +346,13 @@ static void ShowXMLOfFlags(const char *prog_name) {
// --------------------------------------------------------------------
static void ShowVersion() {
fprintf(stdout, "%s\n", ProgramInvocationShortName());
// TODO: add other stuff, like a timestamp, who built it, what
// target they built, etc.
const char* version_string = VersionString();
if (version_string && *version_string) {
fprintf(stdout, "%s version %s\n",
ProgramInvocationShortName(), version_string);
} else {
fprintf(stdout, "%s\n", ProgramInvocationShortName());
}
# if !defined(NDEBUG)
fprintf(stdout, "Debug build (NDEBUG not #defined)\n");
# endif
@ -375,7 +377,6 @@ static void AppendPrognameStrings(vector<string>* substrings,
void HandleCommandLineHelpFlags() {
const char* progname = ProgramInvocationShortName();
extern void (*commandlineflags_exitfunc)(int); // in gflags.cc
HandleCommandLineCompletions();
@ -386,21 +387,21 @@ void HandleCommandLineHelpFlags() {
// show only flags related to this binary:
// E.g. for fileutil.cc, want flags containing ... "/fileutil." cc
ShowUsageWithFlagsMatching(progname, substrings);
commandlineflags_exitfunc(1); // almost certainly exit()
gflags_exitfunc(1);
} else if (FLAGS_help || FLAGS_helpfull) {
// show all options
ShowUsageWithFlagsRestrict(progname, ""); // empty restrict
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (!FLAGS_helpon.empty()) {
string restrict = "/" + FLAGS_helpon + ".";
ShowUsageWithFlagsRestrict(progname, restrict.c_str());
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (!FLAGS_helpmatch.empty()) {
ShowUsageWithFlagsRestrict(progname, FLAGS_helpmatch.c_str());
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_helppackage) {
// Shows help for all files in the same directory as main(). We
@ -419,27 +420,27 @@ void HandleCommandLineHelpFlags() {
const string package = Dirname(flag->filename) + "/";
if (package != last_package) {
ShowUsageWithFlagsRestrict(progname, package.c_str());
VLOG(7) << "Found package: " << package;
if (!last_package.empty()) { // means this isn't our first pkg
fprintf(stderr, "WARNING: Multiple packages contain a file=%s\n",
progname);
LOG(WARNING) << "Multiple packages contain a file=" << progname;
}
last_package = package;
}
}
if (last_package.empty()) { // never found a package to print
fprintf(stderr, "WARNING: Unable to find a package for file=%s\n",
progname);
LOG(WARNING) << "Unable to find a package for file=" << progname;
}
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_helpxml) {
ShowXMLOfFlags(progname);
commandlineflags_exitfunc(1);
gflags_exitfunc(1);
} else if (FLAGS_version) {
ShowVersion();
// Unlike help, we may be asking for version in a script, so return 0
commandlineflags_exitfunc(0);
gflags_exitfunc(0);
}
}

@ -28,7 +28,6 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Craig Silverstein.
//
// A simple mutex wrapper, supporting locks and read-write locks.
// You should assume the locks are *not* re-entrant.
@ -117,7 +116,12 @@
#if defined(NO_THREADS)
typedef int MutexType; // to keep a lock-count
#elif defined(_WIN32) || defined(__CYGWIN32__) || defined(__CYGWIN64__)
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN // We only need minimal includes
# endif
# ifndef NOMINMAX
# define NOMINMAX // Don't want windows to override min()/max()
# endif
# ifdef GMUTEX_TRYLOCK
// We need Windows NT or later for TryEnterCriticalSection(). If you
// don't need that functionality, you can remove these _WIN32_WINNT
@ -134,7 +138,10 @@
// *does* cause problems for FreeBSD, or MacOSX, but isn't needed
// for locking there.)
# ifdef __linux__
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# if _XOPEN_SOURCE < 500 // including not being defined at all
# undef _XOPEN_SOURCE
# define _XOPEN_SOURCE 500 // may be needed to get the rwlock calls
# endif
# endif
# include <pthread.h>
typedef pthread_rwlock_t MutexType;

339
extern/libmv/third_party/gflags/util.h vendored Normal file

@ -0,0 +1,339 @@
// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---
//
// Some generically useful utility routines that in google-land would
// be their own projects. We make a shortened version here.
#ifndef GFLAGS_UTIL_H_
#define GFLAGS_UTIL_H_
#include <assert.h>
#include "config.h"
#ifdef HAVE_INTTYPES_H
# include <inttypes.h>
#endif
#include <stdarg.h> // for va_*
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif // for mkdir()
_START_GOOGLE_NAMESPACE_
// This is used for unittests for death-testing. It is defined in gflags.cc.
extern GFLAGS_DLL_DECL void (*gflags_exitfunc)(int);
// Work properly if either strtoll or strtoq is on this system
#ifdef HAVE_STRTOLL
# define strto64 strtoll
# define strtou64 strtoull
#elif HAVE_STRTOQ
# define strto64 strtoq
# define strtou64 strtouq
#else
// Neither strtoll nor strtoq are defined. I hope strtol works!
# define strto64 strtol
# define strtou64 strtoul
#endif
// If we have inttypes.h, it will have defined PRId32/etc for us. If
// not, take our best guess.
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRId64
# define PRId64 "lld"
#endif
#ifndef PRIu64
# define PRIu64 "llu"
#endif
typedef signed char int8;
typedef unsigned char uint8;
// -- utility macros ---------------------------------------------------------
template <bool> struct CompileAssert {};
#define COMPILE_ASSERT(expr, msg) \
typedef CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
// Returns the number of elements in an array.
#define arraysize(arr) (sizeof(arr)/sizeof(*(arr)))
// -- logging and testing ---------------------------------------------------
// For now, we ignore the level for logging, and don't show *VLOG's at
// all, except by hand-editing the lines below
#define LOG(level) std::cerr
#define VLOG(level) if (true) {} else std::cerr
#define DVLOG(level) if (true) {} else std::cerr
// CHECK dies with a fatal error if condition is not true. It is *not*
// controlled by NDEBUG, so the check will be executed regardless of
// compilation mode. Therefore, it is safe to do things like:
// CHECK(fp->Write(x) == 4)
// We allow stream-like objects after this for debugging, but they're ignored.
#define EXPECT_TRUE(condition) \
if (true) { \
if (!(condition)) { \
fprintf(stderr, "Check failed: %s\n", #condition); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_OP(op, val1, val2) \
if (true) { \
if (!((val1) op (val2))) { \
fprintf(stderr, "Check failed: %s %s %s\n", #val1, #op, #val2); \
exit(1); \
} \
} else std::cerr << ""
#define EXPECT_EQ(val1, val2) EXPECT_OP(==, val1, val2)
#define EXPECT_NE(val1, val2) EXPECT_OP(!=, val1, val2)
#define EXPECT_LE(val1, val2) EXPECT_OP(<=, val1, val2)
#define EXPECT_LT(val1, val2) EXPECT_OP(< , val1, val2)
#define EXPECT_GE(val1, val2) EXPECT_OP(>=, val1, val2)
#define EXPECT_GT(val1, val2) EXPECT_OP(> , val1, val2)
#define EXPECT_FALSE(cond) EXPECT_TRUE(!(cond))
// C99 declares isnan and isinf should be macros, so the #ifdef test
// should be reliable everywhere. Of course, it's not, but these
// are testing pertty marginal functionality anyway, so it's ok to
// not-run them even in situations they might, with effort, be made to work.
#ifdef isnan // Some compilers, like sun's for Solaris 10, don't define this
#define EXPECT_NAN(arg) \
do { \
if (!isnan(arg)) { \
fprintf(stderr, "Check failed: isnan(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_NAN(arg)
#endif
#ifdef isinf // Some compilers, like sun's for Solaris 10, don't define this
#define EXPECT_INF(arg) \
do { \
if (!isinf(arg)) { \
fprintf(stderr, "Check failed: isinf(%s)\n", #arg); \
exit(1); \
} \
} while (0)
#else
#define EXPECT_INF(arg)
#endif
#define EXPECT_DOUBLE_EQ(val1, val2) \
do { \
if (((val1) < (val2) - 0.001 || (val1) > (val2) + 0.001)) { \
fprintf(stderr, "Check failed: %s == %s\n", #val1, #val2); \
exit(1); \
} \
} while (0)
#define EXPECT_STREQ(val1, val2) \
do { \
if (strcmp((val1), (val2)) != 0) { \
fprintf(stderr, "Check failed: streq(%s, %s)\n", #val1, #val2); \
exit(1); \
} \
} while (0)
// Call this in a .cc file where you will later call RUN_ALL_TESTS in main().
#define TEST_INIT \
static std::vector<void (*)()> g_testlist; /* the tests to run */ \
static int RUN_ALL_TESTS() { \
std::vector<void (*)()>::const_iterator it; \
for (it = g_testlist.begin(); it != g_testlist.end(); ++it) { \
(*it)(); /* The test will error-exit if there's a problem. */ \
} \
fprintf(stderr, "\nPassed %d tests\n\nPASS\n", \
static_cast<int>(g_testlist.size())); \
return 0; \
}
// Note that this macro uses a FlagSaver to keep tests isolated.
#define TEST(a, b) \
struct Test_##a##_##b { \
Test_##a##_##b() { g_testlist.push_back(&Run); } \
static void Run() { \
FlagSaver fs; \
fprintf(stderr, "Running test %s/%s\n", #a, #b); \
RunTest(); \
} \
static void RunTest(); \
}; \
static Test_##a##_##b g_test_##a##_##b; \
void Test_##a##_##b::RunTest()
// This is a dummy class that eases the google->opensource transition.
namespace testing {
class Test {};
}
// Call this in a .cc file where you will later call EXPECT_DEATH
#define EXPECT_DEATH_INIT \
static bool g_called_exit; \
static void CalledExit(int) { g_called_exit = true; }
#define EXPECT_DEATH(fn, msg) \
do { \
g_called_exit = false; \
gflags_exitfunc = &CalledExit; \
fn; \
gflags_exitfunc = &exit; /* set back to its default */ \
if (!g_called_exit) { \
fprintf(stderr, "Function didn't die (%s): %s\n", msg, #fn); \
exit(1); \
} \
} while (0)
#define GTEST_HAS_DEATH_TEST 1
// -- path routines ----------------------------------------------------------
// Tries to create the directory path as a temp-dir. If it fails,
// changes path to some directory it *can* create.
#if defined(__MINGW32__)
#include <io.h>
inline void MakeTmpdir(std::string* path) {
// I had trouble creating a directory in /tmp from mingw
*path = "./gflags_unittest_testdir";
mkdir(path->c_str()); // mingw has a weird one-arg mkdir
}
#elif defined(_MSC_VER)
#include <direct.h>
#include <windows.h>
inline void MakeTmpdir(std::string* path) {
char tmppath_buffer[1024];
int tmppath_len = GetTempPathA(sizeof(tmppath_buffer), tmppath_buffer);
assert(tmppath_len > 0 && tmppath_len < sizeof(tmppath_buffer));
assert(tmppath_buffer[tmppath_len - 1] == '\\'); // API guarantees it
*path = std::string(tmppath_buffer) + "gflags_unittest_testdir";
_mkdir(path->c_str());
}
// Windows is missing random bits like strcasecmp, strtoll, strtoull, and
// snprintf in the usual locations. Put them somewhere sensible.
//
// TODO(keir): Get the upstream Windows port and use that instead.
#define snprintf _snprintf
#undef strtoint64
#define strtoint64 _strtoi64
#undef strtouint64
#define strtouint64 _strtoui64
#define strcasecmp _stricmp
#define va_copy(dst, src) ((dst) = (src))
#define strto64 _strtoi64
#define strtou64 _strtoui64
#else
inline void MakeTmpdir(std::string* path) {
mkdir(path->c_str(), 0755);
}
#endif
// -- string routines --------------------------------------------------------
inline void InternalStringPrintf(std::string* output, const char* format,
va_list ap) {
char space[128]; // try a small buffer and hope it fits
// It's possible for methods that use a va_list to invalidate
// the data in it upon use. The fix is to make a copy
// of the structure before using it and use that copy instead.
va_list backup_ap;
va_copy(backup_ap, ap);
int bytes_written = vsnprintf(space, sizeof(space), format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (bytes_written < sizeof(space))) {
output->append(space, bytes_written);
return;
}
// Repeatedly increase buffer size until it fits.
int length = sizeof(space);
while (true) {
if (bytes_written < 0) {
// Older snprintf() behavior. :-( Just try doubling the buffer size
length *= 2;
} else {
// We need exactly "bytes_written+1" characters
length = bytes_written+1;
}
char* buf = new char[length];
// Restore the va_list before we use it again
va_copy(backup_ap, ap);
bytes_written = vsnprintf(buf, length, format, backup_ap);
va_end(backup_ap);
if ((bytes_written >= 0) && (bytes_written < length)) {
output->append(buf, bytes_written);
delete[] buf;
return;
}
delete[] buf;
}
}
// Clears output before writing to it.
inline void SStringPrintf(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
output->clear();
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline void StringAppendF(std::string* output, const char* format, ...) {
va_list ap;
va_start(ap, format);
InternalStringPrintf(output, format, ap);
va_end(ap);
}
inline std::string StringPrintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
std::string output;
InternalStringPrintf(&output, format, ap);
va_end(ap);
return output;
}
_END_GOOGLE_NAMESPACE_
#endif // GFLAGS_UTIL_H_

@ -1,3 +1,13 @@
2012-01-12 Google Inc. <opensource@google.com>
* google-glog: version 0.3.2
* Clang support.
* Demangler and stacktrace improvement for newer GCCs.
* Now fork(2) doesn't mess up log files.
* Make valgrind happier.
* Reduce warnings for more -W options.
* Provide a workaround for ERROR defined by windows.h.
2010-06-15 Google Inc. <opensource@google.com>
* google-glog: version 0.3.1

@ -1,38 +1,24 @@
Project: Google Logging
URL: http://code.google.com/p/google-glog/
License: New BSD
Upstream version: 0.3.1
Upstream version: 0.3.2
Local modifications:
Upgrading Notes
* Had to change #include <gflags/gflags.h> to #include "gflags/gflags.h"
* Make sure to copy over a config_YOUR_PLATFORM.h and put it in config.h
Old changes which got obsoleted (maybe?) by 0.3.1 merge:
* The config_linux.h is generated by configure on Keir's Ubuntu 9.04 desktop.
* Commented out some struct ::tm weirdness causing compile failures on
ubuntu 8.10 and 9.04.
* Switched several initializers to memset instead of = {}.
* Changed some includes pointing to gflags. Not sure why the regular inclusion
didn't work.
* Added some compile flags to silence various warnings, allowing us to keep the
differences between upstream small.
* Don't redefine _XOPEN_SOURCE.
* Added "google::" to GetReferenceableValue in CHECK_OP_LOG.
* Add virtual destructor to Thread in googletest.h.
* Update windows/glog/log_severity to build with QT library that include WinGDI
(It cause a double definition of ERROR variable).
Old changes which got obsoleted (maybe?) by 0.2.1 merge:
* Added #ifndef / def REG_EIP; not sure what that is.
* Added (void) arg stuff to prevent unused variable warnings.
* Added google:: namespace prefix to GetReferencableValue
* Added assignments for several functions marked with no_ignore_return, where
the return value was ignored.
* Commented out the unused function DumpPCAndSymbol() in utilities.cc to silent
gcc on the mac
TODO(keir): Remove any obsoleted changes above if they are not necessary after
testing on more platforms.
WARNING: Mac port not updated for 0.2.1
* Replace <gflags/gflags.h> with "third_party/gflags/gflags/gflags.h" which is easier
to setup things in libmv and also helps with setting up building libmv into
external applications.
* Replace "glog/logging.h" and "glog/logging.h" with <glog/logging.h> and <glog/logging.h>
which is needed on Windows platform because otherwise files like logging.cc will be using
relative path which points to headers used by linux instead of headers need to be used
on Windows.
* Replace _asm int 3 with __debugbreak(). Such assembler code is obsolete and doesn't work
with 64bit versions of MSVC compilers.
* Do not use stacktrace for MinGW and FreeBSD because it leads into issues accessing
some specific data on this platforms.
* Define HAVE_LIB_GFLAGS for Windows builds.
* Do not define __declspec(dllimport) for MinGW platforms.
* Setup proper includes and datatypes for int32, uint32, int64 and uint64 for MinGW
* Do not define va_copy for MinGW platforms (it's already defined there).
* Patch localtime_r to be working fine with MinGW, disable strerror_r for MinGW because
of lack of needed functions.

@ -55,11 +55,11 @@
#ifdef HAVE_LIB_GFLAGS
#include "third_party/gflags/gflags.h"
#include "third_party/gflags/gflags/gflags.h"
#else
#include "glog/logging.h"
#include <glog/logging.h>
#define DECLARE_VARIABLE(type, name, tn) \
namespace FLAG__namespace_do_not_use_directly_use_DECLARE_##tn##_instead { \

@ -36,7 +36,7 @@
class GoogleInitializer {
public:
typedef void (*void_function)(void);
GoogleInitializer(const char* name, void_function f) {
GoogleInitializer(const char*, void_function f) {
f();
}
};

@ -122,13 +122,13 @@
#define PACKAGE_NAME "glog"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "glog 0.3.1"
#define PACKAGE_STRING "glog 0.3.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "glog"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.3.1"
#define PACKAGE_VERSION "0.3.2"
/* How to access the PC from a struct ucontext */
/* #define PC_FROM_UCONTEXT uc_mcontext.gregs[REG_RIP] */
@ -151,7 +151,7 @@
#define TEST_SRC_DIR "."
/* Version number of package */
#define VERSION "0.3.1"
#define VERSION "0.3.2"
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
@ -159,3 +159,8 @@
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
/* isn't getting defined by configure script when clang compilers are used
and cuases compilation errors in stactrace/unwind modules */
#ifdef __clang__
# define NO_FRAME_POINTER
#endif

@ -112,6 +112,10 @@
/* define if your compiler has __sync_val_compare_and_swap */
/* #undef HAVE___SYNC_VAL_COMPARE_AND_SWAP */
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "glog"
@ -122,13 +126,16 @@
#define PACKAGE_NAME "glog"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "glog 0.3.1"
#define PACKAGE_STRING "glog 0.3.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "glog"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.3.1"
#define PACKAGE_VERSION "0.3.2"
/* How to access the PC from a struct ucontext */
#if defined(_M_X64) || defined(__amd64__) || defined(__x86_64__)
@ -157,10 +164,16 @@
#define TEST_SRC_DIR "."
/* Version number of package */
#define VERSION "0.3.1"
#define VERSION "0.3.2"
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
/* isn't getting defined by configure script when clang compilers are used
and cuases compilation errors in stactrace/unwind modules */
#ifdef __clang__
# define NO_FRAME_POINTER
#endif

@ -122,13 +122,13 @@
#define PACKAGE_NAME "glog"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "glog 0.3.1"
#define PACKAGE_STRING "glog 0.3.2"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "glog"
/* Define to the version of this package. */
#define PACKAGE_VERSION "0.3.1"
#define PACKAGE_VERSION "0.3.2"
/* How to access the PC from a struct ucontext */
#undef PC_FROM_UCONTEXT
@ -150,10 +150,16 @@
#define TEST_SRC_DIR "."
/* Version number of package */
#define VERSION "0.3.1"
#define VERSION "0.3.2"
/* Stops putting the code inside the Google namespace */
#define _END_GOOGLE_NAMESPACE_ }
/* Puts following code inside the Google namespace */
#define _START_GOOGLE_NAMESPACE_ namespace google {
/* isn't getting defined by configure script when clang compilers are used
and cuases compilation errors in stactrace/unwind modules */
#ifdef __clang__
# define NO_FRAME_POINTER
#endif

@ -28,6 +28,11 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Author: Satoru Takabayashi
//
// For reference check out:
// http://www.codesourcery.com/public/cxx-abi/abi.html#mangling
//
// Note that we only have partial C++0x support yet.
#include <stdio.h> // for NULL
#include "demangle.h"
@ -138,14 +143,12 @@ static const AbbrevPair kSubstitutionList[] = {
// State needed for demangling.
typedef struct {
const char *mangled_cur; // Cursor of mangled name.
const char *mangled_end; // End of mangled name.
char *out_cur; // Cursor of output string.
const char *out_begin; // Beginning of output string.
const char *out_end; // End of output string.
const char *prev_name; // For constructors/destructors.
int prev_name_length; // For constructors/destructors.
int nest_level; // For nested names.
int number; // Remember the previous number.
short nest_level; // For nested names.
bool append; // Append flag.
bool overflowed; // True if output gets overflowed.
} State;
@ -161,6 +164,16 @@ static size_t StrLen(const char *str) {
return len;
}
// Returns true if "str" has at least "n" characters remaining.
static bool AtLeastNumCharsRemaining(const char *str, int n) {
for (int i = 0; i < n; ++i) {
if (str == '\0') {
return false;
}
}
return true;
}
// Returns true if "str" has "prefix" as a prefix.
static bool StrPrefix(const char *str, const char *prefix) {
size_t i = 0;
@ -174,39 +187,33 @@ static bool StrPrefix(const char *str, const char *prefix) {
static void InitState(State *state, const char *mangled,
char *out, int out_size) {
state->mangled_cur = mangled;
state->mangled_end = mangled + StrLen(mangled);
state->out_cur = out;
state->out_begin = out;
state->out_end = out + out_size;
state->prev_name = NULL;
state->prev_name_length = -1;
state->nest_level = -1;
state->number = -1;
state->append = true;
state->overflowed = false;
}
// Calculates the remaining length of the mangled name.
static int RemainingLength(State *state) {
return state->mangled_end - state->mangled_cur;
}
// Returns true and advances "mangled_cur" if we find "c" at
// "mangled_cur" position.
static bool ParseChar(State *state, const char c) {
if (RemainingLength(state) >= 1 && *state->mangled_cur == c) {
// Returns true and advances "mangled_cur" if we find "one_char_token"
// at "mangled_cur" position. It is assumed that "one_char_token" does
// not contain '\0'.
static bool ParseOneCharToken(State *state, const char one_char_token) {
if (state->mangled_cur[0] == one_char_token) {
++state->mangled_cur;
return true;
}
return false;
}
// Returns true and advances "mangled_cur" if we find "two_chars" at
// "mangled_cur" position.
static bool ParseTwoChar(State *state, const char *two_chars) {
if (RemainingLength(state) >= 2 &&
state->mangled_cur[0] == two_chars[0] &&
state->mangled_cur[1] == two_chars[1]) {
// Returns true and advances "mangled_cur" if we find "two_char_token"
// at "mangled_cur" position. It is assumed that "two_char_token" does
// not contain '\0'.
static bool ParseTwoCharToken(State *state, const char *two_char_token) {
if (state->mangled_cur[0] == two_char_token[0] &&
state->mangled_cur[1] == two_char_token[1]) {
state->mangled_cur += 2;
return true;
}
@ -216,13 +223,13 @@ static bool ParseTwoChar(State *state, const char *two_chars) {
// Returns true and advances "mangled_cur" if we find any character in
// "char_class" at "mangled_cur" position.
static bool ParseCharClass(State *state, const char *char_class) {
if (state->mangled_cur == state->mangled_end) {
if (state->mangled_cur == '\0') {
return false;
}
const char *p = char_class;
for (; *p != '\0'; ++p) {
if (*state->mangled_cur == *p) {
state->mangled_cur += 1;
if (state->mangled_cur[0] == *p) {
++state->mangled_cur;
return true;
}
}
@ -230,7 +237,7 @@ static bool ParseCharClass(State *state, const char *char_class) {
}
// This function is used for handling an optional non-terminal.
static bool Optional(bool status) {
static bool Optional(bool) {
return true;
}
@ -245,6 +252,16 @@ static bool OneOrMore(ParseFunc parse_func, State *state) {
return false;
}
// This function is used for handling <non-terminal>* syntax. The function
// always returns true and must be followed by a termination token or a
// terminating sequence not handled by parse_func (e.g.
// ParseOneCharToken(state, 'E')).
static bool ZeroOrMore(ParseFunc parse_func, State *state) {
while (parse_func(state)) {
}
return true;
}
// Append "str" at "out_cur". If there is an overflow, "overflowed"
// is set to true for later use. The output string is ensured to
// always terminate with '\0' as long as there is no overflow.
@ -270,7 +287,37 @@ static bool IsLower(char c) {
}
static bool IsAlpha(char c) {
return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'));
return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
}
static bool IsDigit(char c) {
return c >= '0' && c <= '9';
}
// Returns true if "str" is a function clone suffix. These suffixes are used
// by GCC 4.5.x and later versions to indicate functions which have been
// cloned during optimization. We treat any sequence (.<alpha>+.<digit>+)+ as
// a function clone suffix.
static bool IsFunctionCloneSuffix(const char *str) {
size_t i = 0;
while (str[i] != '\0') {
// Consume a single .<alpha>+.<digit>+ sequence.
if (str[i] != '.' || !IsAlpha(str[i + 1])) {
return false;
}
i += 2;
while (IsAlpha(str[i])) {
++i;
}
if (str[i] != '.' || !IsDigit(str[i + 1])) {
return false;
}
i += 2;
while (IsDigit(str[i])) {
++i;
}
}
return true; // Consumed everything in "str".
}
// Append "str" with some tweaks, iff "append" state is true.
@ -309,7 +356,7 @@ static bool EnterNestedName(State *state) {
}
// This function is used for handling nested names.
static bool LeaveNestedName(State *state, int prev_value) {
static bool LeaveNestedName(State *state, short prev_value) {
state->nest_level = prev_value;
return true;
}
@ -349,11 +396,11 @@ static void MaybeCancelLastSeparator(State *state) {
}
}
// Returns true if identifier pointed by "mangled_cur" is anonymous
// namespace.
static bool IdentifierIsAnonymousNamespace(State *state) {
const char anon_prefix[] = "_GLOBAL__N_";
return (state->number > sizeof(anon_prefix) - 1 && // Should be longer.
// Returns true if the identifier of the given length pointed to by
// "mangled_cur" is anonymous namespace.
static bool IdentifierIsAnonymousNamespace(State *state, int length) {
static const char anon_prefix[] = "_GLOBAL__N_";
return (length > (int)sizeof(anon_prefix) - 1 && // Should be longer.
StrPrefix(state->mangled_cur, anon_prefix));
}
@ -368,10 +415,10 @@ static bool ParsePrefix(State *state);
static bool ParseUnqualifiedName(State *state);
static bool ParseSourceName(State *state);
static bool ParseLocalSourceName(State *state);
static bool ParseNumber(State *state);
static bool ParseNumber(State *state, int *number_out);
static bool ParseFloatNumber(State *state);
static bool ParseSeqId(State *state);
static bool ParseIdentifier(State *state);
static bool ParseIdentifier(State *state, int length);
static bool ParseOperatorName(State *state);
static bool ParseSpecialName(State *state);
static bool ParseCallOffset(State *state);
@ -428,17 +475,7 @@ static bool ParseSubstitution(State *state);
// <mangled-name> ::= _Z <encoding>
static bool ParseMangledName(State *state) {
if (ParseTwoChar(state, "_Z") && ParseEncoding(state)) {
// Append trailing version suffix if any.
// ex. _Z3foo@@GLIBCXX_3.4
if (state->mangled_cur < state->mangled_end &&
state->mangled_cur[0] == '@') {
MaybeAppend(state, state->mangled_cur);
state->mangled_cur = state->mangled_end;
}
return true;
}
return false;
return ParseTwoCharToken(state, "_Z") && ParseEncoding(state);
}
// <encoding> ::= <(function) name> <bare-function-type>
@ -488,7 +525,7 @@ static bool ParseUnscopedName(State *state) {
}
State copy = *state;
if (ParseTwoChar(state, "St") &&
if (ParseTwoCharToken(state, "St") &&
MaybeAppend(state, "std::") &&
ParseUnqualifiedName(state)) {
return true;
@ -507,12 +544,12 @@ static bool ParseUnscopedTemplateName(State *state) {
// ::= N [<CV-qualifiers>] <template-prefix> <template-args> E
static bool ParseNestedName(State *state) {
State copy = *state;
if (ParseChar(state, 'N') &&
if (ParseOneCharToken(state, 'N') &&
EnterNestedName(state) &&
Optional(ParseCVQualifiers(state)) &&
ParsePrefix(state) &&
LeaveNestedName(state, copy.nest_level) &&
ParseChar(state, 'E')) {
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
@ -565,7 +602,8 @@ static bool ParseUnqualifiedName(State *state) {
// <source-name> ::= <positive length number> <identifier>
static bool ParseSourceName(State *state) {
State copy = *state;
if (ParseNumber(state) && ParseIdentifier(state)) {
int length = -1;
if (ParseNumber(state, &length) && ParseIdentifier(state, length)) {
return true;
}
*state = copy;
@ -579,7 +617,7 @@ static bool ParseSourceName(State *state) {
// http://gcc.gnu.org/viewcvs?view=rev&revision=124467
static bool ParseLocalSourceName(State *state) {
State copy = *state;
if (ParseChar(state, 'L') && ParseSourceName(state) &&
if (ParseOneCharToken(state, 'L') && ParseSourceName(state) &&
Optional(ParseDiscriminator(state))) {
return true;
}
@ -588,15 +626,17 @@ static bool ParseLocalSourceName(State *state) {
}
// <number> ::= [n] <non-negative decimal integer>
static bool ParseNumber(State *state) {
// If "number_out" is non-null, then *number_out is set to the value of the
// parsed number on success.
static bool ParseNumber(State *state, int *number_out) {
int sign = 1;
if (ParseChar(state, 'n')) {
if (ParseOneCharToken(state, 'n')) {
sign = -1;
}
const char *p = state->mangled_cur;
int number = 0;
for (;p < state->mangled_end; ++p) {
if ((*p >= '0' && *p <= '9')) {
for (;*p != '\0'; ++p) {
if (IsDigit(*p)) {
number = number * 10 + (*p - '0');
} else {
break;
@ -604,7 +644,9 @@ static bool ParseNumber(State *state) {
}
if (p != state->mangled_cur) { // Conversion succeeded.
state->mangled_cur = p;
state->number = number * sign;
if (number_out != NULL) {
*number_out = number * sign;
}
return true;
}
return false;
@ -614,19 +656,13 @@ static bool ParseNumber(State *state) {
// hexadecimal string.
static bool ParseFloatNumber(State *state) {
const char *p = state->mangled_cur;
int number = 0;
for (;p < state->mangled_end; ++p) {
if ((*p >= '0' && *p <= '9')) {
number = number * 16 + (*p - '0');
} else if (*p >= 'a' && *p <= 'f') {
number = number * 16 + (*p - 'a' + 10);
} else {
for (;*p != '\0'; ++p) {
if (!IsDigit(*p) && !(*p >= 'a' && *p <= 'f')) {
break;
}
}
if (p != state->mangled_cur) { // Conversion succeeded.
state->mangled_cur = p;
state->number = number;
return true;
}
return false;
@ -636,37 +672,30 @@ static bool ParseFloatNumber(State *state) {
// using digits and upper case letters
static bool ParseSeqId(State *state) {
const char *p = state->mangled_cur;
int number = 0;
for (;p < state->mangled_end; ++p) {
if ((*p >= '0' && *p <= '9')) {
number = number * 36 + (*p - '0');
} else if (*p >= 'A' && *p <= 'Z') {
number = number * 36 + (*p - 'A' + 10);
} else {
for (;*p != '\0'; ++p) {
if (!IsDigit(*p) && !(*p >= 'A' && *p <= 'Z')) {
break;
}
}
if (p != state->mangled_cur) { // Conversion succeeded.
state->mangled_cur = p;
state->number = number;
return true;
}
return false;
}
// <identifier> ::= <unqualified source code identifier>
static bool ParseIdentifier(State *state) {
if (state->number == -1 ||
RemainingLength(state) < state->number) {
// <identifier> ::= <unqualified source code identifier> (of given length)
static bool ParseIdentifier(State *state, int length) {
if (length == -1 ||
!AtLeastNumCharsRemaining(state->mangled_cur, length)) {
return false;
}
if (IdentifierIsAnonymousNamespace(state)) {
if (IdentifierIsAnonymousNamespace(state, length)) {
MaybeAppend(state, "(anonymous namespace)");
} else {
MaybeAppendWithLength(state, state->mangled_cur, state->number);
MaybeAppendWithLength(state, state->mangled_cur, length);
}
state->mangled_cur += state->number;
state->number = -1; // Reset the number.
state->mangled_cur += length;
return true;
}
@ -674,12 +703,12 @@ static bool ParseIdentifier(State *state) {
// ::= cv <type> # (cast)
// ::= v <digit> <source-name> # vendor extended operator
static bool ParseOperatorName(State *state) {
if (RemainingLength(state) < 2) {
if (!AtLeastNumCharsRemaining(state->mangled_cur, 2)) {
return false;
}
// First check with "cv" (cast) case.
State copy = *state;
if (ParseTwoChar(state, "cv") &&
if (ParseTwoCharToken(state, "cv") &&
MaybeAppend(state, "operator ") &&
EnterNestedName(state) &&
ParseType(state) &&
@ -689,7 +718,7 @@ static bool ParseOperatorName(State *state) {
*state = copy;
// Then vendor extended operators.
if (ParseChar(state, 'v') && ParseCharClass(state, "0123456789") &&
if (ParseOneCharToken(state, 'v') && ParseCharClass(state, "0123456789") &&
ParseSourceName(state)) {
return true;
}
@ -738,34 +767,34 @@ static bool ParseOperatorName(State *state) {
// stack traces. The are special data.
static bool ParseSpecialName(State *state) {
State copy = *state;
if (ParseChar(state, 'T') &&
if (ParseOneCharToken(state, 'T') &&
ParseCharClass(state, "VTIS") &&
ParseType(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "Tc") && ParseCallOffset(state) &&
if (ParseTwoCharToken(state, "Tc") && ParseCallOffset(state) &&
ParseCallOffset(state) && ParseEncoding(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "GV") &&
if (ParseTwoCharToken(state, "GV") &&
ParseName(state)) {
return true;
}
*state = copy;
if (ParseChar(state, 'T') && ParseCallOffset(state) &&
if (ParseOneCharToken(state, 'T') && ParseCallOffset(state) &&
ParseEncoding(state)) {
return true;
}
*state = copy;
// G++ extensions
if (ParseTwoChar(state, "TC") && ParseType(state) &&
ParseNumber(state) && ParseChar(state, '_') &&
if (ParseTwoCharToken(state, "TC") && ParseType(state) &&
ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
DisableAppend(state) &&
ParseType(state)) {
RestoreAppend(state, copy.append);
@ -773,23 +802,23 @@ static bool ParseSpecialName(State *state) {
}
*state = copy;
if (ParseChar(state, 'T') && ParseCharClass(state, "FJ") &&
if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "FJ") &&
ParseType(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "GR") && ParseName(state)) {
if (ParseTwoCharToken(state, "GR") && ParseName(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "GA") && ParseEncoding(state)) {
if (ParseTwoCharToken(state, "GA") && ParseEncoding(state)) {
return true;
}
*state = copy;
if (ParseChar(state, 'T') && ParseCharClass(state, "hv") &&
if (ParseOneCharToken(state, 'T') && ParseCharClass(state, "hv") &&
ParseCallOffset(state) && ParseEncoding(state)) {
return true;
}
@ -801,14 +830,14 @@ static bool ParseSpecialName(State *state) {
// ::= v <v-offset> _
static bool ParseCallOffset(State *state) {
State copy = *state;
if (ParseChar(state, 'h') &&
ParseNVOffset(state) && ParseChar(state, '_')) {
if (ParseOneCharToken(state, 'h') &&
ParseNVOffset(state) && ParseOneCharToken(state, '_')) {
return true;
}
*state = copy;
if (ParseChar(state, 'v') &&
ParseVOffset(state) && ParseChar(state, '_')) {
if (ParseOneCharToken(state, 'v') &&
ParseVOffset(state) && ParseOneCharToken(state, '_')) {
return true;
}
*state = copy;
@ -818,14 +847,14 @@ static bool ParseCallOffset(State *state) {
// <nv-offset> ::= <(offset) number>
static bool ParseNVOffset(State *state) {
return ParseNumber(state);
return ParseNumber(state, NULL);
}
// <v-offset> ::= <(offset) number> _ <(virtual offset) number>
static bool ParseVOffset(State *state) {
State copy = *state;
if (ParseNumber(state) && ParseChar(state, '_') &&
ParseNumber(state)) {
if (ParseNumber(state, NULL) && ParseOneCharToken(state, '_') &&
ParseNumber(state, NULL)) {
return true;
}
*state = copy;
@ -836,7 +865,7 @@ static bool ParseVOffset(State *state) {
// ::= D0 | D1 | D2
static bool ParseCtorDtorName(State *state) {
State copy = *state;
if (ParseChar(state, 'C') &&
if (ParseOneCharToken(state, 'C') &&
ParseCharClass(state, "123")) {
const char * const prev_name = state->prev_name;
const int prev_name_length = state->prev_name_length;
@ -845,7 +874,7 @@ static bool ParseCtorDtorName(State *state) {
}
*state = copy;
if (ParseChar(state, 'D') &&
if (ParseOneCharToken(state, 'D') &&
ParseCharClass(state, "012")) {
const char * const prev_name = state->prev_name;
const int prev_name_length = state->prev_name_length;
@ -858,11 +887,12 @@ static bool ParseCtorDtorName(State *state) {
}
// <type> ::= <CV-qualifiers> <type>
// ::= P <type>
// ::= R <type>
// ::= C <type>
// ::= G <type>
// ::= U <source-name> <type>
// ::= P <type> # pointer-to
// ::= R <type> # reference-to
// ::= O <type> # rvalue reference-to (C++0x)
// ::= C <type> # complex pair (C 2000)
// ::= G <type> # imaginary (C 2000)
// ::= U <source-name> <type> # vendor extended type qualifier
// ::= <builtin-type>
// ::= <function-type>
// ::= <class-enum-type>
@ -871,6 +901,11 @@ static bool ParseCtorDtorName(State *state) {
// ::= <template-template-param> <template-args>
// ::= <template-param>
// ::= <substitution>
// ::= Dp <type> # pack expansion of (C++0x)
// ::= Dt <expression> E # decltype of an id-expression or class
// # member access (C++0x)
// ::= DT <expression> E # decltype of an expression (C++0x)
//
static bool ParseType(State *state) {
// We should check CV-qualifers, and PRGC things first.
State copy = *state;
@ -879,12 +914,23 @@ static bool ParseType(State *state) {
}
*state = copy;
if (ParseCharClass(state, "PRCG") && ParseType(state)) {
if (ParseCharClass(state, "OPRCG") && ParseType(state)) {
return true;
}
*state = copy;
if (ParseChar(state, 'U') && ParseSourceName(state) &&
if (ParseTwoCharToken(state, "Dp") && ParseType(state)) {
return true;
}
*state = copy;
if (ParseOneCharToken(state, 'D') && ParseCharClass(state, "tT") &&
ParseExpression(state) && ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
if (ParseOneCharToken(state, 'U') && ParseSourceName(state) &&
ParseType(state)) {
return true;
}
@ -918,9 +964,9 @@ static bool ParseType(State *state) {
// ParseType().
static bool ParseCVQualifiers(State *state) {
int num_cv_qualifiers = 0;
num_cv_qualifiers += ParseChar(state, 'r');
num_cv_qualifiers += ParseChar(state, 'V');
num_cv_qualifiers += ParseChar(state, 'K');
num_cv_qualifiers += ParseOneCharToken(state, 'r');
num_cv_qualifiers += ParseOneCharToken(state, 'V');
num_cv_qualifiers += ParseOneCharToken(state, 'K');
return num_cv_qualifiers > 0;
}
@ -937,7 +983,7 @@ static bool ParseBuiltinType(State *state) {
}
State copy = *state;
if (ParseChar(state, 'u') && ParseSourceName(state)) {
if (ParseOneCharToken(state, 'u') && ParseSourceName(state)) {
return true;
}
*state = copy;
@ -947,8 +993,9 @@ static bool ParseBuiltinType(State *state) {
// <function-type> ::= F [Y] <bare-function-type> E
static bool ParseFunctionType(State *state) {
State copy = *state;
if (ParseChar(state, 'F') && Optional(ParseChar(state, 'Y')) &&
ParseBareFunctionType(state) && ParseChar(state, 'E')) {
if (ParseOneCharToken(state, 'F') &&
Optional(ParseOneCharToken(state, 'Y')) &&
ParseBareFunctionType(state) && ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
@ -977,14 +1024,14 @@ static bool ParseClassEnumType(State *state) {
// ::= A [<(dimension) expression>] _ <(element) type>
static bool ParseArrayType(State *state) {
State copy = *state;
if (ParseChar(state, 'A') && ParseNumber(state) &&
ParseChar(state, '_') && ParseType(state)) {
if (ParseOneCharToken(state, 'A') && ParseNumber(state, NULL) &&
ParseOneCharToken(state, '_') && ParseType(state)) {
return true;
}
*state = copy;
if (ParseChar(state, 'A') && Optional(ParseExpression(state)) &&
ParseChar(state, '_') && ParseType(state)) {
if (ParseOneCharToken(state, 'A') && Optional(ParseExpression(state)) &&
ParseOneCharToken(state, '_') && ParseType(state)) {
return true;
}
*state = copy;
@ -994,7 +1041,7 @@ static bool ParseArrayType(State *state) {
// <pointer-to-member-type> ::= M <(class) type> <(member) type>
static bool ParsePointerToMemberType(State *state) {
State copy = *state;
if (ParseChar(state, 'M') && ParseType(state) &&
if (ParseOneCharToken(state, 'M') && ParseType(state) &&
ParseType(state)) {
return true;
}
@ -1005,14 +1052,14 @@ static bool ParsePointerToMemberType(State *state) {
// <template-param> ::= T_
// ::= T <parameter-2 non-negative number> _
static bool ParseTemplateParam(State *state) {
if (ParseTwoChar(state, "T_")) {
if (ParseTwoCharToken(state, "T_")) {
MaybeAppend(state, "?"); // We don't support template substitutions.
return true;
}
State copy = *state;
if (ParseChar(state, 'T') && ParseNumber(state) &&
ParseChar(state, '_')) {
if (ParseOneCharToken(state, 'T') && ParseNumber(state, NULL) &&
ParseOneCharToken(state, '_')) {
MaybeAppend(state, "?"); // We don't support template substitutions.
return true;
}
@ -1032,9 +1079,9 @@ static bool ParseTemplateTemplateParam(State *state) {
static bool ParseTemplateArgs(State *state) {
State copy = *state;
DisableAppend(state);
if (ParseChar(state, 'I') &&
if (ParseOneCharToken(state, 'I') &&
OneOrMore(ParseTemplateArg, state) &&
ParseChar(state, 'E')) {
ParseOneCharToken(state, 'E')) {
RestoreAppend(state, copy.append);
MaybeAppend(state, "<>");
return true;
@ -1045,16 +1092,25 @@ static bool ParseTemplateArgs(State *state) {
// <template-arg> ::= <type>
// ::= <expr-primary>
// ::= I <template-arg>* E # argument pack
// ::= X <expression> E
static bool ParseTemplateArg(State *state) {
State copy = *state;
if (ParseOneCharToken(state, 'I') &&
ZeroOrMore(ParseTemplateArg, state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
if (ParseType(state) ||
ParseExprPrimary(state)) {
return true;
}
*state = copy;
State copy = *state;
if (ParseChar(state, 'X') && ParseExpression(state) &&
ParseChar(state, 'E')) {
if (ParseOneCharToken(state, 'X') && ParseExpression(state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
@ -1097,19 +1153,19 @@ static bool ParseExpression(State *state) {
}
*state = copy;
if (ParseTwoChar(state, "st") && ParseType(state)) {
if (ParseTwoCharToken(state, "st") && ParseType(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "sr") && ParseType(state) &&
if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
ParseUnqualifiedName(state) &&
ParseTemplateArgs(state)) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "sr") && ParseType(state) &&
if (ParseTwoCharToken(state, "sr") && ParseType(state) &&
ParseUnqualifiedName(state)) {
return true;
}
@ -1124,28 +1180,28 @@ static bool ParseExpression(State *state) {
// ::= LZ <encoding> E
static bool ParseExprPrimary(State *state) {
State copy = *state;
if (ParseChar(state, 'L') && ParseType(state) &&
ParseNumber(state) &&
ParseChar(state, 'E')) {
if (ParseOneCharToken(state, 'L') && ParseType(state) &&
ParseNumber(state, NULL) &&
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
if (ParseChar(state, 'L') && ParseType(state) &&
if (ParseOneCharToken(state, 'L') && ParseType(state) &&
ParseFloatNumber(state) &&
ParseChar(state, 'E')) {
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
if (ParseChar(state, 'L') && ParseMangledName(state) &&
ParseChar(state, 'E')) {
if (ParseOneCharToken(state, 'L') && ParseMangledName(state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
if (ParseTwoChar(state, "LZ") && ParseEncoding(state) &&
ParseChar(state, 'E')) {
if (ParseTwoCharToken(state, "LZ") && ParseEncoding(state) &&
ParseOneCharToken(state, 'E')) {
return true;
}
*state = copy;
@ -1158,15 +1214,15 @@ static bool ParseExprPrimary(State *state) {
// := Z <(function) encoding> E s [<discriminator>]
static bool ParseLocalName(State *state) {
State copy = *state;
if (ParseChar(state, 'Z') && ParseEncoding(state) &&
ParseChar(state, 'E') && MaybeAppend(state, "::") &&
if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
ParseOneCharToken(state, 'E') && MaybeAppend(state, "::") &&
ParseName(state) && Optional(ParseDiscriminator(state))) {
return true;
}
*state = copy;
if (ParseChar(state, 'Z') && ParseEncoding(state) &&
ParseTwoChar(state, "Es") && Optional(ParseDiscriminator(state))) {
if (ParseOneCharToken(state, 'Z') && ParseEncoding(state) &&
ParseTwoCharToken(state, "Es") && Optional(ParseDiscriminator(state))) {
return true;
}
*state = copy;
@ -1176,7 +1232,7 @@ static bool ParseLocalName(State *state) {
// <discriminator> := _ <(non-negative) number>
static bool ParseDiscriminator(State *state) {
State copy = *state;
if (ParseChar(state, '_') && ParseNumber(state)) {
if (ParseOneCharToken(state, '_') && ParseNumber(state, NULL)) {
return true;
}
*state = copy;
@ -1187,21 +1243,21 @@ static bool ParseDiscriminator(State *state) {
// ::= S <seq-id> _
// ::= St, etc.
static bool ParseSubstitution(State *state) {
if (ParseTwoChar(state, "S_")) {
if (ParseTwoCharToken(state, "S_")) {
MaybeAppend(state, "?"); // We don't support substitutions.
return true;
}
State copy = *state;
if (ParseChar(state, 'S') && ParseSeqId(state) &&
ParseChar(state, '_')) {
if (ParseOneCharToken(state, 'S') && ParseSeqId(state) &&
ParseOneCharToken(state, '_')) {
MaybeAppend(state, "?"); // We don't support substitutions.
return true;
}
*state = copy;
// Expand abbreviations like "St" => "std".
if (ParseChar(state, 'S')) {
if (ParseOneCharToken(state, 'S')) {
const AbbrevPair *p;
for (p = kSubstitutionList; p->abbrev != NULL; ++p) {
if (state->mangled_cur[0] == p->abbrev[1]) {
@ -1210,7 +1266,7 @@ static bool ParseSubstitution(State *state) {
MaybeAppend(state, "::");
MaybeAppend(state, p->real_name);
}
state->mangled_cur += 1;
++state->mangled_cur;
return true;
}
}
@ -1219,13 +1275,33 @@ static bool ParseSubstitution(State *state) {
return false;
}
// Parse <mangled-name>, optionally followed by either a function-clone suffix
// or version suffix. Returns true only if all of "mangled_cur" was consumed.
static bool ParseTopLevelMangledName(State *state) {
if (ParseMangledName(state)) {
if (state->mangled_cur[0] != '\0') {
// Drop trailing function clone suffix, if any.
if (IsFunctionCloneSuffix(state->mangled_cur)) {
return true;
}
// Append trailing version suffix if any.
// ex. _Z3foo@@GLIBCXX_3.4
if (state->mangled_cur[0] == '@') {
MaybeAppend(state, state->mangled_cur);
return true;
}
return false; // Unconsumed suffix.
}
return true;
}
return false;
}
// The demangler entry point.
bool Demangle(const char *mangled, char *out, int out_size) {
State state;
InitState(&state, mangled, out, out_size);
return (ParseMangledName(&state) &&
state.overflowed == false &&
RemainingLength(&state) == 0);
return ParseTopLevelMangledName(&state) && !state.overflowed;
}
_END_GOOGLE_NAMESPACE_

@ -44,7 +44,15 @@
// you ever need to change their values or add a new severity.
typedef int LogSeverity;
const int INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3, NUM_SEVERITIES = 4;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
#endif
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG

@ -33,7 +33,6 @@
// Pretty much everybody needs to #include this file so that they can
// log various happenings.
//
#ifndef _LOGGING_H_
#define _LOGGING_H_
@ -80,7 +79,7 @@
#endif
#if 1
#include "third_party/gflags/gflags.h"
#include "third_party/gflags/gflags/gflags.h"
#endif
namespace google {
@ -153,21 +152,21 @@ typedef unsigned __int64 uint64;
// You can also do occasional logging (log every n'th occurrence of an
// event):
//
// LOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";
// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// The above will cause log messages to be output on the 1st, 11th, 21st, ...
// times it is executed. Note that the special COUNTER value is used to
// identify which repetition is happening.
// times it is executed. Note that the special google::COUNTER value is used
// to identify which repetition is happening.
//
// You can also do occasional conditional logging (log every n'th
// occurrence of an event, when condition is satisfied):
//
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
// << "th big cookie";
//
// You can log messages the first N times your code executes a line. E.g.
//
// LOG_FIRST_N(INFO, 20) << "Got the " << COUNTER << "th cookie";
// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
//
// Outputs log messages for the first 20 times it is executed.
//
@ -184,7 +183,7 @@ typedef unsigned __int64 uint64;
//
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// DLOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";
// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// All "debug mode" logging is compiled away to nothing for non-debug mode
// compiles.
@ -228,11 +227,11 @@ typedef unsigned __int64 uint64;
// "program with --v=1 or more";
// VLOG_EVERY_N(1, 10)
// << "I'm printed every 10th occurrence, and when you run the program "
// "with --v=1 or more. Present occurence is " << COUNTER;
// "with --v=1 or more. Present occurence is " << google::COUNTER;
// VLOG_IF_EVERY_N(1, (size > 1024), 10)
// << "I'm printed on every 10th occurence of case when size is more "
// " than 1024, when you run the program with --v=1 or more. ";
// "Present occurence is " << COUNTER;
// "Present occurence is " << google::COUNTER;
//
// The supported severity levels for macros that allow you to specify one
// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
@ -369,7 +368,7 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
__FILE__, __LINE__)
#define LOG_TO_STRING_INFO(message) google::LogMessage( \
__FILE__, __LINE__, google::INFO, message)
__FILE__, __LINE__, google::GLOG_INFO, message)
#else
#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
#define LOG_TO_STRING_INFO(message) google::NullStream()
@ -377,9 +376,9 @@ DECLARE_bool(stop_logging_if_full_disk);
#if GOOGLE_STRIP_LOG <= 1
#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
__FILE__, __LINE__, google::WARNING)
__FILE__, __LINE__, google::GLOG_WARNING)
#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
__FILE__, __LINE__, google::WARNING, message)
__FILE__, __LINE__, google::GLOG_WARNING, message)
#else
#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
#define LOG_TO_STRING_WARNING(message) google::NullStream()
@ -387,9 +386,9 @@ DECLARE_bool(stop_logging_if_full_disk);
#if GOOGLE_STRIP_LOG <= 2
#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
__FILE__, __LINE__, google::ERROR)
__FILE__, __LINE__, google::GLOG_ERROR)
#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
__FILE__, __LINE__, google::ERROR, message)
__FILE__, __LINE__, google::GLOG_ERROR, message)
#else
#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
#define LOG_TO_STRING_ERROR(message) google::NullStream()
@ -399,7 +398,7 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
__FILE__, __LINE__)
#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
__FILE__, __LINE__, google::FATAL, message)
__FILE__, __LINE__, google::GLOG_FATAL, message)
#else
#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
@ -411,32 +410,32 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
#elif GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
__FILE__, __LINE__, google::FATAL)
__FILE__, __LINE__, google::GLOG_FATAL)
#else
#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
#endif
#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::INFO, counter, &google::LogMessage::SendToLog)
#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
#define SYSLOG_INFO(counter) \
google::LogMessage(__FILE__, __LINE__, google::INFO, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_DFATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
@ -455,7 +454,7 @@ DECLARE_bool(stop_logging_if_full_disk);
FORMAT_MESSAGE_FROM_SYSTEM, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, ERROR, 0, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog).stream() << message; \
LocalFree(message); \
} \
@ -502,12 +501,12 @@ class LogSink; // defined below
#define LOG_TO_SINK(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::severity, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), true).stream()
#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::severity, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), false).stream()
// If a non-NULL string pointer is given, we write this message to that string.
@ -772,7 +771,7 @@ DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
#define GOOGLE_PLOG(severity, counter) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::severity, counter, \
__FILE__, __LINE__, google::GLOG_ ## severity, counter, \
&google::LogMessage::SendToLog)
#define PLOG_IF(severity, condition) \
@ -811,7 +810,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
@ -820,7 +819,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (condition && \
((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
@ -829,7 +828,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
@ -838,7 +837,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
++LOG_OCCURRENCES; \
if (LOG_OCCURRENCES <= n) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
namespace glog_internal_namespace_ {
@ -852,7 +851,7 @@ struct CrashReason;
typedef google::glog_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
#define LOG_EVERY_N(severity, n) \
GOOGLE_GLOG_COMPILE_ASSERT(google::severity < \
GOOGLE_GLOG_COMPILE_ASSERT(google::GLOG_ ## severity < \
google::NUM_SEVERITIES, \
INVALID_REQUESTED_LOG_SEVERITY); \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
@ -872,6 +871,27 @@ struct CrashReason;
// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
enum PRIVATE_Counter {COUNTER};
#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
// to keep using this syntax, we define this macro to do the same thing
// as COMPACT_GOOGLE_LOG_ERROR.
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
#define SYSLOG_0 SYSLOG_ERROR
#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
// Needed for LOG_IS_ON(ERROR).
const LogSeverity GLOG_0 = GLOG_ERROR;
#else
// Users may include windows.h after logging.h without
// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
// For this case, we cannot detect if ERROR is defined before users
// actually use ERROR. Let's make an undefined symbol to warn users.
# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
# define SYSLOG_0 GLOG_ERROR_MSG
# define LOG_TO_STRING_0 GLOG_ERROR_MSG
# define GLOG_0 GLOG_ERROR_MSG
#endif
// Plus some debug-logging macros that get compiled to nothing for production
@ -1016,14 +1036,14 @@ public:
# pragma warning(default: 4275)
#endif
public:
LogStream(char *buf, int len, int ctr)
LogStream(char *buf, int len, int ctr_in)
: ostrstream(buf, len),
ctr_(ctr) {
ctr_(ctr_in) {
self_ = this;
}
int ctr() const { return ctr_; }
void set_ctr(int ctr) { ctr_ = ctr; }
void set_ctr(int ctr_in) { ctr_ = ctr_in; }
LogStream* self() const { return self_; }
private:
@ -1465,7 +1485,7 @@ class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
// converted to LogStream and the message will be computed and then
// quietly discarded.
template<class T>
inline NullStream& operator<<(NullStream &str, const T &value) { return str; }
inline NullStream& operator<<(NullStream &str, const T &) { return str; }
// Similar to NullStream, but aborts the program (without stack
// trace), like LogMessageFatal.

@ -68,7 +68,7 @@ namespace google {
// I0821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (google::severity) { \
switch (google::GLOG_ ## severity) { \
case 0: \
RAW_LOG_INFO(__VA_ARGS__); \
break; \
@ -100,28 +100,28 @@ namespace google {
#endif // STRIP_LOG == 0
#if STRIP_LOG == 0
#define RAW_LOG_INFO(...) google::RawLog__(google::INFO, \
#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) google::RawLog__(google::WARNING, \
#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
#if STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) google::RawLog__(google::ERROR, \
#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
#if STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) google::RawLog__(google::FATAL, \
#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
@ -162,7 +162,7 @@ namespace google {
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int ignored, ...) {
static inline void RawLogStub__(int /* ignored */, ...) {
}
// Helper function to implement RAW_LOG and RAW_VLOG

@ -111,7 +111,7 @@ _END_GOOGLE_NAMESPACE_
// The default is ERROR instead of FATAL so that users can see problems
// when they run a program without having to look in another file.
DEFINE_int32(stderrthreshold,
GOOGLE_NAMESPACE::ERROR,
GOOGLE_NAMESPACE::GLOG_ERROR,
"log messages at or above this level are copied to stderr in "
"addition to logfiles. This flag obsoletes --alsologtostderr.");
@ -311,8 +311,10 @@ class LogDestination {
static const int kNetworkBytes = 1400;
static const string& hostname();
private:
static void DeleteLogDestinations();
private:
LogDestination(LogSeverity severity, const char* base_filename);
~LogDestination() { }
@ -503,7 +505,7 @@ inline void LogDestination::SetEmailLogging(LogSeverity min_severity,
static void WriteToStderr(const char* message, size_t len) {
// Avoid using cerr from this module since we may get called during
// exit code, and cerr may be partially or fully destroyed by then.
write(STDERR_FILENO, message, len);
fwrite(message, len, 1, stderr);
}
inline void LogDestination::MaybeLogToStderr(LogSeverity severity,
@ -607,6 +609,13 @@ inline LogDestination* LogDestination::log_destination(LogSeverity severity) {
return log_destinations_[severity];
}
void LogDestination::DeleteLogDestinations() {
for (int severity = 0; severity < NUM_SEVERITIES; ++severity) {
delete log_destinations_[severity];
log_destinations_[severity] = NULL;
}
}
namespace {
LogFileObject::LogFileObject(LogSeverity severity,
@ -719,14 +728,18 @@ bool LogFileObject::CreateLogfile(const char* time_pid_string) {
// Make the symlink be relative (in the same dir) so that if the
// entire log directory gets relocated the link is still valid.
const char *linkdest = slash ? (slash + 1) : filename;
symlink(linkdest, linkpath.c_str()); // silently ignore failures
if (symlink(linkdest, linkpath.c_str()) != 0) {
// silently ignore failures
}
// Make an additional link to the log file in a place specified by
// FLAGS_log_link, if indicated
if (!FLAGS_log_link.empty()) {
linkpath = FLAGS_log_link + "/" + linkname;
unlink(linkpath.c_str()); // delete old one if it exists
symlink(filename, linkpath.c_str()); // silently ignore failures
if (symlink(filename, linkpath.c_str()) != 0) {
// silently ignore failures
}
}
#endif
}
@ -745,7 +758,8 @@ void LogFileObject::Write(bool force_flush,
return;
}
if (static_cast<int>(file_length_ >> 20) >= MaxLogSize()) {
if (static_cast<int>(file_length_ >> 20) >= MaxLogSize() ||
PidHasChanged()) {
if (file_ != NULL) fclose(file_);
file_ = NULL;
file_length_ = bytes_since_flush_ = 0;
@ -936,12 +950,12 @@ LogMessage::LogMessage(const char* file, int line, LogSeverity severity,
LogMessage::LogMessage(const char* file, int line,
const CheckOpString& result) {
Init(file, line, FATAL, &LogMessage::SendToLog);
Init(file, line, GLOG_FATAL, &LogMessage::SendToLog);
stream() << "Check failed: " << (*result.str_) << " ";
}
LogMessage::LogMessage(const char* file, int line) {
Init(file, line, INFO, &LogMessage::SendToLog);
Init(file, line, GLOG_INFO, &LogMessage::SendToLog);
}
LogMessage::LogMessage(const char* file, int line, LogSeverity severity) {
@ -972,7 +986,7 @@ void LogMessage::Init(const char* file,
LogSeverity severity,
void (LogMessage::*send_method)()) {
allocated_ = NULL;
if (severity != FATAL || !exit_on_dfatal) {
if (severity != GLOG_FATAL || !exit_on_dfatal) {
allocated_ = new LogMessageData();
data_ = allocated_;
data_->buf_ = new char[kMaxLogMessageLen+1];
@ -1123,7 +1137,7 @@ void ReprintFatalMessage() {
// Also write to stderr
WriteToStderr(fatal_message, n);
}
LogDestination::LogToAllLogfiles(ERROR, fatal_time, fatal_message, n);
LogDestination::LogToAllLogfiles(GLOG_ERROR, fatal_time, fatal_message, n);
}
}
@ -1181,7 +1195,7 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
// If we log a FATAL message, flush all the log destinations, then toss
// a signal for others to catch. We leave the logs in a state that
// someone else can use them (as long as they flush afterwards)
if (data_->severity_ == FATAL && exit_on_dfatal) {
if (data_->severity_ == GLOG_FATAL && exit_on_dfatal) {
if (data_->first_fatal_) {
// Store crash information so that it is accessible from within signal
// handlers that may be invoked later.
@ -1212,7 +1226,9 @@ void LogMessage::SendToLog() EXCLUSIVE_LOCKS_REQUIRED(log_mutex) {
LogDestination::WaitForSinks(data_);
const char* message = "*** Check failure stack trace: ***\n";
write(STDERR_FILENO, message, strlen(message));
if (write(STDERR_FILENO, message, strlen(message)) < 0) {
// Ignore errors.
}
Fail();
}
}
@ -1231,27 +1247,31 @@ void LogMessage::RecordCrashReason(
#endif
}
#ifdef HAVE___ATTRIBUTE__
# define ATTRIBUTE_NORETURN __attribute__((noreturn))
#else
# define ATTRIBUTE_NORETURN
#endif
static void logging_fail() ATTRIBUTE_NORETURN;
static void logging_fail() {
// #if defined(_DEBUG) && defined(_MSC_VER)
// doesn't work for my laptop (sergey)
#if 0
#if defined(_DEBUG) && defined(_MSC_VER)
// When debugging on windows, avoid the obnoxious dialog and make
// it possible to continue past a LOG(FATAL) in the debugger
_asm int 3
__debugbreak();
#else
abort();
#endif
}
#ifdef HAVE___ATTRIBUTE__
typedef void (*logging_fail_func_t)() ATTRIBUTE_NORETURN;
GOOGLE_GLOG_DLL_DECL
void (*g_logging_fail_func)() __attribute__((noreturn)) = &logging_fail;
#else
GOOGLE_GLOG_DLL_DECL void (*g_logging_fail_func)() = &logging_fail;
#endif
logging_fail_func_t g_logging_fail_func = &logging_fail;
void InstallFailureFunction(void (*fail_func)()) {
g_logging_fail_func = fail_func;
g_logging_fail_func = (logging_fail_func_t)fail_func;
}
void LogMessage::Fail() {
@ -1544,7 +1564,7 @@ static void GetTempDirectories(vector<string>* list) {
"/tmp",
};
for (int i = 0; i < ARRAYSIZE(candidates); i++) {
for (size_t i = 0; i < ARRAYSIZE(candidates); i++) {
const char *d = candidates[i];
if (!d) continue; // Empty env var
@ -1631,9 +1651,9 @@ void TruncateLogFile(const char *path, int64 limit, int64 keep) {
// rather scary.
// Instead just truncate the file to something we can manage
if (truncate(path, 0) == -1) {
PLOG(ERROR) << "Unable to truncate " << path;
PLOG(ERROR) << "Unable to truncate " << path;
} else {
LOG(ERROR) << "Truncated " << path << " due to EFBIG error";
LOG(ERROR) << "Truncated " << path << " due to EFBIG error";
}
} else {
PLOG(ERROR) << "Unable to open " << path;
@ -1769,7 +1789,7 @@ int posix_strerror_r(int err, char *buf, size_t len) {
}
LogMessageFatal::LogMessageFatal(const char* file, int line) :
LogMessage(file, line, FATAL) {}
LogMessage(file, line, GLOG_FATAL) {}
LogMessageFatal::LogMessageFatal(const char* file, int line,
const CheckOpString& result) :
@ -1780,4 +1800,15 @@ LogMessageFatal::~LogMessageFatal() {
LogMessage::Fail();
}
void InitGoogleLogging(const char* argv0) {
glog_internal_namespace_::InitGoogleLoggingUtilities(argv0);
}
void ShutdownGoogleLogging() {
glog_internal_namespace_::ShutdownGoogleLoggingUtilities();
LogDestination::DeleteLogDestinations();
delete logging_directories_list;
logging_directories_list = NULL;
}
_END_GOOGLE_NAMESPACE_

@ -151,7 +151,7 @@ void RawLog__(LogSeverity severity, const char* file, int line,
// libc (to side-step any libc interception).
// We write just once to avoid races with other invocations of RawLog__.
safe_write(STDERR_FILENO, buffer, strlen(buffer));
if (severity == FATAL) {
if (severity == GLOG_FATAL) {
if (!sync_val_compare_and_swap(&crashed, false, true)) {
crash_reason.filename = file;
crash_reason.line_number = line;

@ -34,7 +34,7 @@
#include "utilities.h"
#include "stacktrace.h"
#include "symbolize.h"
#include "glog/logging.h"
#include <glog/logging.h>
#include <signal.h>
#include <time.h>
@ -142,7 +142,9 @@ class MinimalFormatter {
// Writes the given data with the size to the standard error.
void WriteToStderr(const char* data, int size) {
write(STDERR_FILENO, data, size);
if (write(STDERR_FILENO, data, size) < 0) {
// Ignore errors.
}
}
// The writer function can be changed by InstallFailureWriter().
@ -167,7 +169,7 @@ void DumpTimeInfo() {
void DumpSignalInfo(int signal_number, siginfo_t *siginfo) {
// Get the signal name.
const char* signal_name = NULL;
for (int i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
if (signal_number == kFailureSignals[i].number) {
signal_name = kFailureSignals[i].name;
}
@ -336,7 +338,7 @@ void InstallFailureSignalHandler() {
sig_action.sa_flags |= SA_SIGINFO;
sig_action.sa_sigaction = &FailureSignalHandler;
for (int i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
for (size_t i = 0; i < ARRAYSIZE(kFailureSignals); ++i) {
CHECK_ERR(sigaction(kFailureSignals[i].number, &sig_action, NULL));
}
}

@ -37,7 +37,7 @@ extern "C" {
#define UNW_LOCAL_ONLY
#include <libunwind.h>
}
#include "glog/raw_logging.h"
#include <glog/raw_logging.h>
#include "stacktrace.h"
_START_GOOGLE_NAMESPACE_

@ -33,10 +33,6 @@
extern "C" {
#include <stdlib.h> // for NULL
#if defined(__FreeBSD__)
/* devel/libunwind only includes _Unwind_Backtrace if this is set */
#define _GNU_SOURCE 1
#endif
#include <unwind.h> // ABI defined unwinder
}
#include "stacktrace.h"

@ -82,8 +82,8 @@ static ATTRIBUTE_NOINLINE void DemangleInplace(char *out, int out_size) {
char demangled[256]; // Big enough for sane demangled symbols.
if (Demangle(out, demangled, sizeof(demangled))) {
// Demangling succeeded. Copy to out if the space allows.
int len = strlen(demangled);
if (len + 1 <= out_size) { // +1 for '\0'.
size_t len = strlen(demangled);
if (len + 1 <= (size_t)out_size) { // +1 for '\0'.
SAFE_ASSERT(len < sizeof(demangled));
memmove(out, demangled, len + 1);
}
@ -111,7 +111,7 @@ _END_GOOGLE_NAMESPACE_
#include "symbolize.h"
#include "config.h"
#include "glog/raw_logging.h"
#include <glog/raw_logging.h>
// Re-runs fn until it doesn't cause EINTR.
#define NO_INTR(fn) do {} while ((fn) < 0 && errno == EINTR)
@ -637,7 +637,7 @@ static ATTRIBUTE_NOINLINE bool SymbolizeAndDemangle(void *pc, char *out,
int out_size) {
Dl_info info;
if (dladdr(pc, &info)) {
if (strlen(info.dli_sname) < out_size) {
if ((int)strlen(info.dli_sname) < out_size) {
strcpy(out, info.dli_sname);
// Symbolization succeeded. Now we try to demangle the symbol.
DemangleInplace(out, out_size);

@ -56,7 +56,7 @@
#include "utilities.h"
#include "config.h"
#include "glog/logging.h"
#include <glog/logging.h>
#ifdef HAVE_SYMBOLIZE

@ -77,9 +77,11 @@ typedef void DebugWriter(const char*, void*);
// For some environments, add two extra bytes for the leading "0x".
static const int kPrintfPointerFieldWidth = 2 + 2 * sizeof(void*);
static void DebugWriteToStderr(const char* data, void *unused) {
static void DebugWriteToStderr(const char* data, void *) {
// This one is signal-safe.
write(STDERR_FILENO, data, strlen(data));
if (write(STDERR_FILENO, data, strlen(data)) < 0) {
// Ignore errors.
}
}
void DebugWriteToString(const char* data, void *arg) {
@ -221,8 +223,17 @@ int32 GetMainThreadPid() {
return g_main_thread_pid;
}
bool PidHasChanged() {
int32 pid = getpid();
if (g_main_thread_pid == pid) {
return false;
}
g_main_thread_pid = pid;
return true;
}
pid_t GetTID() {
// On Linux and FreeBSD, we try to use gettid().
// On Linux and MACOSX , we try to use gettid().
#if defined OS_LINUX || defined OS_MACOSX
#ifndef __NR_gettid
#ifdef OS_MACOSX
@ -245,7 +256,7 @@ pid_t GetTID() {
// the value change to "true".
lacks_gettid = true;
}
#endif // OS_LINUX || OS_FREEBSD
#endif // OS_LINUX || OS_MACOSX
// If gettid() could not be used, we use one of the following.
#if defined OS_LINUX
@ -302,9 +313,7 @@ void SetCrashReason(const CrashReason* r) {
r);
}
} // namespace glog_internal_namespace_
void InitGoogleLogging(const char* argv0) {
void InitGoogleLoggingUtilities(const char* argv0) {
CHECK(!IsGoogleLoggingInitialized())
<< "You called InitGoogleLogging() twice!";
const char* slash = strrchr(argv0, '/');
@ -319,14 +328,16 @@ void InitGoogleLogging(const char* argv0) {
#endif
}
void ShutdownGoogleLogging() {
void ShutdownGoogleLoggingUtilities() {
CHECK(IsGoogleLoggingInitialized())
<< "You called ShutdownGoogleLogging() without InitGoogleLogging() first!";
<< "You called ShutdownGoogleLogging() without calling InitGoogleLogging() first!";
#ifdef HAVE_SYSLOG_H
closelog();
#endif
}
} // namespace glog_internal_namespace_
_END_GOOGLE_NAMESPACE_
// Make an implementation of stacktrace compiled.

@ -161,6 +161,7 @@ typedef double WallTime;
WallTime WallTime_Now();
int32 GetMainThreadPid();
bool PidHasChanged();
pid_t GetTID();
@ -215,6 +216,9 @@ struct CrashReason {
void SetCrashReason(const CrashReason* r);
void InitGoogleLoggingUtilities(const char* argv0);
void ShutdownGoogleLoggingUtilities();
} // namespace glog_internal_namespace_
_END_GOOGLE_NAMESPACE_

@ -70,8 +70,8 @@ GOOGLE_GLOG_DLL_DECL bool SafeFNMatch_(const char* pattern,
size_t patt_len,
const char* str,
size_t str_len) {
int p = 0;
int s = 0;
size_t p = 0;
size_t s = 0;
while (1) {
if (p == patt_len && s == str_len) return true;
if (p == patt_len) return false;
@ -211,7 +211,7 @@ bool InitVLOG3__(int32** site_flag, int32* site_default,
const char* base = strrchr(fname, '/');
base = base ? (base+1) : fname;
const char* base_end = strchr(base, '.');
size_t base_length = base_end ? (base_end - base) : strlen(base);
size_t base_length = base_end ? size_t(base_end - base) : strlen(base);
// Trim out trailing "-inl" if any
if (base_length >= 4 && (memcmp(base+base_length-4, "-inl", 4) == 0)) {

@ -48,7 +48,15 @@
// you ever need to change their values or add a new severity.
typedef int LogSeverity;
const int INFO = 0, WARNING = 1, ERROR = 2, FATAL = 3, NUM_SEVERITIES = 4;
const int GLOG_INFO = 0, GLOG_WARNING = 1, GLOG_ERROR = 2, GLOG_FATAL = 3,
NUM_SEVERITIES = 4;
#ifndef GLOG_NO_ABBREVIATED_SEVERITIES
# ifdef ERROR
# error ERROR macro is defined. Define GLOG_NO_ABBREVIATED_SEVERITIES before including logging.h. See the document for detail.
# endif
const int INFO = GLOG_INFO, WARNING = GLOG_WARNING,
ERROR = GLOG_ERROR, FATAL = GLOG_FATAL;
#endif
// DFATAL is FATAL in debug mode, ERROR in normal mode
#ifdef NDEBUG

@ -83,7 +83,7 @@
#endif
#if 1
#include "third_party/gflags/gflags.h"
#include "third_party/gflags/gflags/gflags.h"
#endif
#ifdef __MINGW32__
@ -170,21 +170,21 @@ typedef uint64_t uint64;
// You can also do occasional logging (log every n'th occurrence of an
// event):
//
// LOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";
// LOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// The above will cause log messages to be output on the 1st, 11th, 21st, ...
// times it is executed. Note that the special COUNTER value is used to
// identify which repetition is happening.
// times it is executed. Note that the special google::COUNTER value is used
// to identify which repetition is happening.
//
// You can also do occasional conditional logging (log every n'th
// occurrence of an event, when condition is satisfied):
//
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << COUNTER
// LOG_IF_EVERY_N(INFO, (size > 1024), 10) << "Got the " << google::COUNTER
// << "th big cookie";
//
// You can log messages the first N times your code executes a line. E.g.
//
// LOG_FIRST_N(INFO, 20) << "Got the " << COUNTER << "th cookie";
// LOG_FIRST_N(INFO, 20) << "Got the " << google::COUNTER << "th cookie";
//
// Outputs log messages for the first 20 times it is executed.
//
@ -201,7 +201,7 @@ typedef uint64_t uint64;
//
// DLOG_IF(INFO, num_cookies > 10) << "Got lots of cookies";
//
// DLOG_EVERY_N(INFO, 10) << "Got the " << COUNTER << "th cookie";
// DLOG_EVERY_N(INFO, 10) << "Got the " << google::COUNTER << "th cookie";
//
// All "debug mode" logging is compiled away to nothing for non-debug mode
// compiles.
@ -245,11 +245,11 @@ typedef uint64_t uint64;
// "program with --v=1 or more";
// VLOG_EVERY_N(1, 10)
// << "I'm printed every 10th occurrence, and when you run the program "
// "with --v=1 or more. Present occurence is " << COUNTER;
// "with --v=1 or more. Present occurence is " << google::COUNTER;
// VLOG_IF_EVERY_N(1, (size > 1024), 10)
// << "I'm printed on every 10th occurence of case when size is more "
// " than 1024, when you run the program with --v=1 or more. ";
// "Present occurence is " << COUNTER;
// "Present occurence is " << google::COUNTER;
//
// The supported severity levels for macros that allow you to specify one
// are (in increasing order of severity) INFO, WARNING, ERROR, and FATAL.
@ -386,7 +386,7 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_INFO google::LogMessage( \
__FILE__, __LINE__)
#define LOG_TO_STRING_INFO(message) google::LogMessage( \
__FILE__, __LINE__, google::INFO, message)
__FILE__, __LINE__, google::GLOG_INFO, message)
#else
#define COMPACT_GOOGLE_LOG_INFO google::NullStream()
#define LOG_TO_STRING_INFO(message) google::NullStream()
@ -394,9 +394,9 @@ DECLARE_bool(stop_logging_if_full_disk);
#if GOOGLE_STRIP_LOG <= 1
#define COMPACT_GOOGLE_LOG_WARNING google::LogMessage( \
__FILE__, __LINE__, google::WARNING)
__FILE__, __LINE__, google::GLOG_WARNING)
#define LOG_TO_STRING_WARNING(message) google::LogMessage( \
__FILE__, __LINE__, google::WARNING, message)
__FILE__, __LINE__, google::GLOG_WARNING, message)
#else
#define COMPACT_GOOGLE_LOG_WARNING google::NullStream()
#define LOG_TO_STRING_WARNING(message) google::NullStream()
@ -404,9 +404,9 @@ DECLARE_bool(stop_logging_if_full_disk);
#if GOOGLE_STRIP_LOG <= 2
#define COMPACT_GOOGLE_LOG_ERROR google::LogMessage( \
__FILE__, __LINE__, google::ERROR)
__FILE__, __LINE__, google::GLOG_ERROR)
#define LOG_TO_STRING_ERROR(message) google::LogMessage( \
__FILE__, __LINE__, google::ERROR, message)
__FILE__, __LINE__, google::GLOG_ERROR, message)
#else
#define COMPACT_GOOGLE_LOG_ERROR google::NullStream()
#define LOG_TO_STRING_ERROR(message) google::NullStream()
@ -416,7 +416,7 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_FATAL google::LogMessageFatal( \
__FILE__, __LINE__)
#define LOG_TO_STRING_FATAL(message) google::LogMessage( \
__FILE__, __LINE__, google::FATAL, message)
__FILE__, __LINE__, google::GLOG_FATAL, message)
#else
#define COMPACT_GOOGLE_LOG_FATAL google::NullStreamFatal()
#define LOG_TO_STRING_FATAL(message) google::NullStreamFatal()
@ -428,32 +428,32 @@ DECLARE_bool(stop_logging_if_full_disk);
#define COMPACT_GOOGLE_LOG_DFATAL COMPACT_GOOGLE_LOG_ERROR
#elif GOOGLE_STRIP_LOG <= 3
#define COMPACT_GOOGLE_LOG_DFATAL google::LogMessage( \
__FILE__, __LINE__, google::FATAL)
__FILE__, __LINE__, google::GLOG_FATAL)
#else
#define COMPACT_GOOGLE_LOG_DFATAL google::NullStreamFatal()
#endif
#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::INFO, counter, &google::LogMessage::SendToLog)
#define GOOGLE_LOG_INFO(counter) google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, &google::LogMessage::SendToLog)
#define SYSLOG_INFO(counter) \
google::LogMessage(__FILE__, __LINE__, google::INFO, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_INFO, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_WARNING(counter) \
google::LogMessage(__FILE__, __LINE__, google::WARNING, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_WARNING, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_ERROR(counter) \
google::LogMessage(__FILE__, __LINE__, google::ERROR, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToLog)
#define SYSLOG_FATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::FATAL, counter, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_FATAL, counter, \
&google::LogMessage::SendToSyslogAndLog)
#define GOOGLE_LOG_DFATAL(counter) \
google::LogMessage(__FILE__, __LINE__, google::DFATAL_LEVEL, counter, \
@ -472,7 +472,7 @@ DECLARE_bool(stop_logging_if_full_disk);
FORMAT_MESSAGE_FROM_SYSTEM, \
0, result, 0, msg, 100, NULL); \
if (message_length > 0) { \
google::LogMessage(__FILE__, __LINE__, ERROR, 0, \
google::LogMessage(__FILE__, __LINE__, google::GLOG_ERROR, 0, \
&google::LogMessage::SendToLog).stream() << message; \
LocalFree(message); \
} \
@ -519,12 +519,12 @@ class LogSink; // defined below
#define LOG_TO_SINK(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::severity, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), true).stream()
#define LOG_TO_SINK_BUT_NOT_TO_LOGFILE(sink, severity) \
google::LogMessage( \
__FILE__, __LINE__, \
google::severity, \
google::GLOG_ ## severity, \
static_cast<google::LogSink*>(sink), false).stream()
// If a non-NULL string pointer is given, we write this message to that string.
@ -789,7 +789,7 @@ DECLARE_CHECK_STROP_IMPL(strcasecmp, false)
#define GOOGLE_PLOG(severity, counter) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::severity, counter, \
__FILE__, __LINE__, google::GLOG_ ## severity, counter, \
&google::LogMessage::SendToLog)
#define PLOG_IF(severity, condition) \
@ -828,7 +828,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_IF_EVERY_N(severity, condition, n, what_to_do) \
@ -837,7 +837,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (condition && \
((LOG_OCCURRENCES_MOD_N=(LOG_OCCURRENCES_MOD_N + 1) % n) == (1 % n))) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_PLOG_EVERY_N(severity, n, what_to_do) \
@ -846,7 +846,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
if (++LOG_OCCURRENCES_MOD_N > n) LOG_OCCURRENCES_MOD_N -= n; \
if (LOG_OCCURRENCES_MOD_N == 1) \
google::ErrnoLogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
#define SOME_KIND_OF_LOG_FIRST_N(severity, n, what_to_do) \
@ -855,7 +855,7 @@ PLOG_IF(FATAL, GOOGLE_PREDICT_BRANCH_NOT_TAKEN((invocation) == -1)) \
++LOG_OCCURRENCES; \
if (LOG_OCCURRENCES <= n) \
google::LogMessage( \
__FILE__, __LINE__, google::severity, LOG_OCCURRENCES, \
__FILE__, __LINE__, google::GLOG_ ## severity, LOG_OCCURRENCES, \
&what_to_do).stream()
namespace glog_internal_namespace_ {
@ -869,7 +869,7 @@ struct CrashReason;
typedef google::glog_internal_namespace_::CompileAssert<(bool(expr))> msg[bool(expr) ? 1 : -1]
#define LOG_EVERY_N(severity, n) \
GOOGLE_GLOG_COMPILE_ASSERT(google::severity < \
GOOGLE_GLOG_COMPILE_ASSERT(google::GLOG_ ## severity < \
google::NUM_SEVERITIES, \
INVALID_REQUESTED_LOG_SEVERITY); \
SOME_KIND_OF_LOG_EVERY_N(severity, (n), google::LogMessage::SendToLog)
@ -889,6 +889,27 @@ struct CrashReason;
// We want the special COUNTER value available for LOG_EVERY_X()'ed messages
enum PRIVATE_Counter {COUNTER};
#ifdef GLOG_NO_ABBREVIATED_SEVERITIES
// wingdi.h defines ERROR to be 0. When we call LOG(ERROR), it gets
// substituted with 0, and it expands to COMPACT_GOOGLE_LOG_0. To allow us
// to keep using this syntax, we define this macro to do the same thing
// as COMPACT_GOOGLE_LOG_ERROR.
#define COMPACT_GOOGLE_LOG_0 COMPACT_GOOGLE_LOG_ERROR
#define SYSLOG_0 SYSLOG_ERROR
#define LOG_TO_STRING_0 LOG_TO_STRING_ERROR
// Needed for LOG_IS_ON(ERROR).
const LogSeverity GLOG_0 = GLOG_ERROR;
#else
// Users may include windows.h after logging.h without
// GLOG_NO_ABBREVIATED_SEVERITIES nor WIN32_LEAN_AND_MEAN.
// For this case, we cannot detect if ERROR is defined before users
// actually use ERROR. Let's make an undefined symbol to warn users.
# define GLOG_ERROR_MSG ERROR_macro_is_defined_Define_GLOG_NO_ABBREVIATED_SEVERITIES_before_including_logging_h_See_the_document_for_detail
# define COMPACT_GOOGLE_LOG_0 GLOG_ERROR_MSG
# define SYSLOG_0 GLOG_ERROR_MSG
# define LOG_TO_STRING_0 GLOG_ERROR_MSG
# define GLOG_0 GLOG_ERROR_MSG
#endif
// Plus some debug-logging macros that get compiled to nothing for production
@ -1033,14 +1054,14 @@ public:
# pragma warning(default: 4275)
#endif
public:
LogStream(char *buf, int len, int ctr)
LogStream(char *buf, int len, int ctr_in)
: ostrstream(buf, len),
ctr_(ctr) {
ctr_(ctr_in) {
self_ = this;
}
int ctr() const { return ctr_; }
void set_ctr(int ctr) { ctr_ = ctr; }
void set_ctr(int ctr_in) { ctr_ = ctr_in; }
LogStream* self() const { return self_; }
private:
@ -1482,7 +1503,7 @@ class GOOGLE_GLOG_DLL_DECL NullStream : public LogMessage::LogStream {
// converted to LogStream and the message will be computed and then
// quietly discarded.
template<class T>
inline NullStream& operator<<(NullStream &str, const T &value) { return str; }
inline NullStream& operator<<(NullStream &str, const T &) { return str; }
// Similar to NullStream, but aborts the program (without stack
// trace), like LogMessageFatal.

@ -72,7 +72,7 @@ namespace google {
// I0821 211317 file.cc:142] RAW: status is 20
#define RAW_LOG(severity, ...) \
do { \
switch (google::severity) { \
switch (google::GLOG_ ## severity) { \
case 0: \
RAW_LOG_INFO(__VA_ARGS__); \
break; \
@ -104,28 +104,28 @@ namespace google {
#endif // STRIP_LOG == 0
#if STRIP_LOG == 0
#define RAW_LOG_INFO(...) google::RawLog__(google::INFO, \
#define RAW_LOG_INFO(...) google::RawLog__(google::GLOG_INFO, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_INFO(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG == 0
#if STRIP_LOG <= 1
#define RAW_LOG_WARNING(...) google::RawLog__(google::WARNING, \
#define RAW_LOG_WARNING(...) google::RawLog__(google::GLOG_WARNING, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_WARNING(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 1
#if STRIP_LOG <= 2
#define RAW_LOG_ERROR(...) google::RawLog__(google::ERROR, \
#define RAW_LOG_ERROR(...) google::RawLog__(google::GLOG_ERROR, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_ERROR(...) google::RawLogStub__(0, __VA_ARGS__)
#endif // STRIP_LOG <= 2
#if STRIP_LOG <= 3
#define RAW_LOG_FATAL(...) google::RawLog__(google::FATAL, \
#define RAW_LOG_FATAL(...) google::RawLog__(google::GLOG_FATAL, \
__FILE__, __LINE__, __VA_ARGS__)
#else
#define RAW_LOG_FATAL(...) \
@ -166,7 +166,7 @@ namespace google {
// Stub log function used to work around for unused variable warnings when
// building with STRIP_LOG > 0.
static inline void RawLogStub__(int ignored, ...) {
static inline void RawLogStub__(int /* ignored */, ...) {
}
// Helper function to implement RAW_LOG and RAW_VLOG

@ -59,16 +59,14 @@
* used by both C and C++ code, so we put all the C++ together.
*/
#if _MSC_VER
/* 4244: otherwise we get problems when substracting two size_t's to an int
* 4251: it's complaining about a private struct I've chosen not to dllexport
* 4355: we use this in a constructor, but we do it safely
* 4715: for some reason VC++ stopped realizing you can't return after abort()
* 4800: we know we're casting ints/char*'s to bools, and we're ok with that
* 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
*/
# pragma warning(disable:4244 4251 4355 4715 4800 4996)
#endif
/* 4244: otherwise we get problems when substracting two size_t's to an int
* 4251: it's complaining about a private struct I've chosen not to dllexport
* 4355: we use this in a constructor, but we do it safely
* 4715: for some reason VC++ stopped realizing you can't return after abort()
* 4800: we know we're casting ints/char*'s to bools, and we're ok with that
* 4996: Yes, we're ok using "unsafe" functions like fopen() and strerror()
*/
#pragma warning(disable:4244 4251 4355 4715 4800 4996)
/* file I/O */
#define PATH_MAX 1024

@ -465,7 +465,7 @@ int dtStatNavMesh::raycast(dtStatPolyRef centerRef, const float* startPos, const
if (!m_header) return 0;
if (!centerRef) return 0;
dtStatPolyRef prevRef = centerRef;
/* dtStatPolyRef prevRef = centerRef; */ /* UNUSED */
dtStatPolyRef curRef = centerRef;
t = 0;
@ -506,7 +506,7 @@ int dtStatNavMesh::raycast(dtStatPolyRef centerRef, const float* startPos, const
}
// No hit, advance to neighbour polygon.
prevRef = curRef;
/* prevRef = curRef; */ /* UNUSED */
curRef = nextRef;
}

@ -66,3 +66,8 @@ if(WITH_CYCLES)
add_subdirectory(cycles)
endif()
#Only Windows needs utf16 converter
if(WIN32)
add_subdirectory(utfconv)
endif()

@ -3,6 +3,7 @@ Import ('env')
SConscript(['audaspace/SConscript',
'string/SConscript',
'utfconv/SConscript',
'ghost/SConscript',
'guardedalloc/SConscript',
'moto/SConscript',

@ -49,6 +49,9 @@ bool AUD_SequencerReader::isSeekable() const
void AUD_SequencerReader::seek(int position)
{
if(position < 0)
return;
m_position = position;
for(AUD_HandleIterator it = m_handles.begin(); it != m_handles.end(); it++)

@ -771,7 +771,7 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
// prepare operands for actual boolean operation. it's needed because operands might consist of
// several intersecting meshes and in case if another operands intersect an edge loop of intersecting that
// meshes tesselation of operation result can't be done properly. the only way to make such situations
// meshes tessellation of operation result can't be done properly. the only way to make such situations
// working is to union intersecting meshes of the same operand
Carve_unionIntersections(&left, &right, oface_num);

@ -173,7 +173,7 @@ void BOP_triangulateC(BOP_Mesh* mesh, BOP_Faces* faces, BOP_Face* face, BOP_Inde
/**
* Triangulates the face (v1,v2,v3) in five new faces by two inner points (v4,v5), where
* v1 v4 v5 defines the nice triangle and v4 v5 v2 v3 defines the quad to be tesselated.
* v1 v4 v5 defines the nice triangle and v4 v5 v2 v3 defines the quad to be tessellated.
* @param mesh mesh that contains the faces, edges and vertices
* @param faces set of faces that contains face and will contains new faces
* @param face input face to be triangulate

@ -678,7 +678,7 @@ static void xml_read_mesh(const XMLReadState& state, pugi::xml_node node)
//dsplit.dicing_rate = 5.0f;
dsplit.dicing_rate = state.dicing_rate;
xml_read_float(&dsplit.dicing_rate, node, "dicing_rate");
sdmesh.tesselate(&dsplit, false, mesh, shader, smooth);
sdmesh.tessellate(&dsplit, false, mesh, shader, smooth);
}
else {
/* create vertices */

@ -22,7 +22,7 @@ bl_info = {
"name": "Cycles Render Engine",
"author": "",
"version": (0, 0),
"blender": (2, 6, 0),
"blender": (2, 6, 2),
"location": "Info header, render engine menu",
"description": "Cycles Render Engine integration.",
"warning": "",

@ -527,9 +527,9 @@ class CyclesWorld_PT_ambient_occlusion(CyclesButtonsPanel, Panel):
layout.active = light.use_ambient_occlusion
split = layout.split()
split.prop(light, "ao_factor", text="Factor")
split.prop(light, "distance", text="Distance")
row = layout.row()
row.prop(light, "ao_factor", text="Factor")
row.prop(light, "distance", text="Distance")
class CyclesWorld_PT_settings(CyclesButtonsPanel, Panel):
@ -649,7 +649,6 @@ class CyclesTexture_PT_context(CyclesButtonsPanel, Panel):
pin_id = space.pin_id
use_pin_id = space.use_pin_id
user = context.texture_user
# node = context.texture_node
if not use_pin_id or not isinstance(pin_id, bpy.types.Texture):
pin_id = None

@ -73,10 +73,10 @@ static void create_mesh(Scene *scene, Mesh *mesh, BL::Mesh b_mesh, const vector<
*N= get_float3(v->normal());
/* create faces */
BL::Mesh::faces_iterator f;
BL::Mesh::tessfaces_iterator f;
vector<int> nverts;
for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
int4 vi = get_int4(f->vertices_raw());
int n = (vi[3] == 0)? 3: 4;
int mi = clamp(f->material_index(), 0, used_shaders.size()-1);
@ -196,9 +196,9 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
sdmesh.add_vert(get_float3(v->co()));
/* create faces */
BL::Mesh::faces_iterator f;
BL::Mesh::tessfaces_iterator f;
for(b_mesh.faces.begin(f); f != b_mesh.faces.end(); ++f) {
for(b_mesh.tessfaces.begin(f); f != b_mesh.tessfaces.end(); ++f) {
int4 vi = get_int4(f->vertices_raw());
int n= (vi[3] == 0)? 3: 4;
//int shader = used_shaders[f->material_index()];
@ -217,7 +217,7 @@ static void create_subd_mesh(Mesh *mesh, BL::Mesh b_mesh, PointerRNA *cmesh, con
dsplit.camera = NULL;
dsplit.dicing_rate = RNA_float_get(cmesh, "dicing_rate");
sdmesh.tesselate(&dsplit, false, mesh, used_shaders[0], true);
sdmesh.tessellate(&dsplit, false, mesh, used_shaders[0], true);
}
/* Sync */

@ -192,6 +192,7 @@ void BlenderSync::sync_render_layers(BL::SpaceView3D b_v3d, const char *layer)
if(b_v3d) {
render_layer.scene_layer = get_layer(b_v3d.layers());
render_layer.layer = render_layer.scene_layer;
render_layer.holdout_layer = 0;
render_layer.material_override = PointerRNA_NULL;
}
else {

@ -106,7 +106,7 @@ private:
struct RenderLayerInfo {
RenderLayerInfo()
: scene_layer(0), layer(0),
: scene_layer(0), layer(0), holdout_layer(0),
material_override(PointerRNA_NULL)
{}

@ -151,26 +151,20 @@ __device_inline void path_radiance_bsdf_bounce(PathRadiance *L, float3 *throughp
#ifdef __PASSES__
if(L->use_light_pass) {
if(bounce == 0) {
if(bsdf_label & LABEL_TRANSPARENT) {
/* transparent bounce before first hit */
*throughput *= bsdf_eval->transparent*inverse_pdf;
}
else {
/* first on directly visible surface */
float3 value = *throughput*inverse_pdf;
if(bounce == 0 && !(bsdf_label & LABEL_TRANSPARENT)) {
/* first on directly visible surface */
float3 value = *throughput*inverse_pdf;
L->indirect_diffuse = bsdf_eval->diffuse*value;
L->indirect_glossy = bsdf_eval->glossy*value;
L->indirect_transmission = bsdf_eval->transmission*value;
L->indirect_diffuse = bsdf_eval->diffuse*value;
L->indirect_glossy = bsdf_eval->glossy*value;
L->indirect_transmission = bsdf_eval->transmission*value;
*throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
L->direct_throughput = *throughput;
}
*throughput = L->indirect_diffuse + L->indirect_glossy + L->indirect_transmission;
L->direct_throughput = *throughput;
}
else {
/* indirectly visible through BSDF */
/* transparent bounce before first hit, or indirectly visible through BSDF */
float3 sum = (bsdf_eval->diffuse + bsdf_eval->glossy + bsdf_eval->transmission + bsdf_eval->transparent)*inverse_pdf;
*throughput *= sum;
}

@ -146,10 +146,10 @@ __device void camera_sample_environment(KernelGlobals *kg, float raster_x, float
ray->dP.dy = make_float3(0.0f, 0.0f, 0.0f);
Pcamera = transform(&rastertocamera, make_float3(raster_x + 1.0f, raster_y, 0.0f));
ray->dD.dx = equirectangular_to_direction(Pcamera.x, Pcamera.y) - ray->D;
ray->dD.dx = normalize(transform_direction(&cameratoworld, equirectangular_to_direction(Pcamera.x, Pcamera.y))) - ray->D;
Pcamera = transform(&rastertocamera, make_float3(raster_x, raster_y + 1.0f, 0.0f));
ray->dD.dy = equirectangular_to_direction(Pcamera.x, Pcamera.y) - ray->D;
ray->dD.dy = normalize(transform_direction(&cameratoworld, equirectangular_to_direction(Pcamera.x, Pcamera.y))) - ray->D;
#endif
#ifdef __CAMERA_CLIPPING__

@ -288,7 +288,6 @@ __device float4 kernel_path_integrate(KernelGlobals *kg, RNG *rng, int sample, R
throughput /= probability;
#ifdef __AO__
/* ambient occlusion */
if(kernel_data.integrator.use_ambient_occlusion) {

@ -16,7 +16,7 @@ set(SRC
buffers.cpp
camera.cpp
film.cpp
# film_response.cpp # XXX, why isnt this in?
# film_response.cpp # XXX, why isn't this in?
filter.cpp
graph.cpp
image.cpp
@ -41,7 +41,7 @@ set(SRC_HEADERS
buffers.h
camera.h
film.h
# film_response.h # XXX, why isnt this in?
# film_response.h # XXX, why isn't this in?
filter.h
graph.h
image.h

@ -19,8 +19,8 @@
#ifndef __SUBD_DICE_H__
#define __SUBD_DICE_H__
/* DX11 like EdgeDice implementation, with different tesselation factors for
* each edge for watertight tesselation, with subpatch remapping to work with
/* DX11 like EdgeDice implementation, with different tessellation factors for
* each edge for watertight tessellation, with subpatch remapping to work with
* DiagSplit. For more algorithm details, see the DiagSplit paper or the
* ARB_tessellation_shader OpenGL extension, Section 2.X.2. */
@ -59,7 +59,7 @@ public:
/* Quad EdgeDice
*
* Edge tesselation factors and subpatch coordinates are as follows:
* Edge tessellation factors and subpatch coordinates are as follows:
*
* tu1
* P01 --------- P11
@ -115,7 +115,7 @@ public:
/* Triangle EdgeDice
*
* Edge tesselation factors and subpatch coordinates are as follows:
* Edge tessellation factors and subpatch coordinates are as follows:
*
* Pw
* /\

@ -285,7 +285,7 @@ void SubdMesh::link_boundary_edge(SubdEdge *edge)
edge->vert->edge = edge;
}
void SubdMesh::tesselate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
void SubdMesh::tessellate(DiagSplit *split, bool linear, Mesh *mesh, int shader, bool smooth)
{
SubdBuilder *builder = SubdBuilder::create(linear);
int num_faces = faces.size();

@ -61,7 +61,7 @@ public:
SubdFace *add_face(int *index, int num);
bool link_boundary();
void tesselate(DiagSplit *split, bool linear,
void tessellate(DiagSplit *split, bool linear,
Mesh *mesh, int shader, bool smooth);
protected:

@ -20,7 +20,7 @@
#define __SUBD_SPLIT_H__
/* DiagSplit: Parallel, Crack-free, Adaptive Tessellation for Micropolygon Rendering
* Splits up patches and determines edge tesselation factors for dicing. Patch
* Splits up patches and determines edge tessellation factors for dicing. Patch
* evaluation at arbitrary points is required for this to work. See the paper
* for more details. */

@ -265,8 +265,10 @@ BuildHeap(
// load in edge pointers to the heap
std::vector<LOD_Edge> & edge_set= m_mesh.EdgeSet();
std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end();
std::vector<LOD_Edge>::iterator edge_start = edge_set.begin();
// UNUSED
// std::vector<LOD_Edge>::const_iterator edge_end = edge_set.end();
// std::vector<LOD_Edge>::iterator edge_start = edge_set.begin();
std::vector<int> & heap_vector = m_heap->HeapVector();

@ -281,6 +281,10 @@ elseif(WIN32)
${WINTAB_INC}
)
list(APPEND INC
../utfconv
)
list(APPEND SRC
intern/GHOST_DisplayManagerWin32.cpp
intern/GHOST_SystemWin32.cpp

@ -842,6 +842,14 @@ extern void GHOST_putClipboard(GHOST_TInt8 *buffer, int selection);
*/
extern int GHOST_toggleConsole(int action);
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
extern int GHOST_confirmQuit(GHOST_WindowHandle windowhandle);
#ifdef __cplusplus
}
#endif

@ -82,7 +82,7 @@ class GHOST_IEventConsumer;
* <li> OSX Carbon.</li>
* <li> Windows.</li>
* <li> X11.</li>
* <li> SDL1.3 (experemental).</li>
* <li> SDL1.3 (experimental).</li>
* <li> NULL (headless mode).</li>
* </ul>
*
@ -392,7 +392,11 @@ public:
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
virtual int confirmQuit(GHOST_IWindow * window) const = 0;
protected:
/**
* Initialize the system.

@ -110,6 +110,7 @@ else:
if window_system in ('win32-vc', 'win32-mingw', 'cygwin', 'linuxcross', 'win64-vc'):
incs = env['BF_WINTAB_INC'] + ' ' + incs
incs += ' ../utfconv'
if window_system in ('win32-vc', 'win64-vc'):
env.BlenderLib ('bf_intern_ghost', sources, Split(incs), defines=defs, libtype=['intern','player'], priority = [40,15]) #, cc_compileflags=env['CCFLAGS'].append('/WX') )

@ -865,3 +865,9 @@ int GHOST_toggleConsole(int action)
GHOST_ISystem* system = GHOST_ISystem::getSystem();
return system->toggleConsole(action);
}
int GHOST_confirmQuit(GHOST_WindowHandle windowhandle){
GHOST_ISystem* system = GHOST_ISystem::getSystem();
return system->confirmQuit((GHOST_IWindow*) windowhandle);
}

@ -32,12 +32,14 @@
#include "GHOST_SystemSDL.h"
#include "GHOST_DisplayManagerSDL.h"
#include "GHOST_WindowManager.h"
GHOST_DisplayManagerSDL::GHOST_DisplayManagerSDL(GHOST_SystemSDL *system)
:
GHOST_DisplayManager(),
m_system(system)
{
/* do nothing */
memset(&m_mode, 0, sizeof m_mode);
}
GHOST_TSuccess
@ -52,22 +54,29 @@ GHOST_TSuccess GHOST_DisplayManagerSDL::getNumDisplaySettings(GHOST_TUns8 displa
GHOST_TInt32& numSettings) const
{
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
int i;
SDL_Rect **vidmodes;
vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
SDL_FULLSCREEN | SDL_HWPALETTE);
if (!vidmodes) {
fprintf(stderr, "Could not get available video modes: %s.\n",
SDL_GetError());
return GHOST_kFailure;
}
for (i = 0; vidmodes[i]; i++);
numSettings = GHOST_TInt32(i);
numSettings = SDL_GetNumDisplayModes(display - 1);
return GHOST_kSuccess;
}
static void ghost_mode_from_sdl(GHOST_DisplaySetting& setting, SDL_DisplayMode *mode)
{
setting.xPixels = mode->w;
setting.yPixels = mode->h;
setting.bpp = SDL_BYTESPERPIXEL(mode->format) * 8;
/* Just guess the frequency :( */
setting.frequency = mode->refresh_rate ? mode->refresh_rate : 60;
}
static void ghost_mode_to_sdl(const GHOST_DisplaySetting& setting, SDL_DisplayMode *mode)
{
mode->w = setting.xPixels;
mode->h = setting.yPixels;
// setting.bpp = SDL_BYTESPERPIXEL(mode->format) * 8; ???
mode->refresh_rate = setting.frequency;
}
GHOST_TSuccess
GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
GHOST_TInt32 index,
@ -75,36 +84,10 @@ GHOST_DisplayManagerSDL::getDisplaySetting(GHOST_TUns8 display,
{
GHOST_ASSERT(display < 1, "Only single display systems are currently supported.\n");
int i;
SDL_Rect **vidmodes;
/* NULL is passed in here to get the modes for the current bit depth.
* Other bit depths may be possible; in that case, an SDL_PixelFormat struct
* should be passed in. To get a complete profile, all possible bit depths
* would need to be iterated over. - z0r */
vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
SDL_FULLSCREEN | SDL_HWPALETTE);
if (!vidmodes) {
fprintf(stderr, "Could not get available video modes: %s.\n",
SDL_GetError());
return GHOST_kFailure;
}
for (i = 0; vidmodes[i]; i++);
GHOST_ASSERT(index < i, "Requested setting outside of valid range.\n");
SDL_DisplayMode mode;
SDL_GetDisplayMode(display, index, &mode);
setting.xPixels = vidmodes[index]->w;
setting.yPixels = vidmodes[index]->h;
SDL_Surface *surf;
surf = SDL_GetVideoSurface();
if (surf == NULL) {
fprintf(stderr, "Getting display setting: %s\n", SDL_GetError());
/* Just guess the bit depth */
setting.bpp = 32;
} else {
setting.bpp = surf->format->BitsPerPixel;
}
/* Just guess the frequency :( */
setting.frequency = 60;
ghost_mode_from_sdl(setting, &mode);
return GHOST_kSuccess;
}
@ -113,31 +96,18 @@ GHOST_TSuccess
GHOST_DisplayManagerSDL::getCurrentDisplaySetting(GHOST_TUns8 display,
GHOST_DisplaySetting& setting) const
{
SDL_Surface *surf;
const SDL_VideoInfo *info;
SDL_DisplayMode mode;
SDL_GetCurrentDisplayMode(display, &mode);
/* Note: not using SDL_GetDesktopDisplayMode because that does not return
* the current mode. Try to use GetVideoSurface first, as it seems more
* accurate. If that fails, try other methods. - z0r */
surf = SDL_GetVideoSurface();
ghost_mode_from_sdl(setting, &mode);
if (surf != NULL) {
setting.xPixels = surf->w;
setting.yPixels = surf->h;
setting.bpp = surf->format->BitsPerPixel;
/* Just guess the frequency :( */
setting.frequency = 60;
} else {
/* This may happen if the surface hasn't been created yet, e.g. on
* application startup. */
info = SDL_GetVideoInfo();
setting.xPixels = info->current_w;
setting.yPixels = info->current_h;
setting.bpp = info->vfmt->BitsPerPixel;
/* Just guess the frequency :( */
setting.frequency = 60;
}
return GHOST_kSuccess;
}
GHOST_TSuccess
GHOST_DisplayManagerSDL::getCurrentDisplayModeSDL(SDL_DisplayMode &mode) const
{
mode = m_mode;
return GHOST_kSuccess;
}
@ -145,7 +115,6 @@ GHOST_TSuccess
GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display,
const GHOST_DisplaySetting& setting)
{
/*
* Mode switching code ported from Quake 2 version 3.21 and bzflag version
* 2.4.0:
@ -154,31 +123,28 @@ GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display,
* http://wiki.bzflag.org/BZFlag_Source
* See src/platform/SDLDisplay.cxx:SDLDisplay and createWindow
*/
SDL_Surface *surf;
SDL_DisplayMode mode;
const int num_modes = SDL_GetNumDisplayModes(display);
int best_fit, best_dist, dist, x, y;
SDL_Rect **vidmodes = SDL_ListModes(NULL, SDL_HWSURFACE | SDL_OPENGL |
SDL_FULLSCREEN | SDL_HWPALETTE);
if (!vidmodes) {
fprintf(stderr, "Could not get available video modes: %s.\n",
SDL_GetError());
}
best_dist = 9999999;
best_fit = -1;
if (vidmodes == (SDL_Rect **) -1) {
if (num_modes == 0) {
/* Any mode is OK. */
x = setting.xPixels;
y = setting.yPixels;
} else {
for (int i = 0; vidmodes[i]; i++) {
if (setting.xPixels > vidmodes[i]->w ||
setting.yPixels > vidmodes[i]->h)
ghost_mode_to_sdl(setting, &mode);
}
else {
for (int i = 0; i < num_modes; i++) {
SDL_GetDisplayMode(display, i, &mode);
if (setting.xPixels > mode.w ||
setting.yPixels > mode.h)
continue;
x = setting.xPixels - vidmodes[i]->w;
y = setting.yPixels - vidmodes[i]->h;
x = setting.xPixels - mode.w;
y = setting.yPixels - mode.h;
dist = (x * x) + (y * y);
if (dist < best_dist) {
best_dist = dist;
@ -189,24 +155,30 @@ GHOST_DisplayManagerSDL:: setCurrentDisplaySetting(GHOST_TUns8 display,
if (best_fit == -1)
return GHOST_kFailure;
x = vidmodes[best_fit]->w;
y = vidmodes[best_fit]->h;
SDL_GetDisplayMode(display, best_fit, &mode);
}
# ifdef _DEBUG
printf("Switching to video mode %dx%d\n", x, y);
# endif
m_mode = mode;
// limit us to the main display
static char singleDisplayEnv[] = "SDL_SINGLEDISPLAY=1";
putenv(singleDisplayEnv);
/* evil, SDL2 needs a window to adjust display modes */
GHOST_WindowSDL *win = (GHOST_WindowSDL *)m_system->getWindowManager()->getActiveWindow();
// change to the mode
surf = SDL_SetVideoMode(x, y, setting.bpp, SDL_OPENGL | SDL_FULLSCREEN);
if (surf == NULL) {
fprintf(stderr, "Could not set video mode: %s.\n", SDL_GetError());
return GHOST_kFailure;
if (win) {
SDL_Window *sdl_win = win->getSDLWindow();
SDL_SetWindowDisplayMode(sdl_win, &mode);
SDL_ShowWindow(sdl_win);
SDL_SetWindowFullscreen(sdl_win, SDL_TRUE);
return GHOST_kSuccess;
}
else {
/* this is a problem for the BGE player :S, perhaps SDL2 will resolve at some point.
* we really need SDL_SetDisplayModeForDisplay() to become an API func! - campbell */
printf("no windows available, cant fullscreen");
return GHOST_kSuccess;
/* do not fail, we will try again later when the window is created - wander */
return GHOST_kSuccess;
}
}

@ -34,8 +34,8 @@ extern "C" {
#include "SDL.h"
}
#if !SDL_VERSION_ATLEAST(1, 3, 0)
# error "SDL 1.3 or newer is needed to build with Ghost"
#if !SDL_VERSION_ATLEAST(2, 0, 0)
# error "SDL 2.0 or newer is needed to build with Ghost"
#endif
class GHOST_SystemSDL;
@ -61,12 +61,16 @@ public:
getCurrentDisplaySetting(GHOST_TUns8 display,
GHOST_DisplaySetting& setting) const;
GHOST_TSuccess
getCurrentDisplayModeSDL(SDL_DisplayMode &mode) const;
GHOST_TSuccess
setCurrentDisplaySetting(GHOST_TUns8 display,
const GHOST_DisplaySetting& setting);
private :
GHOST_SystemSDL * m_system;
SDL_DisplayMode m_mode;
};
#endif /* __GHOST_DISPLAYMANAGERSDL_H__ */

@ -34,6 +34,9 @@
#include "GHOST_DropTargetWin32.h"
#include <ShellApi.h>
#include "utf_winfunc.h"
#include "utfconv.h"
#ifdef GHOST_DEBUG
// utility
void printLastError(void);
@ -267,20 +270,12 @@ void * GHOST_DropTargetWin32::getDropDataAsFilenames(IDataObject * pDataObject)
{
if ( ::DragQueryFileW ( hdrop, nfile, fpath, MAX_PATH ) > 0 )
{
if ( !WideCharToANSI(fpath, temp_path) )
if ( !(temp_path = alloc_utf_8_from_16(fpath, 0)) )
{
continue;
}
// Just ignore paths that could not be converted verbatim.
if (strpbrk(temp_path, "?"))
{
#ifdef GHOST_DEBUG
::printf("\ndiscarding path that contains illegal characters: %s", temp_path);
#endif // GHOST_DEBUG
::free(temp_path);
temp_path = NULL;
continue;
}
strArray->strings[nvalid] = (GHOST_TUns8*) temp_path;
strArray->count = nvalid+1;
nvalid++;
@ -309,7 +304,7 @@ void * GHOST_DropTargetWin32::getDropDataAsString(IDataObject * pDataObject)
if(pDataObject->GetData(&fmtetc, &stgmed) == S_OK)
{
LPCWSTR wstr = (LPCWSTR)::GlobalLock(stgmed.hGlobal);
if ( !WideCharToANSI(wstr, tmp_string) )
if ( !(tmp_string = alloc_utf_8_from_16((wchar_t*)wstr, 0)) )
{
::GlobalUnlock(stgmed.hGlobal);
return NULL;

@ -366,3 +366,9 @@ GHOST_TSuccess GHOST_System::createFullScreenWindow(GHOST_Window** window, const
}
return success;
}
int GHOST_System::confirmQuit(GHOST_IWindow * window) const
{
return 1;
}

@ -297,6 +297,13 @@ public:
*/
virtual void putClipboard(GHOST_TInt8 *buffer, bool selection) const = 0;
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
virtual int confirmQuit(GHOST_IWindow * window) const;
protected:
/**

@ -35,6 +35,7 @@
#define _WIN32_IE 0x0501
#endif
#include <shlobj.h>
#include "utfconv.h"
#if defined(__MINGW32__) || defined(__CYGWIN__)
@ -70,11 +71,14 @@ GHOST_SystemPathsWin32::~GHOST_SystemPathsWin32()
const GHOST_TUns8* GHOST_SystemPathsWin32::getSystemDir() const
{
static char knownpath[MAX_PATH];
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
static char knownpath[MAX_PATH*3] = {0}; /* 1 utf-16 might translante into 3 utf-8. 2 utf-16 translates into 4 utf-8*/
wchar_t knownpath_16[MAX_PATH];
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_COMMON_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
if (hResult == S_OK)
{
conv_utf_16_to_8(knownpath_16,knownpath,MAX_PATH*3);
return (GHOST_TUns8*)knownpath;
}
@ -83,11 +87,14 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getSystemDir() const
const GHOST_TUns8* GHOST_SystemPathsWin32::getUserDir() const
{
static char knownpath[MAX_PATH];
HRESULT hResult = SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath);
static char knownpath[MAX_PATH*3] = {0};
wchar_t knownpath_16[MAX_PATH];
HRESULT hResult = SHGetFolderPathW(NULL, CSIDL_APPDATA, NULL, SHGFP_TYPE_CURRENT, knownpath_16);
if (hResult == S_OK)
{
conv_utf_16_to_8(knownpath_16,knownpath,MAX_PATH*3);
return (GHOST_TUns8*)knownpath;
}
@ -96,8 +103,11 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getUserDir() const
const GHOST_TUns8* GHOST_SystemPathsWin32::getBinaryDir() const
{
static char fullname[MAX_PATH];
if(GetModuleFileName(0, fullname, MAX_PATH)) {
static char fullname[MAX_PATH*3] = {0};
wchar_t fullname_16[MAX_PATH*3];
if(GetModuleFileNameW(0, fullname_16, MAX_PATH)) {
conv_utf_16_to_8(fullname_16,fullname,MAX_PATH*3);
return (GHOST_TUns8*)fullname;
}
@ -107,5 +117,7 @@ const GHOST_TUns8* GHOST_SystemPathsWin32::getBinaryDir() const
void GHOST_SystemPathsWin32::addToSystemRecentFiles(const char* filename) const
{
/* SHARD_PATH resolves to SHARD_PATHA for non-UNICODE build */
SHAddToRecentDocs(SHARD_PATH,filename);
UTF16_ENCODE(filename)
SHAddToRecentDocs(SHARD_PATHW,filename_16);
UTF16_UN_ENCODE(filename)
}

@ -76,6 +76,17 @@ GHOST_SystemSDL::createWindow(const STR_String& title,
window= new GHOST_WindowSDL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1);
if (window) {
if (GHOST_kWindowStateFullScreen == state) {
SDL_Window *sdl_win = window->getSDLWindow();
SDL_DisplayMode mode;
static_cast<GHOST_DisplayManagerSDL *> (m_displayManager)->getCurrentDisplayModeSDL(mode);
SDL_SetWindowDisplayMode(sdl_win, &mode);
SDL_ShowWindow(sdl_win);
SDL_SetWindowFullscreen(sdl_win, SDL_TRUE);
}
if (window->getValid()) {
m_windowManager->addWindow(window);
pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window));
@ -481,8 +492,8 @@ GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x,
bool
GHOST_SystemSDL::generateWindowExposeEvents()
{
vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin();
vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end();
std::vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin();
std::vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end();
bool anyProcessed= false;
for (;w_start != w_end; ++w_start) {
@ -563,10 +574,10 @@ GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
// We should always check the window manager's list of windows
// and only process events on these windows.
vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows();
std::vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows();
vector<GHOST_IWindow *>::iterator win_it= win_vec.begin();
vector<GHOST_IWindow *>::const_iterator win_end= win_vec.end();
std::vector<GHOST_IWindow *>::iterator win_it= win_vec.begin();
std::vector<GHOST_IWindow *>::const_iterator win_end= win_vec.end();
for (; win_it != win_end; ++win_it) {
GHOST_WindowSDL * window= static_cast<GHOST_WindowSDL *>(*win_it);

@ -39,8 +39,8 @@ extern "C" {
#include "SDL.h"
}
#if !SDL_VERSION_ATLEAST(1, 3, 0)
# error "SDL 1.3 or newer is needed to build with Ghost"
#if !SDL_VERSION_ATLEAST(2, 0, 0)
# error "SDL 2.0 or newer is needed to build with Ghost"
#endif

@ -60,6 +60,8 @@
#endif
#endif
#include "utfconv.h"
#include "GHOST_DisplayManagerWin32.h"
#include "GHOST_EventButton.h"
#include "GHOST_EventCursor.h"
@ -292,8 +294,8 @@ bool GHOST_SystemWin32::processEvents(bool waitForEvent)
}
// Process all the events waiting for us
while (::PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0) {
::DispatchMessage(&msg);
while (::PeekMessageW(&msg, 0, 0, 0, PM_REMOVE) != 0) {
::DispatchMessageW(&msg);
anyProcessed = true;
}
} while (waitForEvent && !anyProcessed);
@ -394,7 +396,7 @@ GHOST_TSuccess GHOST_SystemWin32::init()
}
if (success) {
WNDCLASS wc;
WNDCLASSW wc;
wc.style= CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc= s_wndProc;
wc.cbClsExtra= 0;
@ -408,10 +410,10 @@ GHOST_TSuccess GHOST_SystemWin32::init()
wc.hCursor = ::LoadCursor(0, IDC_ARROW);
wc.hbrBackground= (HBRUSH)::GetStockObject(BLACK_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName= GHOST_WindowWin32::getWindowClassName();
wc.lpszClassName= L"GHOST_WindowClass";
// Use RegisterClassEx for setting small icon
if (::RegisterClass(&wc) == 0) {
if (::RegisterClassW(&wc) == 0) {
success = GHOST_kFailure;
}
}
@ -719,15 +721,17 @@ GHOST_EventKey* GHOST_SystemWin32::processKeyEvent(GHOST_IWindow *window, RAWINP
char utf8_char[6] = {0};
char ascii = 0;
wchar_t utf16[2]={0};
wchar_t utf16[3]={0};
BYTE state[256] ={0};
GetKeyboardState(state);
int r;
GetKeyboardState((PBYTE)state);
if(ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))
WideCharToMultiByte(CP_UTF8, 0,
(wchar_t*)utf16, 1,
(LPSTR) utf8_char, 5,
NULL,NULL); else *utf8_char = 0;
if(r = ToUnicodeEx(vk, 0, state, utf16, 2, 0, system->m_keylayout))
if((r>0 && r<3)){utf16[r]=0;
conv_utf_16_to_8(utf16,utf8_char,6);}
else if (r==-1) utf8_char[0] = '\0';
@ -1189,8 +1193,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
* DefWindowProc returns.
*/
break;
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
// Other events
////////////////////////////////////////////////////////////////////////
case WM_GETTEXT:
@ -1239,17 +1242,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
}
if (!eventHandled)
lResult = ::DefWindowProc(hwnd, msg, wParam, lParam);
lResult = ::DefWindowProcW(hwnd, msg, wParam, lParam);
return lResult;
}
GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const
{
wchar_t *buffer;
char *temp_buff;
if ( IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL) ) {
wchar_t *buffer;
size_t len = 0;
HANDLE hData = GetClipboardData( CF_UNICODETEXT );
if (hData == NULL) {
@ -1262,9 +1265,32 @@ GHOST_TUns8* GHOST_SystemWin32::getClipboard(bool selection) const
return NULL;
}
len = WideCharToMultiByte(CP_UTF8, 0, buffer, -1, NULL, 0, NULL, NULL);
temp_buff = (char*) malloc(len);
WideCharToMultiByte(CP_UTF8, 0, buffer, -1, temp_buff, len, NULL, NULL);
temp_buff = alloc_utf_8_from_16(buffer,0);
/* Buffer mustn't be accessed after CloseClipboard
it would like accessing free-d memory */
GlobalUnlock( hData );
CloseClipboard();
return (GHOST_TUns8*)temp_buff;
} else if ( IsClipboardFormatAvailable(CF_TEXT) && OpenClipboard(NULL) ) {
char *buffer;
size_t len = 0;
HANDLE hData = GetClipboardData( CF_TEXT );
if (hData == NULL) {
CloseClipboard();
return NULL;
}
buffer = (char*)GlobalLock( hData );
if (!buffer) {
CloseClipboard();
return NULL;
}
len = strlen(buffer);
temp_buff = (char*) malloc(len+1);
strncpy(temp_buff, buffer, len);
temp_buff[len] = '\0';
/* Buffer mustn't be accessed after CloseClipboard
it would like accessing free-d memory */
@ -1281,20 +1307,19 @@ void GHOST_SystemWin32::putClipboard(GHOST_TInt8 *buffer, bool selection) const
{
if(selection) {return;} // for copying the selection, used on X11
if (OpenClipboard(NULL)) {
if(OpenClipboard(NULL)) {
HLOCAL clipbuffer;
wchar_t *data;
if (buffer) {
size_t len = count_utf_16_from_8(buffer);
EmptyClipboard();
int wlen = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, NULL, 0);
clipbuffer = LocalAlloc(LMEM_FIXED, wlen * sizeof(wchar_t));
clipbuffer = LocalAlloc(LMEM_FIXED,sizeof(wchar_t) * len);
data = (wchar_t*)GlobalLock(clipbuffer);
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, data, wlen);
conv_utf_8_to_16(buffer, data, len);
LocalUnlock(clipbuffer);
SetClipboardData(CF_UNICODETEXT,clipbuffer);
}
@ -1356,3 +1381,9 @@ int GHOST_SystemWin32::toggleConsole(int action)
return m_consoleStatus;
}
int GHOST_SystemWin32::confirmQuit(GHOST_IWindow * window) const
{
return (MessageBox(window ? ((GHOST_WindowWin32*)window)->getHWND() : 0, "Some changes have not been saved.\nDo you really want to quit ?",
"Exit Blender", MB_OKCANCEL | MB_ICONWARNING | MB_TOPMOST) == IDOK);
}

@ -200,7 +200,13 @@ public:
* @return Indication whether the event was handled.
*/
static GHOST_TSuccess pushDragDropEvent(GHOST_TEventType eventType, GHOST_TDragnDropTypes draggedObjectType,GHOST_IWindow* window, int mouseX, int mouseY, void* data);
/**
* Confirms quitting he program when there is just one window left open
* in the application
*/
virtual int confirmQuit(GHOST_IWindow * window) const;
protected:
/**
* Initializes the system.

Some files were not shown because too many files have changed in this diff Show More