Compare commits

..

No commits in common. "main" and "v1.0.0" have entirely different histories.
main ... v1.0.0

1688 changed files with 227974 additions and 389497 deletions

View File

@ -1,109 +0,0 @@
---
Language: Cpp
# BasedOnStyle: Google
# Generated with clang-format 5.0.0
AccessModifierOffset: -1
AlignAfterOpenBracket: Align
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlines: Left
AlignOperands: true
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: true
AllowShortFunctionsOnASingleLine: All
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterClass: false
AfterControlStatement: false
AfterEnum: false
AfterFunction: false
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: false
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeBraces: Attach
BreakBeforeInheritanceComma: false
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
CompactNamespaces: false
ConstructorInitializerAllOnOneLineOrOnePerLine: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: false
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IncludeCategories:
- Regex: '^<.*\.h>'
Priority: 1
- Regex: '^<.*'
Priority: 2
- Regex: '.*'
Priority: 3
IncludeIsMainRegex: '([-_](test|unittest))?$'
IndentCaseLabels: true
IndentWidth: 2
IndentWrappedFunctionNames: false
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBlockIndentWidth: 2
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Right
ReflowComments: true
SortIncludes: false
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Auto
TabWidth: 8
UseTab: Never
...

75
.gitignore vendored
View File

@ -1,68 +1,61 @@
*.S
*.a
*.asm.s
*.d
*.gcda
*.gcno
*.o
*~
.cproject
.project
.settings
/*-*.mk
/*.asm
/*.doxy
/*.ivf
/*.ivf.md5
/.bins
/.deps
/.docs
/.install-*
/.libs
/Makefile
/config.log
/config.err
/config.mk
/decode_to_md5
/decode_to_md5.c
/decode_to_md5.dox
/decode_with_drops
/decode_with_drops.c
/decode_with_drops.dox
/docs/
/doxyfile
/examples/*.dox
/examples/decode_to_md5
/examples/decode_with_drops
/examples/decode_with_partial_drops
/examples/example_xma
/examples/postproc
/examples/resize_util
/examples/set_maps
/examples/simple_decoder
/examples/simple_encoder
/examples/twopass_encoder
/examples/vp8_multi_resolution_encoder
/examples/vp8cx_set_ref
/examples/vp9cx_set_ref
/examples/vp9_lossless_encoder
/examples/vp9_spatial_svc_encoder
/examples/vpx_temporal_svc_encoder
/error_resilient
/error_resilient.c
/error_resilient.dox
/force_keyframe
/force_keyframe.c
/force_keyframe.dox
/ivfdec
/ivfdec.dox
/ivfenc
/ivfenc.dox
/libvpx.so*
/libvpx.ver
/obj_int_extract
/postproc
/postproc.c
/postproc.dox
/samples.dox
/test_intra_pred_speed
/test_libvpx
/tools.dox
/tools/*.dox
/tools/tiny_ssim
/simple_decoder
/simple_decoder.c
/simple_decoder.dox
/simple_encoder
/simple_encoder.c
/simple_encoder.dox
/twopass_encoder
/twopass_encoder.c
/twopass_encoder.dox
/vp8_api1_migration.dox
/vp[89x]_rtcd.h
/vpx.pc
/vp8_scalable_patterns
/vp8_scalable_patterns.dox
/vp8_set_maps
/vp8_set_maps.c
/vp8_set_maps.dox
/vp8cx_set_ref
/vp8cx_set_ref.c
/vp8cx_set_ref.dox
/vpx_config.c
/vpx_config.h
/vpx_dsp_rtcd.h
/vpx_scale_rtcd.h
/vpx_version.h
/vpxdec
/vpxdec.dox
/vpxenc
/vpxenc.dox
TAGS

View File

@ -1,42 +1,7 @@
Adrian Grange <agrange@google.com>
Aex Converse <aconverse@google.com>
Aex Converse <aconverse@google.com> <alex.converse@gmail.com>
Alexis Ballier <aballier@gentoo.org> <alexis.ballier@gmail.com>
Alpha Lam <hclam@google.com> <hclam@chromium.org>
Chris Cunningham <chcunningham@chromium.org>
Daniele Castagna <dcastagna@chromium.org> <dcastagna@google.com>
Deb Mukherjee <debargha@google.com>
Erik Niemeyer <erik.a.niemeyer@intel.com> <erik.a.niemeyer@gmail.com>
Guillaume Martres <gmartres@google.com> <smarter3@gmail.com>
Hangyu Kuang <hkuang@google.com>
Hui Su <huisu@google.com>
Jacky Chen <jackychen@google.com>
Jim Bankoski <jimbankoski@google.com>
Johann Koenig <johannkoenig@google.com>
Johann Koenig <johannkoenig@google.com> <johann.koenig@duck.com>
Johann Koenig <johannkoenig@google.com> <johann.koenig@gmail.com>
Johann Koenig <johannkoenig@google.com> <johannkoenig@chromium.org>
John Koleszar <jkoleszar@google.com>
Joshua Litt <joshualitt@google.com> <joshualitt@chromium.org>
Marco Paniconi <marpan@google.com>
Marco Paniconi <marpan@google.com> <marpan@chromium.org>
Pascal Massimino <pascal.massimino@gmail.com>
Paul Wilkins <paulwilkins@google.com>
Peter Boström <pbos@chromium.org> <pbos@google.com>
Peter de Rivaz <peter.derivaz@gmail.com>
Peter de Rivaz <peter.derivaz@gmail.com> <peter.derivaz@argondesign.com>
Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
Tom Finegan <tomfinegan@google.com>
Ralph Giles <giles@xiph.org> <giles@entropywave.com>
Ralph Giles <giles@xiph.org> <giles@mozilla.com>
Ronald S. Bultje <rsbultje@gmail.com> <rbultje@google.com>
Sami Pietilä <samipietila@google.com>
Shiyou Yin <yinshiyou-hf@loongson.cn>
Tamar Levy <tamar.levy@intel.com>
Tamar Levy <tamar.levy@intel.com> <levytamar82@gmail.com>
Tero Rintaluoma <teror@google.com> <tero.rintaluoma@on2.com>
Timothy B. Terriberry <tterribe@xiph.org> <tterriberry@mozilla.com>
Tom Finegan <tomfinegan@google.com>
Tom Finegan <tomfinegan@google.com> <tomfinegan@chromium.org>
Urvang Joshi <urvang@google.com> <urvang@chromium.org>
Yaowu Xu <yaowu@google.com> <adam@xuyaowu.com>
Yaowu Xu <yaowu@google.com> <yaowu@xuyaowu.com>
Yaowu Xu <yaowu@google.com> <Yaowu Xu>
Alpha Lam <hclam@google.com> <hclam@chromium.org>

113
AUTHORS
View File

@ -2,169 +2,60 @@
# by tools/gen_authors.sh.
Aaron Watry <awatry@gmail.com>
Abo Talib Mahfoodh <ab.mahfoodh@gmail.com>
Adrian Grange <agrange@google.com>
Aex Converse <aconverse@google.com>
Ahmad Sharif <asharif@google.com>
Aleksey Vasenev <margtu-fivt@ya.ru>
Alexander Potapenko <glider@google.com>
Alexander Voronov <avoronov@graphics.cs.msu.ru>
Alexandra Hájková <alexandra.khirnova@gmail.com>
Alex Converse <alex.converse@gmail.com>
Alexis Ballier <aballier@gentoo.org>
Alok Ahuja <waveletcoeff@gmail.com>
Alpha Lam <hclam@google.com>
A.Mahfoodh <ab.mahfoodh@gmail.com>
Ami Fischman <fischman@chromium.org>
Andoni Morales Alastruey <ylatuya@gmail.com>
Andres Mejia <mcitadel@gmail.com>
Andrew Lewis <andrewlewis@google.com>
Andrew Russell <anrussell@google.com>
Angie Chiang <angiebird@google.com>
Aron Rosenberg <arosenberg@logitech.com>
Attila Nagy <attilanagy@google.com>
Brion Vibber <bvibber@wikimedia.org>
changjun.yang <changjun.yang@intel.com>
Charles 'Buck' Krasic <ckrasic@google.com>
Cheng Chen <chengchen@google.com>
chm <chm@rock-chips.com>
Chris Cunningham <chcunningham@chromium.org>
Christian Duvivier <cduvivier@google.com>
Daniele Castagna <dcastagna@chromium.org>
Daniel Kang <ddkang@google.com>
Deb Mukherjee <debargha@google.com>
Deepa K G <deepa.kg@ittiam.com>
Dim Temp <dimtemp0@gmail.com>
Dmitry Kovalev <dkovalev@google.com>
Dragan Mrdjan <dmrdjan@mips.com>
Ed Baker <edward.baker@intel.com>
Ehsan Akhgari <ehsan.akhgari@gmail.com>
Erik Niemeyer <erik.a.niemeyer@intel.com>
Fabio Pedretti <fabio.ped@libero.it>
Frank Galligan <fgalligan@google.com>
Fredrik Söderquist <fs@opera.com>
Fritz Koenig <frkoenig@google.com>
Gabriel Marin <gmx@chromium.org>
Gaute Strokkenes <gaute.strokkenes@broadcom.com>
Geza Lore <gezalore@gmail.com>
Ghislain MARY <ghislainmary2@gmail.com>
Giuseppe Scrivano <gscrivano@gnu.org>
Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com>
Gregor Jasny <gjasny@gmail.com>
Guillaume Martres <gmartres@google.com>
Guillermo Ballester Valor <gbvalor@gmail.com>
Hangyu Kuang <hkuang@google.com>
Hanno Böck <hanno@hboeck.de>
Han Shen <shenhan@google.com>
Henrik Lundin <hlundin@google.com>
Hui Su <huisu@google.com>
Ivan Krasin <krasin@chromium.org>
Ivan Maltz <ivanmaltz@google.com>
Jacek Caban <cjacek@gmail.com>
Jacky Chen <jackychen@google.com>
James Berry <jamesberry@google.com>
James Yu <james.yu@linaro.org>
James Zern <jzern@google.com>
Jan Gerber <j@mailb.org>
Jan Kratochvil <jan.kratochvil@redhat.com>
Janne Salonen <jsalonen@google.com>
Jean-Yves Avenard <jyavenard@mozilla.com>
Jeff Faust <jfaust@google.com>
Jeff Muizelaar <jmuizelaar@mozilla.com>
Jeff Petkau <jpet@chromium.org>
Jerome Jiang <jianj@google.com>
Jia Jia <jia.jia@linaro.org>
Jian Zhou <zhoujian@google.com>
Jim Bankoski <jimbankoski@google.com>
Jingning Han <jingning@google.com>
Joey Parrish <joeyparrish@google.com>
Johann Koenig <johannkoenig@google.com>
John Koleszar <jkoleszar@google.com>
Johnny Klonaris <google@jawknee.com>
John Stark <jhnstrk@gmail.com>
Joshua Bleecher Snyder <josh@treelinelabs.com>
Joshua Litt <joshualitt@google.com>
Julia Robson <juliamrobson@gmail.com>
Justin Clift <justin@salasaga.org>
Justin Lebar <justin.lebar@gmail.com>
Kaustubh Raste <kaustubh.raste@imgtec.com>
KO Myung-Hun <komh@chollian.net>
Kyle Siefring <kylesiefring@gmail.com>
Lawrence Velázquez <larryv@macports.org>
Linfeng Zhang <linfengz@google.com>
Lou Quillio <louquillio@google.com>
Luca Barbato <lu_zero@gentoo.org>
Makoto Kato <makoto.kt@gmail.com>
Mans Rullgard <mans@mansr.com>
Marco Paniconi <marpan@google.com>
Mark Mentovai <mark@chromium.org>
Martin Ettl <ettl.martin78@googlemail.com>
Martin Storsjo <martin@martin.st>
Matthew Heaney <matthewjheaney@chromium.org>
Michael Kohler <michaelkohler@live.com>
Mike Frysinger <vapier@chromium.org>
Mike Hommey <mhommey@mozilla.com>
Mikhal Shemer <mikhal@google.com>
Min Chen <chenm003@gmail.com>
Minghai Shang <minghai@google.com>
Min Ye <yeemmi@google.com>
Moriyoshi Koizumi <mozo@mozo.jp>
Morton Jonuschat <yabawock@gmail.com>
Nathan E. Egge <negge@mozilla.com>
Nico Weber <thakis@chromium.org>
Parag Salasakar <img.mips1@gmail.com>
Pascal Massimino <pascal.massimino@gmail.com>
Patrik Westin <patrik.westin@gmail.com>
Paul Wilkins <paulwilkins@google.com>
Pavol Rusnak <stick@gk2.sk>
Paweł Hajdan <phajdan@google.com>
Pengchong Jin <pengchong@google.com>
Peter Boström <pbos@chromium.org>
Peter Collingbourne <pcc@chromium.org>
Peter de Rivaz <peter.derivaz@gmail.com>
Philip Jägenstedt <philipj@opera.com>
Priit Laes <plaes@plaes.org>
Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
Rafaël Carré <funman@videolan.org>
Rafael de Lucena Valle <rafaeldelucena@gmail.com>
Rahul Chaudhry <rahulchaudhry@google.com>
Ralph Giles <giles@xiph.org>
Ranjit Kumar Tulabandu <ranjit.tulabandu@ittiam.com>
Rob Bradford <rob@linux.intel.com>
Ronald S. Bultje <rsbultje@gmail.com>
Rui Ueyama <ruiu@google.com>
Sami Pietilä <samipietila@google.com>
Sarah Parker <sarahparker@google.com>
Sasi Inguva <isasi@google.com>
Scott Graham <scottmg@chromium.org>
Ronald S. Bultje <rbultje@google.com>
Scott LaVarnway <slavarnway@google.com>
Sean McGovern <gseanmcg@gmail.com>
Sergey Kolomenkin <kolomenkin@gmail.com>
Sergey Ulanov <sergeyu@chromium.org>
Shimon Doodkin <helpmepro1@gmail.com>
Shiyou Yin <yinshiyou-hf@loongson.cn>
Shunyao Li <shunyaoli@google.com>
Stefan Holmer <holmer@google.com>
Suman Sunkara <sunkaras@google.com>
Sylvestre Ledru <sylvestre@mozilla.com>
Taekhyun Kim <takim@nvidia.com>
Takanori MATSUURA <t.matsuu@gmail.com>
Tamar Levy <tamar.levy@intel.com>
Tao Bai <michaelbai@chromium.org>
Tero Rintaluoma <teror@google.com>
Thijs Vermeir <thijsvermeir@gmail.com>
Tim Kopp <tkopp@google.com>
Timothy B. Terriberry <tterribe@xiph.org>
Tom Finegan <tomfinegan@google.com>
Tristan Matthews <le.businessman@gmail.com>
Urvang Joshi <urvang@google.com>
Vignesh Venkatasubramanian <vigneshv@google.com>
Vlad Tsyrklevich <vtsyrklevich@chromium.org>
Yaowu Xu <yaowu@google.com>
Yi Luo <luoyi@google.com>
Yongzhe Wang <yongzhe@google.com>
Yunqing Wang <yunqingwang@google.com>
Yury Gitman <yuryg@google.com>
Zoe Liu <zoeliu@google.com>
Google Inc.
The Mozilla Foundation
The Xiph.Org Foundation

282
CHANGELOG
View File

@ -1,285 +1,3 @@
2017-01-04 v1.7.0 "Mandarin Duck"
This release focused on high bit depth performance (10/12 bit) and vp9
encoding improvements.
- Upgrading:
This release is ABI incompatible due to new vp9 encoder features.
Frame parallel decoding for vp9 has been removed.
- Enhancements:
vp9 encoding supports additional threads with --row-mt. This can be greater
than the number of tiles.
Two new vp9 encoder options have been added:
--corpus-complexity
--tune-content=film
Additional tooling for respecting the vp9 "level" profiles has been added.
- Bug fixes:
A variety of fuzzing issues.
vp8 threading fix for ARM.
Codec control VP9_SET_SKIP_LOOP_FILTER fixed.
Reject invalid multi resolution configurations.
2017-01-09 v1.6.1 "Long Tailed Duck"
This release improves upon the VP9 encoder and speeds up the encoding and
decoding processes.
- Upgrading:
This release is ABI compatible with 1.6.0.
- Enhancements:
Faster VP9 encoding and decoding.
High bit depth builds now provide similar speed for 8 bit encode and decode
for x86 targets. Other platforms and higher bit depth improvements are in
progress.
- Bug Fixes:
A variety of fuzzing issues.
2016-07-20 v1.6.0 "Khaki Campbell Duck"
This release improves upon the VP9 encoder and speeds up the encoding and
decoding processes.
- Upgrading:
This release is ABI incompatible with 1.5.0 due to a new 'color_range' enum
in vpx_image and some minor changes to the VP8_COMP structure.
The default key frame interval for VP9 has changed from 128 to 9999.
- Enhancement:
A core focus has been performance for low end Intel processors. SSSE3
instructions such as 'pshufb' have been avoided and instructions have been
reordered to better accommodate the more constrained pipelines.
As a result, devices based on Celeron processors have seen substantial
decoding improvements. From Indian Runner Duck to Javan Whistling Duck,
decoding speed improved between 10 and 30%. Between Javan Whistling Duck
and Khaki Campbell Duck, it improved another 10 to 15%.
While Celeron benefited most, Core-i5 also improved 5% and 10% between the
respective releases.
Realtime performance for WebRTC for both speed and quality has received a
lot of attention.
- Bug Fixes:
A number of fuzzing issues, found variously by Mozilla, Chromium and others,
have been fixed and we strongly recommend updating.
2015-11-09 v1.5.0 "Javan Whistling Duck"
This release improves upon the VP9 encoder and speeds up the encoding and
decoding processes.
- Upgrading:
This release is ABI incompatible with 1.4.0. It drops deprecated VP8
controls and adds a variety of VP9 controls for testing.
The vpxenc utility now prefers VP9 by default.
- Enhancements:
Faster VP9 encoding and decoding
Smaller library size by combining functions used by VP8 and VP9
- Bug Fixes:
A variety of fuzzing issues
2015-04-03 v1.4.0 "Indian Runner Duck"
This release includes significant improvements to the VP9 codec.
- Upgrading:
This release is ABI incompatible with 1.3.0. It drops the compatibility
layer, requiring VPX_IMG_FMT_* instead of IMG_FMT_*, and adds several codec
controls for VP9.
- Enhancements:
Faster VP9 encoding and decoding
Multithreaded VP9 decoding (tile and frame-based)
Multithreaded VP9 encoding - on by default
YUV 4:2:2 and 4:4:4 support in VP9
10 and 12bit support in VP9
64bit ARM support by replacing ARM assembly with intrinsics
- Bug Fixes:
Fixes a VP9 bitstream issue in Profile 1. This only affected non-YUV 4:2:0
files.
- Known Issues:
Frame Parallel decoding fails for segmented and non-420 files.
2013-11-15 v1.3.0 "Forest"
This release introduces the VP9 codec in a backward-compatible way.
All existing users of VP8 can continue to use the library without
modification. However, some VP8 options do not map to VP9 in the same manner.
The VP9 encoder in this release is not feature complete. Users interested in
the encoder are advised to use the git master branch and discuss issues on
libvpx mailing lists.
- Upgrading:
This release is ABI and API compatible with Duclair (v1.0.0). Users
of older releases should refer to the Upgrading notes in this document
for that release.
- Enhancements:
Get rid of bashisms in the main build scripts
Added usage info on command line options
Add lossless compression mode
Dll build of libvpx
Add additional Mac OS X targets: 10.7, 10.8 and 10.9 (darwin11-13)
Add option to disable documentation
configure: add --enable-external-build support
make: support V=1 as short form of verbose=yes
configure: support mingw-w64
configure: support hardfloat armv7 CHOSTS
configure: add support for android x86
Add estimated completion time to vpxenc
Don't exit on decode errors in vpxenc
vpxenc: support scaling prior to encoding
vpxdec: support scaling output
vpxenc: improve progress indicators with --skip
msvs: Don't link to winmm.lib
Add a new script for producing vcxproj files
Produce Visual Studio 10 and 11 project files
Produce Windows Phone project files
msvs-build: use msbuild for vs >= 2005
configure: default configure log to config.log
Add encoding option --static-thresh
- Speed:
Miscellaneous speed optimizations for VP8 and VP9.
- Quality:
In general, quality is consistent with the Eider release.
- Bug Fixes:
This release represents approximately a year of engineering effort,
and contains multiple bug fixes. Please refer to git history for details.
2012-12-21 v1.2.0
This release acts as a checkpoint for a large amount of internal refactoring
and testing. It also contains a number of small bugfixes, so all users are
encouraged to upgrade.
- Upgrading:
This release is ABI and API compatible with Duclair (v1.0.0). Users
of older releases should refer to the Upgrading notes in this
document for that release.
- Enhancements:
VP8 optimizations for MIPS dspr2
vpxenc: add -quiet option
- Speed:
Encoder and decoder speed is consistent with the Eider release.
- Quality:
In general, quality is consistent with the Eider release.
Minor tweaks to ARNR filtering
Minor improvements to real time encoding with multiple temporal layers
- Bug Fixes:
Fixes multithreaded encoder race condition in loopfilter
Fixes multi-resolution threaded encoding
Fix potential encoder dead-lock after picture resize
2012-05-09 v1.1.0 "Eider"
This introduces a number of enhancements, mostly focused on real-time
encoding. In addition, it fixes a decoder bug (first introduced in
Duclair) so all users of that release are encouraged to upgrade.
- Upgrading:
This release is ABI and API compatible with Duclair (v1.0.0). Users
of older releases should refer to the Upgrading notes in this
document for that release.
This release introduces a new temporal denoiser, controlled by the
VP8E_SET_NOISE_SENSITIVITY control. The temporal denoiser does not
currently take a strength parameter, so the control is effectively
a boolean - zero (off) or non-zero (on). For compatibility with
existing applications, the values accepted are the same as those
for the spatial denoiser (0-6). The temporal denoiser is enabled
by default, and the older spatial denoiser may be restored by
configuring with --disable-temporal-denoising. The temporal denoiser
is more computationally intensive than the spatial one.
This release removes support for a legacy, decode only API that was
supported, but deprecated, at the initial release of libvpx
(v0.9.0). This is not expected to have any impact. If you are
impacted, you can apply a reversion to commit 2bf8fb58 locally.
Please update to the latest libvpx API if you are affected.
- Enhancements:
Adds a motion compensated temporal denoiser to the encoder, which
gives higher quality than the older spatial denoiser. (See above
for notes on upgrading).
In addition, support for new compilers and platforms were added,
including:
improved support for XCode
Android x86 NDK build
OS/2 support
SunCC support
Changing resolution with vpx_codec_enc_config_set() is now
supported. Previously, reinitializing the codec was required to
change the input resolution.
The vpxenc application has initial support for producing multiple
encodes from the same input in one call. Resizing is not yet
supported, but varying other codec parameters is. Use -- to
delineate output streams. Options persist from one stream to the
next.
Also, the vpxenc application will now use a keyframe interval of
5 seconds by default. Use the --kf-max-dist option to override.
- Speed:
Decoder performance improved 2.5% versus Duclair. Encoder speed is
consistent with Duclair for most material. Two pass encoding of
slideshow-like material will see significant improvements.
Large realtime encoding speed gains at a small quality expense are
possible by configuring the on-the-fly bitpacking experiment with
--enable-onthefly-bitpacking. Realtime encoder can be up to 13%
faster (ARM) depending on the number of threads and bitrate
settings. This technique sees constant gain over the 5-16 speed
range. For VC style input the loss seen is up to 0.2dB. See commit
52cf4dca for further details.
- Quality:
On the whole, quality is consistent with the Duclair release. Some
tweaks:
Reduced blockiness in easy sections by applying a penalty to
intra modes.
Improved quality of static sections (like slideshows) with
two pass encoding.
Improved keyframe sizing with multiple temporal layers
- Bug Fixes:
Corrected alt-ref contribution to frame rate for visible updates
to the alt-ref buffer. This affected applications making manual
usage of the frame reference flags, or temporal layers.
Additional constraints were added to disable multi-frame quality
enhancement (MFQE) in sections of the frame where there is motion.
(#392)
Fixed corruption issues when vpx_codec_enc_config_set() was called
with spatial resampling enabled.
Fixed a decoder error introduced in Duclair where the segmentation
map was not being reinitialized on keyframes (#378)
2012-01-27 v1.0.0 "Duclair"
Our fourth named release, focused on performance and features related to
real-time encoding. It also fixes a decoder crash bug introduced in

39
PATENTS
View File

@ -1,23 +1,22 @@
Additional IP Rights Grant (Patents)
------------------------------------
"These implementations" means the copyrightable works that implement the WebM
codecs distributed by Google as part of the WebM Project.
"This implementation" means the copyrightable works distributed by
Google as part of the WebM Project.
Google hereby grants to you a perpetual, worldwide, non-exclusive, no-charge,
royalty-free, irrevocable (except as stated in this section) patent license to
make, have made, use, offer to sell, sell, import, transfer, and otherwise
run, modify and propagate the contents of these implementations of WebM, where
such license applies only to those patent claims, both currently owned by
Google and acquired in the future, licensable by Google that are necessarily
infringed by these implementations of WebM. This grant does not include claims
that would be infringed only as a consequence of further modification of these
implementations. If you or your agent or exclusive licensee institute or order
or agree to the institution of patent litigation or any other patent
enforcement activity against any entity (including a cross-claim or
counterclaim in a lawsuit) alleging that any of these implementations of WebM
or any code incorporated within any of these implementations of WebM
constitute direct or contributory patent infringement, or inducement of
patent infringement, then any patent rights granted to you under this License
for these implementations of WebM shall terminate as of the date such
litigation is filed.
Google hereby grants to you a perpetual, worldwide, non-exclusive,
no-charge, royalty-free, irrevocable (except as stated in this section)
patent license to make, have made, use, offer to sell, sell, import,
transfer, and otherwise run, modify and propagate the contents of this
implementation of VP8, where such license applies only to those patent
claims, both currently owned by Google and acquired in the future,
licensable by Google that are necessarily infringed by this
implementation of VP8. This grant does not include claims that would be
infringed only as a consequence of further modification of this
implementation. If you or your agent or exclusive licensee institute or
order or agree to the institution of patent litigation against any
entity (including a cross-claim or counterclaim in a lawsuit) alleging
that this implementation of VP8 or any code incorporated within this
implementation of VP8 constitutes direct or contributory patent
infringement, or inducement of patent infringement, then any patent
rights granted to you under this License for this implementation of VP8
shall terminate as of the date such litigation is filed.

130
README
View File

@ -1,6 +1,7 @@
README - 24 January 2018
vpx Multi-Format Codec SDK
README - 19 May 2010
Welcome to the WebM VP8/VP9 Codec SDK!
Welcome to the WebM VP8 Codec SDK!
COMPILING THE APPLICATIONS/LIBRARIES:
The build system used is similar to autotools. Building generally consists of
@ -9,26 +10,16 @@ COMPILING THE APPLICATIONS/LIBRARIES:
1. Prerequisites
* All x86 targets require the Yasm[1] assembler be installed[2].
* All Windows builds require that Cygwin[3] be installed.
* Building the documentation requires Doxygen[4]. If you do not
have this package, the install-docs option will be disabled.
* Downloading the data for the unit tests requires curl[5] and sha1sum.
sha1sum is provided via the GNU coreutils, installed by default on
many *nix platforms, as well as MinGW and Cygwin. If coreutils is not
available, a compatible version of sha1sum can be built from
source[6]. These requirements are optional if not running the unit
tests.
* All x86 targets require the Yasm[1] assembler be installed.
* All Windows builds require that Cygwin[2] be installed.
* Building the documentation requires PHP[3] and Doxygen[4]. If you do not
have these packages, you must pass --disable-install-docs to the
configure script.
[1]: http://www.tortall.net/projects/yasm
[2]: For Visual Studio the base yasm binary (not vsyasm) should be in the
PATH for Visual Studio. For VS2017 it is sufficient to rename
yasm-<version>-<arch>.exe to yasm.exe and place it in:
Program Files (x86)/Microsoft Visual Studio/2017/<level>/Common7/Tools/
[3]: http://www.cygwin.com
[2]: http://www.cygwin.com
[3]: http://php.net
[4]: http://www.doxygen.org
[5]: http://curl.haxx.se
[6]: http://www.microbrew.org/tools/md5sha1sum/
2. Out-of-tree builds
Out of tree builds are a supported method of building the application. For
@ -45,82 +36,42 @@ COMPILING THE APPLICATIONS/LIBRARIES:
used to get a list of supported options:
$ ../libvpx/configure --help
4. Compiler analyzers
Compilers have added sanitizers which instrument binaries with information
about address calculation, memory usage, threading, undefined behavior, and
other common errors. To simplify building libvpx with some of these features
use tools/set_analyzer_env.sh before running configure. It will set the
compiler and necessary flags for building as well as environment variables
read by the analyzer when testing the binaries.
$ source ../libvpx/tools/set_analyzer_env.sh address
5. Cross development
4. Cross development
For cross development, the most notable option is the --target option. The
most up-to-date list of supported targets can be found at the bottom of the
--help output of the configure script. As of this writing, the list of
available targets is:
arm64-android-gcc
arm64-darwin-gcc
arm64-linux-gcc
armv5te-android-gcc
armv5te-linux-rvct
armv5te-linux-gcc
armv6-darwin-gcc
armv6-linux-rvct
armv6-linux-gcc
armv7-android-gcc
armv7-darwin-gcc
armv7-linux-rvct
armv7-linux-gcc
armv7-none-rvct
armv7-win32-vs11
armv7-win32-vs12
armv7-win32-vs14
armv7-win32-vs15
armv7s-darwin-gcc
armv8-linux-gcc
mips32-linux-gcc
mips64-linux-gcc
ppc32-darwin8-gcc
ppc32-darwin9-gcc
ppc64-darwin8-gcc
ppc64-darwin9-gcc
ppc64-linux-gcc
ppc64le-linux-gcc
sparc-solaris-gcc
x86-android-gcc
x86-darwin8-gcc
x86-darwin8-icc
x86-darwin9-gcc
x86-darwin9-icc
x86-darwin10-gcc
x86-darwin11-gcc
x86-darwin12-gcc
x86-darwin13-gcc
x86-darwin14-gcc
x86-darwin15-gcc
x86-darwin16-gcc
x86-iphonesimulator-gcc
x86-linux-gcc
x86-linux-icc
x86-os2-gcc
x86-solaris-gcc
x86-win32-gcc
x86-win32-vs10
x86-win32-vs11
x86-win32-vs12
x86-win32-vs14
x86-win32-vs15
x86_64-android-gcc
x86-win32-vs7
x86-win32-vs8
x86_64-darwin9-gcc
x86_64-darwin10-gcc
x86_64-darwin11-gcc
x86_64-darwin12-gcc
x86_64-darwin13-gcc
x86_64-darwin14-gcc
x86_64-darwin15-gcc
x86_64-darwin16-gcc
x86_64-iphonesimulator-gcc
x86_64-linux-gcc
x86_64-linux-icc
x86_64-solaris-gcc
x86_64-win64-gcc
x86_64-win64-vs10
x86_64-win64-vs11
x86_64-win64-vs12
x86_64-win64-vs14
x86_64-win64-vs15
x86_64-win64-vs8
universal-darwin8-gcc
universal-darwin9-gcc
generic-gnu
The generic-gnu target, in conjunction with the CROSS environment variable,
@ -136,35 +87,12 @@ COMPILING THE APPLICATIONS/LIBRARIES:
environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
6. Configuration errors
5. Configuration errors
If the configuration step fails, the first step is to look in the error log.
This defaults to config.log. This should give a good indication of what went
This defaults to config.err. This should give a good indication of what went
wrong. If not, contact us for support.
VP8/VP9 TEST VECTORS:
The test vectors can be downloaded and verified using the build system after
running configure. To specify an alternate directory the
LIBVPX_TEST_DATA_PATH environment variable can be used.
$ ./configure --enable-unit-tests
$ LIBVPX_TEST_DATA_PATH=../libvpx-test-data make testdata
CODE STYLE:
The coding style used by this project is enforced with clang-format using the
configuration contained in the .clang-format file in the root of the
repository.
Before pushing changes for review you can format your code with:
# Apply clang-format to modified .c, .h and .cc files
$ clang-format -i --style=file \
$(git diff --name-only --diff-filter=ACMR '*.[hc]' '*.cc')
Check the .clang-format file for the version used to generate it if there is
any difference between your local formatting and the review system.
See also: http://clang.llvm.org/docs/ClangFormat.html
SUPPORT
This library is an open source project supported by its community. Please
email webm-discuss@webmproject.org for help.
please email webm-users@webmproject.org for help.

366
args.c
View File

@ -8,13 +8,15 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "args.h"
#include "vpx/vpx_integer.h"
#include "vpx_ports/msvc.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#endif
#if defined(__GNUC__) && __GNUC__
extern void die(const char *fmt, ...) __attribute__((noreturn));
@ -22,194 +24,242 @@ extern void die(const char *fmt, ...) __attribute__((noreturn));
extern void die(const char *fmt, ...);
#endif
struct arg arg_init(char **argv) {
struct arg a;
a.argv = argv;
a.argv_step = 1;
a.name = NULL;
a.val = NULL;
a.def = NULL;
return a;
struct arg arg_init(char **argv)
{
struct arg a;
a.argv = argv;
a.argv_step = 1;
a.name = NULL;
a.val = NULL;
a.def = NULL;
return a;
}
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv) {
struct arg arg;
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv)
{
struct arg arg;
if (!argv[0] || argv[0][0] != '-') return 0;
if (!argv[0] || argv[0][0] != '-')
return 0;
arg = arg_init(argv);
arg = arg_init(argv);
if (def->short_name && strlen(arg.argv[0]) == strlen(def->short_name) + 1 &&
!strcmp(arg.argv[0] + 1, def->short_name)) {
arg.name = arg.argv[0] + 1;
arg.val = def->has_val ? arg.argv[1] : NULL;
arg.argv_step = def->has_val ? 2 : 1;
} else if (def->long_name) {
const size_t name_len = strlen(def->long_name);
if (def->short_name
&& strlen(arg.argv[0]) == strlen(def->short_name) + 1
&& !strcmp(arg.argv[0] + 1, def->short_name))
{
if (strlen(arg.argv[0]) >= name_len + 2 && arg.argv[0][1] == '-' &&
!strncmp(arg.argv[0] + 2, def->long_name, name_len) &&
(arg.argv[0][name_len + 2] == '=' ||
arg.argv[0][name_len + 2] == '\0')) {
arg.name = arg.argv[0] + 2;
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
arg.argv_step = 1;
arg.name = arg.argv[0] + 1;
arg.val = def->has_val ? arg.argv[1] : NULL;
arg.argv_step = def->has_val ? 2 : 1;
}
}
if (arg.name && !arg.val && def->has_val)
die("Error: option %s requires argument.\n", arg.name);
if (arg.name && arg.val && !def->has_val)
die("Error: option %s requires no argument.\n", arg.name);
if (arg.name && (arg.val || !def->has_val)) {
arg.def = def;
*arg_ = arg;
return 1;
}
return 0;
}
const char *arg_next(struct arg *arg) {
if (arg->argv[0]) arg->argv += arg->argv_step;
return *arg->argv;
}
char **argv_dup(int argc, const char **argv) {
char **new_argv = malloc((argc + 1) * sizeof(*argv));
memcpy(new_argv, argv, argc * sizeof(*argv));
new_argv[argc] = NULL;
return new_argv;
}
void arg_show_usage(FILE *fp, const struct arg_def *const *defs) {
char option_text[40] = { 0 };
for (; *defs; defs++) {
const struct arg_def *def = *defs;
char *short_val = def->has_val ? " <arg>" : "";
char *long_val = def->has_val ? "=<arg>" : "";
if (def->short_name && def->long_name) {
char *comma = def->has_val ? "," : ", ";
snprintf(option_text, 37, "-%s%s%s --%s%6s", def->short_name, short_val,
comma, def->long_name, long_val);
} else if (def->short_name)
snprintf(option_text, 37, "-%s%s", def->short_name, short_val);
else if (def->long_name)
snprintf(option_text, 37, " --%s%s", def->long_name, long_val);
{
const size_t name_len = strlen(def->long_name);
fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
if (strlen(arg.argv[0]) >= name_len + 2
&& arg.argv[0][1] == '-'
&& !strncmp(arg.argv[0] + 2, def->long_name, name_len)
&& (arg.argv[0][name_len+2] == '='
|| arg.argv[0][name_len+2] == '\0'))
{
if (def->enums) {
const struct arg_enum_list *listptr;
fprintf(fp, " %-37s\t ", "");
for (listptr = def->enums; listptr->name; listptr++)
fprintf(fp, "%s%s", listptr->name, listptr[1].name ? ", " : "\n");
arg.name = arg.argv[0] + 2;
arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
arg.argv_step = 1;
}
}
}
if (arg.name && !arg.val && def->has_val)
die("Error: option %s requires argument.\n", arg.name);
if (arg.name && arg.val && !def->has_val)
die("Error: option %s requires no argument.\n", arg.name);
if (arg.name
&& (arg.val || !def->has_val))
{
arg.def = def;
*arg_ = arg;
return 1;
}
return 0;
}
unsigned int arg_parse_uint(const struct arg *arg) {
uint32_t rawval;
char *endptr;
rawval = (uint32_t)strtoul(arg->val, &endptr, 10);
const char *arg_next(struct arg *arg)
{
if (arg->argv[0])
arg->argv += arg->argv_step;
if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval <= UINT_MAX) return rawval;
die("Option %s: Value %ld out of range for unsigned int\n", arg->name,
rawval);
}
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0;
return *arg->argv;
}
int arg_parse_int(const struct arg *arg) {
int32_t rawval;
char *endptr;
rawval = (int32_t)strtol(arg->val, &endptr, 10);
char **argv_dup(int argc, const char **argv)
{
char **new_argv = malloc((argc + 1) * sizeof(*argv));
if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval >= INT_MIN && rawval <= INT_MAX) return (int)rawval;
die("Option %s: Value %ld out of range for signed int\n", arg->name,
rawval);
}
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0;
memcpy(new_argv, argv, argc * sizeof(*argv));
new_argv[argc] = NULL;
return new_argv;
}
struct vpx_rational {
int num; /**< fraction numerator */
int den; /**< fraction denominator */
};
struct vpx_rational arg_parse_rational(const struct arg *arg) {
long int rawval;
char *endptr;
struct vpx_rational rat;
/* parse numerator */
rawval = strtol(arg->val, &endptr, 10);
void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
{
char option_text[40] = {0};
if (arg->val[0] != '\0' && endptr[0] == '/') {
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.num = (int)rawval;
else
die("Option %s: Value %ld out of range for signed int\n", arg->name,
rawval);
} else
die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
for (; *defs; defs++)
{
const struct arg_def *def = *defs;
char *short_val = def->has_val ? " <arg>" : "";
char *long_val = def->has_val ? "=<arg>" : "";
/* parse denominator */
rawval = strtol(endptr + 1, &endptr, 10);
if (def->short_name && def->long_name)
{
char *comma = def->has_val ? "," : ", ";
snprintf(option_text, 37, "-%s%s%s --%s%6s",
def->short_name, short_val, comma,
def->long_name, long_val);
}
else if (def->short_name)
snprintf(option_text, 37, "-%s%s",
def->short_name, short_val);
else if (def->long_name)
snprintf(option_text, 37, " --%s%s",
def->long_name, long_val);
fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
if(def->enums)
{
const struct arg_enum_list *listptr;
fprintf(fp, " %-37s\t ", "");
for(listptr = def->enums; listptr->name; listptr++)
fprintf(fp, "%s%s", listptr->name,
listptr[1].name ? ", " : "\n");
}
}
}
unsigned int arg_parse_uint(const struct arg *arg)
{
long int rawval;
char *endptr;
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= 0 && rawval <= UINT_MAX)
return rawval;
die("Option %s: Value %ld out of range for unsigned int\n",
arg->name, rawval);
}
if (arg->val[0] != '\0' && endptr[0] == '\0') {
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.den = (int)rawval;
else
die("Option %s: Value %ld out of range for signed int\n", arg->name,
rawval);
} else
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return rat;
return 0;
}
int arg_parse_enum(const struct arg *arg) {
const struct arg_enum_list *listptr;
long int rawval;
char *endptr;
/* First see if the value can be parsed as a raw value */
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0') {
/* Got a raw value, make sure it's valid */
for (listptr = arg->def->enums; listptr->name; listptr++)
if (listptr->val == rawval) return (int)rawval;
}
int arg_parse_int(const struct arg *arg)
{
long int rawval;
char *endptr;
/* Next see if it can be parsed as a string */
for (listptr = arg->def->enums; listptr->name; listptr++)
if (!strcmp(arg->val, listptr->name)) return listptr->val;
rawval = strtol(arg->val, &endptr, 10);
die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
return 0;
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
return rawval;
die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return 0;
}
int arg_parse_enum_or_int(const struct arg *arg) {
if (arg->def->enums) return arg_parse_enum(arg);
return arg_parse_int(arg);
struct vpx_rational
{
int num; /**< fraction numerator */
int den; /**< fraction denominator */
};
struct vpx_rational arg_parse_rational(const struct arg *arg)
{
long int rawval;
char *endptr;
struct vpx_rational rat;
/* parse numerator */
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '/')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.num = rawval;
else die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
/* parse denominator */
rawval = strtol(endptr + 1, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
if (rawval >= INT_MIN && rawval <= INT_MAX)
rat.den = rawval;
else die("Option %s: Value %ld out of range for signed int\n",
arg->name, rawval);
}
else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
return rat;
}
int arg_parse_enum(const struct arg *arg)
{
const struct arg_enum_list *listptr;
long int rawval;
char *endptr;
/* First see if the value can be parsed as a raw value */
rawval = strtol(arg->val, &endptr, 10);
if (arg->val[0] != '\0' && endptr[0] == '\0')
{
/* Got a raw value, make sure it's valid */
for(listptr = arg->def->enums; listptr->name; listptr++)
if(listptr->val == rawval)
return rawval;
}
/* Next see if it can be parsed as a string */
for(listptr = arg->def->enums; listptr->name; listptr++)
if(!strcmp(arg->val, listptr->name))
return listptr->val;
die("Option %s: Invalid value '%s'\n", arg->name, arg->val);
return 0;
}
int arg_parse_enum_or_int(const struct arg *arg)
{
if(arg->def->enums)
return arg_parse_enum(arg);
return arg_parse_int(arg);
}

59
args.h
View File

@ -8,42 +8,38 @@
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef ARGS_H_
#define ARGS_H_
#ifndef ARGS_H
#define ARGS_H
#include <stdio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct arg {
char **argv;
const char *name;
const char *val;
unsigned int argv_step;
const struct arg_def *def;
struct arg
{
char **argv;
const char *name;
const char *val;
unsigned int argv_step;
const struct arg_def *def;
};
struct arg_enum_list {
const char *name;
int val;
struct arg_enum_list
{
const char *name;
int val;
};
#define ARG_ENUM_LIST_END \
{ 0 }
#define ARG_ENUM_LIST_END {0}
typedef struct arg_def {
const char *short_name;
const char *long_name;
int has_val;
const char *desc;
const struct arg_enum_list *enums;
typedef struct arg_def
{
const char *short_name;
const char *long_name;
int has_val;
const char *desc;
const struct arg_enum_list *enums;
} arg_def_t;
#define ARG_DEF(s, l, v, d) \
{ s, l, v, d, NULL }
#define ARG_DEF_ENUM(s, l, v, d, e) \
{ s, l, v, d, e }
#define ARG_DEF_LIST_END \
{ 0 }
#define ARG_DEF(s,l,v,d) {s,l,v,d, NULL}
#define ARG_DEF_ENUM(s,l,v,d,e) {s,l,v,d,e}
#define ARG_DEF_LIST_END {0}
struct arg arg_init(char **argv);
int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
@ -54,10 +50,5 @@ char **argv_dup(int argc, const char **argv);
unsigned int arg_parse_uint(const struct arg *arg);
int arg_parse_int(const struct arg *arg);
struct vpx_rational arg_parse_rational(const struct arg *arg);
int arg_parse_enum(const struct arg *arg);
int arg_parse_enum_or_int(const struct arg *arg);
#ifdef __cplusplus
} // extern "C"
#endif
#endif // ARGS_H_

2
build/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
*-vs8/*.rules -crlf
*-msvs/*.rules -crlf

1
build/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
x86*-win32-vs*

View File

@ -27,63 +27,31 @@
# Android.mk file in the libvpx directory:
# LOCAL_PATH := $(call my-dir)
# include $(CLEAR_VARS)
# include jni/libvpx/build/make/Android.mk
# include libvpx/build/make/Android.mk
#
# By default libvpx will detect at runtime the existance of NEON extension.
# For this we import the 'cpufeatures' module from the NDK sources.
# libvpx can also be configured without this runtime detection method.
# Configuring with --disable-runtime-cpu-detect will assume presence of NEON.
# Configuring with --disable-runtime-cpu-detect --disable-neon \
# --disable-neon-asm
# will remove any NEON dependency.
# There are currently two TARGET_ARCH_ABI targets for ARM.
# armeabi and armeabi-v7a. armeabi-v7a is selected by creating an
# Application.mk in the jni directory that contains:
# APP_ABI := armeabi-v7a
#
# To change to building armeabi, run ./libvpx/configure again, but with
# --target=arm5te-android-gcc and and modify the Application.mk file to
# set APP_ABI := armeabi
#
# Running ndk-build will build libvpx and include it in your project.
#
# Alternatively, building the examples and unit tests can be accomplished in the
# following way:
#
# Create a standalone toolchain from the NDK:
# https://developer.android.com/ndk/guides/standalone_toolchain.html
#
# For example - to test on arm64 devices with clang:
# $NDK/build/tools/make_standalone_toolchain.py \
# --arch arm64 --install-dir=/tmp/my-android-toolchain
# export PATH=/tmp/my-android-toolchain/bin:$PATH
# CROSS=aarch64-linux-android- CC=clang CXX=clang++ /path/to/libvpx/configure \
# --target=arm64-android-gcc
#
# Push the resulting binaries to a device and run them:
# adb push test_libvpx /data/tmp/test_libvpx
# adb shell /data/tmp/test_libvpx --gtest_filter=\*Sixtap\*
#
# Make sure to push the test data as well and set LIBVPX_TEST_DATA
CONFIG_DIR := $(LOCAL_PATH)/
CONFIG_DIR := $(LOCAL_PATH)
LIBVPX_PATH := $(LOCAL_PATH)/libvpx
ASM_CNV_PATH_LOCAL := $(TARGET_ARCH_ABI)/ads2gas
ASM_CNV_PATH := $(LOCAL_PATH)/$(ASM_CNV_PATH_LOCAL)
ifneq ($(V),1)
qexec := @
endif
# Use the makefiles generated by upstream configure to determine which files to
# build. Also set any architecture-specific flags.
# Makefiles created by the libvpx configure process
# This will need to be fixed to handle x86.
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
include $(CONFIG_DIR)libs-armv7-android-gcc.mk
LOCAL_ARM_MODE := arm
else ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
include $(CONFIG_DIR)libs-arm64-android-gcc.mk
LOCAL_ARM_MODE := arm
else ifeq ($(TARGET_ARCH_ABI),x86)
include $(CONFIG_DIR)libs-x86-android-gcc.mk
else ifeq ($(TARGET_ARCH_ABI),x86_64)
include $(CONFIG_DIR)libs-x86_64-android-gcc.mk
else ifeq ($(TARGET_ARCH_ABI),mips)
include $(CONFIG_DIR)libs-mips-android-gcc.mk
include $(CONFIG_DIR)/libs-armv7-android-gcc.mk
else
$(error Not a supported TARGET_ARCH_ABI: $(TARGET_ARCH_ABI))
include $(CONFIG_DIR)/libs-armv5te-android-gcc.mk
endif
# Rule that is normally in Makefile created by libvpx
@ -97,21 +65,59 @@ SRC_PATH_BARE := $(LIBVPX_PATH)
# Include the list of files to be built
include $(LIBVPX_PATH)/libs.mk
# Optimise the code. May want to revisit this setting in the future.
# Want arm, not thumb, optimized
LOCAL_ARM_MODE := arm
LOCAL_CFLAGS := -O3
# For x86, include the source code in the search path so it will find files
# like x86inc.asm and x86_abi_support.asm
LOCAL_ASMFLAGS := -I$(LIBVPX_PATH)
# -----------------------------------------------------------------------------
# Template : asm_offsets_template
# Arguments : 1: assembly offsets file to be created
# 2: c file to base assembly offsets on
# Returns : None
# Usage : $(eval $(call asm_offsets_template,<asmfile>, <srcfile>
# Rationale : Create offsets at compile time using for structures that are
# defined in c, but used in assembly functions.
# -----------------------------------------------------------------------------
define asm_offsets_template
.PRECIOUS: %.asm.S
$(ASM_CNV_PATH)/libvpx/%.asm.S: $(LIBVPX_PATH)/%.asm
$(qexec)mkdir -p $(dir $@)
$(qexec)$(CONFIG_DIR)$(ASM_CONVERSION) <$< > $@
_SRC:=$(2)
_OBJ:=$(ASM_CNV_PATH)/$$(notdir $(2)).S
_FLAGS = $$($$(my)CFLAGS) \
$$(call get-src-file-target-cflags,$(2)) \
$$(call host-c-includes,$$(LOCAL_C_INCLUDES) $$(CONFIG_DIR)) \
$$(LOCAL_CFLAGS) \
$$(NDK_APP_CFLAGS) \
$$(call host-c-includes,$$($(my)C_INCLUDES)) \
-DINLINE_ASM \
-S \
_TEXT = "Compile $$(call get-src-file-text,$(2))"
_CC = $$(TARGET_CC)
$$(eval $$(call ev-build-file))
$(1) : $$(_OBJ) $(2)
@mkdir -p $$(dir $$@)
@grep -w EQU $$< | tr -d '\#' | $(CONFIG_DIR)/$(ASM_CONVERSION) > $$@
endef
# Use ads2gas script to convert from RVCT format to GAS format. This passes
# puts the processed file under $(ASM_CNV_PATH). Local clean rule
# to handle removing these
ASM_CNV_OFFSETS_DEPEND = $(ASM_CNV_PATH)/asm_com_offsets.asm
ifeq ($(CONFIG_VP8_DECODER), yes)
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/asm_dec_offsets.asm
endif
ifeq ($(CONFIG_VP8_ENCODER), yes)
ASM_CNV_OFFSETS_DEPEND += $(ASM_CNV_PATH)/asm_enc_offsets.asm
endif
.PRECIOUS: %.asm.s
$(ASM_CNV_PATH)/libvpx/%.asm.s: $(LIBVPX_PATH)/%.asm $(ASM_CNV_OFFSETS_DEPEND)
@mkdir -p $(dir $@)
@$(CONFIG_DIR)/$(ASM_CONVERSION) <$< > $@
# For building *_rtcd.h, which have rules in libs.mk
TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
target := libs
LOCAL_SRC_FILES += vpx_config.c
@ -120,109 +126,68 @@ CODEC_SRCS_UNIQUE = $(sort $(CODEC_SRCS))
# Pull out C files. vpx_config.c is in the immediate directory and
# so it does not need libvpx/ prefixed like the rest of the source files.
# The neon files with intrinsics need to have .neon appended so the proper
# flags are applied.
CODEC_SRCS_C = $(filter %.c, $(CODEC_SRCS_UNIQUE))
LOCAL_NEON_SRCS_C = $(filter %_neon.c, $(CODEC_SRCS_C))
LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c %_neon.c, $(CODEC_SRCS_C))
LOCAL_CODEC_SRCS_C = $(filter-out vpx_config.c, $(CODEC_SRCS_C))
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_CODEC_SRCS_C), libvpx/$(file))
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file).neon)
else # If there are neon sources then we are building for arm64 and do not need to specify .neon
LOCAL_SRC_FILES += $(foreach file, $(LOCAL_NEON_SRCS_C), libvpx/$(file))
endif
# Pull out assembly files, splitting NEON from the rest. This is
# done to specify that the NEON assembly files use NEON assembler flags.
# x86 assembly matches %.asm, arm matches %.asm.S
# x86:
CODEC_SRCS_ASM_X86 = $(filter %.asm, $(CODEC_SRCS_UNIQUE))
LOCAL_SRC_FILES += $(foreach file, $(CODEC_SRCS_ASM_X86), libvpx/$(file))
# arm:
CODEC_SRCS_ASM_ARM_ALL = $(filter %.asm.S, $(CODEC_SRCS_UNIQUE))
CODEC_SRCS_ASM_ARM = $(foreach v, \
$(CODEC_SRCS_ASM_ARM_ALL), \
$(if $(findstring neon,$(v)),,$(v)))
CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.S, \
$(ASM_CNV_PATH_LOCAL)/libvpx/%.S, \
$(CODEC_SRCS_ASM_ARM))
CODEC_SRCS_ASM_ALL = $(filter %.asm.s, $(CODEC_SRCS_UNIQUE))
CODEC_SRCS_ASM = $(foreach v, \
$(CODEC_SRCS_ASM_ALL), \
$(if $(findstring neon,$(v)),,$(v)))
CODEC_SRCS_ASM_ADS2GAS = $(patsubst %.s, \
$(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
$(CODEC_SRCS_ASM))
LOCAL_SRC_FILES += $(CODEC_SRCS_ASM_ADS2GAS)
ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
ASM_INCLUDES := vpx_dsp/arm/idct_neon.asm.S
CODEC_SRCS_ASM_NEON = $(foreach v, \
$(CODEC_SRCS_ASM_ARM_ALL),\
$(CODEC_SRCS_ASM_ALL),\
$(if $(findstring neon,$(v)),$(v),))
CODEC_SRCS_ASM_NEON := $(filter-out $(addprefix %, $(ASM_INCLUDES)), \
$(CODEC_SRCS_ASM_NEON))
CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.S, \
$(ASM_CNV_PATH_LOCAL)/libvpx/%.S, \
CODEC_SRCS_ASM_NEON_ADS2GAS = $(patsubst %.s, \
$(ASM_CNV_PATH_LOCAL)/libvpx/%.s, \
$(CODEC_SRCS_ASM_NEON))
LOCAL_SRC_FILES += $(patsubst %.S, \
%.S.neon, \
LOCAL_SRC_FILES += $(patsubst %.s, \
%.s.neon, \
$(CODEC_SRCS_ASM_NEON_ADS2GAS))
NEON_ASM_TARGETS = $(patsubst %.S, \
$(ASM_CNV_PATH)/libvpx/%.S, \
$(CODEC_SRCS_ASM_NEON))
# add a dependency to the full path to the ads2gas output to ensure the
# includes are converted first.
ifneq ($(strip $(NEON_ASM_TARGETS)),)
$(NEON_ASM_TARGETS): $(addprefix $(ASM_CNV_PATH)/libvpx/, $(ASM_INCLUDES))
endif
endif
LOCAL_CFLAGS += \
-DHAVE_CONFIG_H=vpx_config.h \
-I$(LIBVPX_PATH) \
-I$(ASM_CNV_PATH) \
-I$(ASM_CNV_PATH)/libvpx
-I$(ASM_CNV_PATH)
LOCAL_MODULE := libvpx
ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
LOCAL_STATIC_LIBRARIES := cpufeatures
endif
LOCAL_LDLIBS := -llog
# Add a dependency to force generation of the RTCD files.
define rtcd_dep_template
rtcd_dep_template_SRCS := $(addprefix $(LOCAL_PATH)/, $(LOCAL_SRC_FILES))
rtcd_dep_template_SRCS := $$(rtcd_dep_template_SRCS:.neon=)
ifeq ($(CONFIG_VP8), yes)
$$(rtcd_dep_template_SRCS): vp8_rtcd.h
endif
ifeq ($(CONFIG_VP9), yes)
$$(rtcd_dep_template_SRCS): vp9_rtcd.h
endif
$$(rtcd_dep_template_SRCS): vpx_scale_rtcd.h
$$(rtcd_dep_template_SRCS): vpx_dsp_rtcd.h
rtcd_dep_template_CONFIG_ASM_ABIS := x86 x86_64 armeabi-v7a
ifneq ($$(findstring $(TARGET_ARCH_ABI),$$(rtcd_dep_template_CONFIG_ASM_ABIS)),)
$$(rtcd_dep_template_SRCS): vpx_config.asm
endif
endef
$(eval $(call rtcd_dep_template))
LOCAL_STATIC_LIBRARIES := cpufeatures
.PHONY: clean
clean:
@echo "Clean: ads2gas files [$(TARGET_ARCH_ABI)]"
$(qexec)$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
$(qexec)$(RM) -r $(ASM_CNV_PATH)
$(qexec)$(RM) $(CLEAN-OBJS)
@$(RM) $(CODEC_SRCS_ASM_ADS2GAS) $(CODEC_SRCS_ASM_NEON_ADS2GAS)
@$(RM) $(patsubst %.asm, %.*, $(ASM_CNV_OFFSETS_DEPEND))
@$(RM) -r $(ASM_CNV_PATH)
ifeq ($(ENABLE_SHARED),1)
LOCAL_CFLAGS += -fPIC
include $(BUILD_SHARED_LIBRARY)
else
include $(BUILD_STATIC_LIBRARY)
include $(BUILD_SHARED_LIBRARY)
$(eval $(call asm_offsets_template,\
$(ASM_CNV_PATH)/asm_com_offsets.asm, \
$(LIBVPX_PATH)/vp8/common/asm_com_offsets.c))
ifeq ($(CONFIG_VP8_DECODER), yes)
$(eval $(call asm_offsets_template,\
$(ASM_CNV_PATH)/asm_dec_offsets.asm, \
$(LIBVPX_PATH)/vp8/decoder/asm_dec_offsets.c))
endif
ifeq ($(CONFIG_RUNTIME_CPU_DETECT),yes)
$(call import-module,android/cpufeatures)
ifeq ($(CONFIG_VP8_ENCODER), yes)
$(eval $(call asm_offsets_template,\
$(ASM_CNV_PATH)/asm_enc_offsets.asm, \
$(LIBVPX_PATH)/vp8/encoder/asm_enc_offsets.c))
endif
$(call import-module,cpufeatures)

View File

@ -19,14 +19,9 @@ ifeq ($(target),)
done
all: .DEFAULT
clean:: .DEFAULT
exampletest: .DEFAULT
install:: .DEFAULT
test:: .DEFAULT
test-no-data-check:: .DEFAULT
testdata:: .DEFAULT
utiltest: .DEFAULT
exampletest-no-data-check utiltest-no-data-check: .DEFAULT
test_%: .DEFAULT ;
# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
# installed on cygwin, so we need to autodetect here.
@ -56,24 +51,28 @@ dist:
| sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2 \1/' \
> md5sums.txt;\
fi
endif
# Since we invoke make recursively for multiple targets we need to include the
# .mk file for the correct target, but only when $(target) is non-empty.
ifneq ($(target),)
include $(target)-$(TOOLCHAIN).mk
# Normally, we want to build the filename from the target and the toolchain.
# This disambiguates from the $(target).mk file that exists in the source tree.
# However, the toolchain is part of the target in universal builds, so we
# don't want to include TOOLCHAIN in that case. FAT_ARCHS is used to test
# if we're in the universal case.
include $(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk
endif
BUILD_ROOT?=.
VPATH=$(SRC_PATH_BARE)
CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
CXXFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT)/ -I$(SRC_PATH)/
DIST_DIR?=dist
HOSTCC?=gcc
TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN)))
TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
quiet:=$(if $(or $(verbose), $(V)),, yes)
quiet:=$(if $(verbose),,yes)
qexec=$(if $(quiet),@)
# Cancel built-in implicit rules
@ -90,61 +89,15 @@ all:
.PHONY: clean
clean::
rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.S.o=.asm.S)
rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
rm -f $(CLEAN-OBJS)
.PHONY: clean
distclean: clean
if [ -z "$(target)" ]; then \
rm -f Makefile; \
rm -f config.log config.mk; \
rm -f vpx_config.[hc] vpx_config.asm; \
else \
rm -f $(target)-$(TOOLCHAIN).mk; \
fi
.PHONY: dist
dist:
.PHONY: exampletest
exampletest:
.PHONY: install
install::
.PHONY: test
test::
.PHONY: testdata
testdata::
.PHONY: utiltest
utiltest:
.PHONY: test-no-data-check exampletest-no-data-check utiltest-no-data-check
test-no-data-check::
exampletest-no-data-check utiltest-no-data-check:
# Force to realign stack always on OS/2
ifeq ($(TOOLCHAIN), x86-os2-gcc)
CFLAGS += -mstackrealign
endif
# x86[_64]
$(BUILD_PFX)%_mmx.c.d: CFLAGS += -mmmx
$(BUILD_PFX)%_mmx.c.o: CFLAGS += -mmmx
$(BUILD_PFX)%_sse2.c.d: CFLAGS += -msse2
$(BUILD_PFX)%_sse2.c.o: CFLAGS += -msse2
$(BUILD_PFX)%_sse3.c.d: CFLAGS += -msse3
$(BUILD_PFX)%_sse3.c.o: CFLAGS += -msse3
$(BUILD_PFX)%_ssse3.c.d: CFLAGS += -mssse3
$(BUILD_PFX)%_ssse3.c.o: CFLAGS += -mssse3
$(BUILD_PFX)%_sse4.c.d: CFLAGS += -msse4.1
$(BUILD_PFX)%_sse4.c.o: CFLAGS += -msse4.1
$(BUILD_PFX)%_avx.c.d: CFLAGS += -mavx
$(BUILD_PFX)%_avx.c.o: CFLAGS += -mavx
$(BUILD_PFX)%_avx2.c.d: CFLAGS += -mavx2
$(BUILD_PFX)%_avx2.c.o: CFLAGS += -mavx2
$(BUILD_PFX)%_avx512.c.d: CFLAGS += -mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl
$(BUILD_PFX)%_avx512.c.o: CFLAGS += -mavx512f -mavx512cd -mavx512bw -mavx512dq -mavx512vl
# POWER
$(BUILD_PFX)%_vsx.c.d: CFLAGS += -maltivec -mvsx
$(BUILD_PFX)%_vsx.c.o: CFLAGS += -maltivec -mvsx
$(BUILD_PFX)%.c.d: %.c
$(if $(quiet),@echo " [DEP] $@")
@ -153,28 +106,16 @@ $(BUILD_PFX)%.c.d: %.c
$(BUILD_PFX)%.c.o: %.c
$(if $(quiet),@echo " [CC] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(CC) $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
$(BUILD_PFX)%.cc.d: %.cc
$(if $(quiet),@echo " [DEP] $@")
$(qexec)mkdir -p $(dir $@)
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
$(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -M $< | $(fmt_deps) > $@
$(BUILD_PFX)%.cc.o: %.cc
$(if $(quiet),@echo " [CXX] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
$(BUILD_PFX)%.cpp.d: %.cpp
$(if $(quiet),@echo " [DEP] $@")
$(qexec)mkdir -p $(dir $@)
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -M $< | $(fmt_deps) > $@
$(BUILD_PFX)%.cpp.o: %.cpp
$(if $(quiet),@echo " [CXX] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(CXX) $(INTERNAL_CFLAGS) $(CXXFLAGS) -c -o $@ $<
$(qexec)g++ $(INTERNAL_CFLAGS) $(CFLAGS) -c -o $@ $<
$(BUILD_PFX)%.asm.d: %.asm
$(if $(quiet),@echo " [DEP] $@")
@ -184,29 +125,26 @@ $(BUILD_PFX)%.asm.d: %.asm
$(BUILD_PFX)%.asm.o: %.asm
$(if $(quiet),@echo " [AS] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(AS) $(ASFLAGS) -o $@ $<
$(BUILD_PFX)%.S.d: %.S
$(BUILD_PFX)%.s.d: %.s
$(if $(quiet),@echo " [DEP] $@")
$(qexec)mkdir -p $(dir $@)
$(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
--build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
$(BUILD_PFX)%.S.o: %.S
$(BUILD_PFX)%.s.o: %.s
$(if $(quiet),@echo " [AS] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(AS) $(ASFLAGS) -o $@ $<
.PRECIOUS: %.c.S
%.c.S: CFLAGS += -DINLINE_ASM
$(BUILD_PFX)%.c.S: %.c
$(if $(quiet),@echo " [GEN] $@")
$(qexec)$(if $(CONFIG_DEPENDENCY_TRACKING),,mkdir -p $(dir $@))
$(qexec)$(CC) -S $(CFLAGS) -o $@ $<
.PRECIOUS: %.asm.S
$(BUILD_PFX)%.asm.S: %.asm
.PRECIOUS: %.asm.s
$(BUILD_PFX)%.asm.s: %.asm
$(if $(quiet),@echo " [ASM CONVERSION] $@")
$(qexec)mkdir -p $(dir $@)
$(qexec)$(ASM_CONVERSION) <$< >$@
@ -215,13 +153,13 @@ $(BUILD_PFX)%.asm.S: %.asm
# the copy implementation
HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
ifeq ($(HAVE_GNU_STRIP),yes)
# Older binutils strip global symbols not needed for relocation processing
# when given --strip-unneeded. Using nm and awk to identify globals and
# keep them caused command line length issues under mingw and segfaults in
# test_libvpx were observed under OS/2: simply use --strip-debug.
# Older binutils strip global sybols not needed for relocation processing
# when given --strip-unneeded. Use nm and awk to identify globals and
# keep them.
%.a: %_g.a
$(if $(quiet),@echo " [STRIP] $@ < $<")
$(qexec)$(STRIP) --strip-debug \
$(qexec)$(STRIP) --strip-unneeded \
`$(NM) $< | grep ' [A-TV-Z] ' | awk '{print "-K"$$3'}`\
-o $@ $<
else
%.a: %_g.a
@ -229,6 +167,14 @@ else
$(qexec)cp $< $@
endif
#
# Rule to extract assembly constants from C sources
#
obj_int_extract: build/make/obj_int_extract.c
$(if $(quiet),@echo " [HOSTCC] $@")
$(qexec)$(HOSTCC) -I. -I$(SRC_PATH_BARE) -o $@ $<
CLEAN-OBJS += obj_int_extract
#
# Utility functions
#
@ -242,7 +188,7 @@ cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o .cpp=.cpp.o
obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o .cc=.cc.o
objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
@ -267,7 +213,7 @@ define linkerxx_template
$(1): $(filter-out -%,$(2))
$(1):
$(if $(quiet),@echo " [LD] $$@")
$(qexec)$$(CXX) $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
$(qexec)g++ $$(strip $$(INTERNAL_LDFLAGS) $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
endef
# make-3.80 has a bug with expanding large input strings to the eval function,
# which was triggered in some cases by the following component of
@ -290,7 +236,7 @@ define archive_template
# for creating them.
$(1):
$(if $(quiet),@echo " [AR] $$@")
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$^
$(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
endef
define so_template
@ -303,32 +249,20 @@ $(1):
$(if $(quiet),@echo " [LD] $$@")
$(qexec)$$(LD) -shared $$(LDFLAGS) \
-Wl,--no-undefined -Wl,-soname,$$(SONAME) \
-Wl,--version-script,$$(EXPORTS_FILE) -o $$@ \
$$(filter %.o,$$^) $$(extralibs)
-Wl,--version-script,$$(SO_VERSION_SCRIPT) -o $$@ \
$$(filter %.o,$$?) $$(extralibs)
endef
define dl_template
# Not using a pattern rule here because we don't want to generate empty
# archives when they are listed as a dependency in files not responsible
# for creating them.
$(1):
$(if $(quiet),@echo " [LD] $$@")
$(qexec)$$(LD) -dynamiclib $$(LDFLAGS) \
-exported_symbols_list $$(EXPORTS_FILE) \
-Wl,-headerpad_max_install_names,-compatibility_version,1.0,-current_version,$$(VERSION_MAJOR) \
-o $$@ \
$$(filter %.o,$$^) $$(extralibs)
define lipo_lib_template
$(1): $(addsuffix /$(1),$(FAT_ARCHS))
$(if $(quiet),@echo " [LIPO] $$@")
$(qexec)libtool -static -o $$@ $$?
endef
define dll_template
# Not using a pattern rule here because we don't want to generate empty
# archives when they are listed as a dependency in files not responsible
# for creating them.
$(1):
$(if $(quiet),@echo " [LD] $$@")
$(qexec)$$(LD) -Zdll $$(LDFLAGS) \
-o $$@ \
$$(filter %.o,$$^) $$(extralibs) $$(EXPORTS_FILE)
define lipo_bin_template
$(1): $(addsuffix /$(1),$(FAT_ARCHS))
$(if $(quiet),@echo " [LIPO] $$@")
$(qexec)lipo -output $$@ -create $$?
endef
@ -338,15 +272,10 @@ endef
ifneq ($(target),)
include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
endif
skip_deps := $(filter %clean,$(MAKECMDGOALS))
skip_deps += $(findstring testdata,$(MAKECMDGOALS))
ifeq ($(strip $(skip_deps)),)
ifeq ($(CONFIG_DEPENDENCY_TRACKING),yes)
# Older versions of make don't like -include directives with no arguments
ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
-include $(filter %.d,$(OBJS-yes:.o=.d))
endif
ifeq ($(filter clean,$(MAKECMDGOALS)),)
# Older versions of make don't like -include directives with no arguments
ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
-include $(filter %.d,$(OBJS-yes:.o=.d))
endif
endif
@ -387,9 +316,7 @@ LIBS=$(call enabled,LIBS)
.libs: $(LIBS)
@touch $@
$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
$(foreach lib,$(filter %so.$(SO_VERSION_MAJOR).$(SO_VERSION_MINOR).$(SO_VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dylib,$(LIBS)),$(eval $(call dl_template,$(lib))))
$(foreach lib,$(filter %$(SO_VERSION_MAJOR).dll,$(LIBS)),$(eval $(call dll_template,$(lib))))
$(foreach lib,$(filter %so.$(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH),$(LIBS)),$(eval $(call so_template,$(lib))))
INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
ifeq ($(MAKECMDGOALS),dist)
@ -425,14 +352,14 @@ ifneq ($(call enabled,DIST-SRCS),)
DIST-SRCS-yes += build/make/gen_asm_deps.sh
DIST-SRCS-yes += build/make/Makefile
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_vcxproj.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/msvs_common.sh
DIST-SRCS-$(CONFIG_MSVS) += build/x86-msvs/yasm.rules
DIST-SRCS-$(CONFIG_MSVS) += build/x86-msvs/obj_int_extract.bat
DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
# Include obj_int_extract if we use offsets from asm_*_offsets
DIST-SRCS-$(ARCH_ARM)$(ARCH_X86)$(ARCH_X86_64) += build/make/obj_int_extract.c
DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl
DIST-SRCS-$(ARCH_ARM) += build/make/ads2gas_apple.pl
DIST-SRCS-$(ARCH_ARM) += build/make/ads2armasm_ms.pl
DIST-SRCS-$(ARCH_ARM) += build/make/thumb.pm
DIST-SRCS-yes += $(target:-$(TOOLCHAIN)=).mk
endif
INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
@ -455,5 +382,3 @@ all: $(BUILD_TARGETS)
install:: $(INSTALL_TARGETS)
dist: $(INSTALL_TARGETS)
test::
.SUFFIXES: # Delete default suffix rules

View File

@ -1,39 +0,0 @@
#!/usr/bin/env perl
##
## Copyright (c) 2013 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
use FindBin;
use lib $FindBin::Bin;
use thumb;
print "; This file was created from a .asm file\n";
print "; using the ads2armasm_ms.pl script.\n";
while (<STDIN>)
{
undef $comment;
undef $line;
s/REQUIRE8//;
s/PRESERVE8//;
s/^\s*ARM\s*$//;
s/AREA\s+\|\|(.*)\|\|/AREA |$1|/;
s/qsubaddx/qsax/i;
s/qaddsubx/qasx/i;
thumb::FixThumbInstructions($_, 1);
s/ldrneb/ldrbne/i;
s/ldrneh/ldrhne/i;
s/^(\s*)ENDP.*/$&\n$1ALIGN 4/;
print;
}

View File

@ -1,4 +1,4 @@
#!/usr/bin/env perl
#!/usr/bin/perl
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
@ -17,48 +17,21 @@
#
# Usage: cat inputfile | perl ads2gas.pl > outputfile
#
use FindBin;
use lib $FindBin::Bin;
use thumb;
my $thumb = 0;
my $elf = 1;
foreach my $arg (@ARGV) {
$thumb = 1 if ($arg eq "-thumb");
$elf = 0 if ($arg eq "-noelf");
}
print "@ This file was created from a .asm file\n";
print "@ using the ads2gas.pl script.\n";
print "\t.equ DO1STROUNDING, 0\n";
if ($thumb) {
print "\t.syntax unified\n";
print "\t.thumb\n";
}
# Stack of procedure names.
@proc_stack = ();
while (<STDIN>)
{
undef $comment;
undef $line;
$comment_char = ";";
$comment_sub = "@";
# Handle comments.
if (/$comment_char/)
{
$comment = "";
($line, $comment) = /(.*?)$comment_char(.*)/;
$_ = $line;
}
# Load and store alignment
s/@/,:/g;
# Comment character
s/;/@/g;
# Hexadecimal constants prefaced by 0x
s/#&/#0x/g;
@ -78,27 +51,16 @@ while (<STDIN>)
s/:SHR:/ >> /g;
# Convert ELSE to .else
s/\bELSE\b/.else/g;
s/ELSE/.else/g;
# Convert ENDIF to .endif
s/\bENDIF\b/.endif/g;
s/ENDIF/.endif/g;
# Convert ELSEIF to .elseif
s/\bELSEIF\b/.elseif/g;
s/ELSEIF/.elseif/g;
# Convert LTORG to .ltorg
s/\bLTORG\b/.ltorg/g;
# Convert endfunc to nothing.
s/\bendfunc\b//ig;
# Convert FUNCTION to nothing.
s/\bFUNCTION\b//g;
s/\bfunction\b//g;
s/\bENTRY\b//g;
s/\bMSARMASM\b/0/g;
s/^\s+end\s+$//g;
s/LTORG/.ltorg/g;
# Convert IF :DEF:to .if
# gcc doesn't have the ability to do a conditional
@ -140,18 +102,18 @@ while (<STDIN>)
s/DCD(.*)/.long $1/;
s/DCB(.*)/.byte $1/;
# RN to .req
if (s/RN\s+([Rr]\d+|lr)/.req $1/)
{
print;
next;
}
# Make function visible to linker, and make additional symbol with
# prepended underscore
if ($elf) {
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
} else {
s/EXPORT\s+\|([\$\w]*)\|/.global $1/;
}
s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
s/EXPORT\s+([\$\w]*)/.global $1/;
s/export\s+([\$\w]*)/.global $1/;
# No vertical bars required; make additional symbol with prepended
# underscore
s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
@ -162,41 +124,19 @@ while (<STDIN>)
s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
# ALIGN directive
s/\bALIGN\b/.balign/g;
s/ALIGN/.balign/g;
if ($thumb) {
# ARM code - we force everything to thumb with the declaration in the header
s/\sARM//g;
} else {
# ARM code
s/\sARM/.arm/g;
}
# push/pop
s/(push\s+)(r\d+)/stmdb sp\!, \{$2\}/g;
s/(pop\s+)(r\d+)/ldmia sp\!, \{$2\}/g;
# NEON code
s/(vld1.\d+\s+)(q\d+)/$1\{$2\}/g;
s/(vtbl.\d+\s+[^,]+),([^,]+)/$1,\{$2\}/g;
if ($thumb) {
thumb::FixThumbInstructions($_, 0);
}
# ARM code
s/\sARM/.arm/g;
# eabi_attributes numerical equivalents can be found in the
# "ARM IHI 0045C" document.
if ($elf) {
# REQUIRE8 Stack is required to be 8-byte aligned
s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
# REQUIRE8 Stack is required to be 8-byte aligned
s/\sREQUIRE8/.eabi_attribute 24, 1 \@Tag_ABI_align_needed/g;
# PRESERVE8 Stack 8-byte align is preserved
s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
} else {
s/\sREQUIRE8//;
s/\sPRESERVE8//;
}
# PRESERVE8 Stack 8-byte align is preserved
s/\sPRESERVE8/.eabi_attribute 25, 1 \@Tag_ABI_align_preserved/g;
# Use PROC and ENDP to give the symbols a .size directive.
# This makes them show up properly in debugging tools like gdb and valgrind.
@ -213,14 +153,14 @@ while (<STDIN>)
my $proc;
s/\bENDP\b/@ $&/;
$proc = pop(@proc_stack);
$_ = "\t.size $proc, .-$proc".$_ if ($proc and $elf);
$_ = "\t.size $proc, .-$proc".$_ if ($proc);
}
# EQU directive
s/(\S+\s+)EQU(\s+\S+)/.equ $1, $2/;
s/(.*)EQU(.*)/.equ $1, $2/;
# Begin macro definition
if (/\bMACRO\b/) {
if (/MACRO/) {
$_ = <STDIN>;
s/^/.macro/;
s/\$//g; # remove formal param reference
@ -229,11 +169,10 @@ while (<STDIN>)
# For macros, use \ to reference formal params
s/\$/\\/g; # End macro definition
s/\bMEND\b/.endm/; # No need to tell it where to stop assembling
s/MEND/.endm/; # No need to tell it where to stop assembling
next if /^\s*END\s*$/;
print;
print "$comment_sub$comment\n" if defined $comment;
}
# Mark that this object doesn't need an executable stack.
printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n") if $elf;
printf ("\t.section\t.note.GNU-stack,\"\",\%\%progbits\n");

View File

@ -10,14 +10,13 @@
##
# ads2gas_apple.pl
# ads2gas.pl
# Author: Eric Fung (efung (at) acm.org)
#
# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
#
# Usage: cat inputfile | perl ads2gas_apple.pl > outputfile
# Usage: cat inputfile | perl ads2gas.pl > outputfile
#
print "@ This file was created from a .asm file\n";
print "@ using the ads2gas_apple.pl script.\n\n";
print "\t.set WIDE_REFERENCE, 0\n";
@ -48,7 +47,7 @@ while (<STDIN>)
s/@/,:/g;
# Comment character
s/;/ @/g;
s/;/@/g;
# Hexadecimal constants prefaced by 0x
s/#&/#0x/g;
@ -69,16 +68,16 @@ while (<STDIN>)
s/:SHR:/ >> /g;
# Convert ELSE to .else
s/\bELSE\b/.else/g;
s/ELSE/.else/g;
# Convert ENDIF to .endif
s/\bENDIF\b/.endif/g;
s/ENDIF/.endif/g;
# Convert ELSEIF to .elseif
s/\bELSEIF\b/.elseif/g;
s/ELSEIF/.elseif/g;
# Convert LTORG to .ltorg
s/\bLTORG\b/.ltorg/g;
s/LTORG/.ltorg/g;
# Convert IF :DEF:to .if
# gcc doesn't have the ability to do a conditional
@ -120,6 +119,18 @@ while (<STDIN>)
s/DCD(.*)/.long $1/;
s/DCB(.*)/.byte $1/;
# Build a hash of all the register - alias pairs.
if (s/(.*)RN(.*)/$1 .req $2/g)
{
$register_aliases{trim($1)} = trim($2);
next;
}
while (($key, $value) = each(%register_aliases))
{
s/\b$key\b/$value/g;
}
# Make function visible to linker, and make additional symbol with
# prepended underscore
s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/;
@ -146,7 +157,7 @@ while (<STDIN>)
s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
# ALIGN directive
s/\bALIGN\b/.balign/g;
s/ALIGN/.balign/g;
# Strip ARM
s/\sARM/@ ARM/g;
@ -166,7 +177,7 @@ while (<STDIN>)
s/(.*)EQU(.*)/.set $1, $2/;
# Begin macro definition
if (/\bMACRO\b/)
if (/MACRO/)
{
# Process next line down, which will be the macro definition
$_ = <STDIN>;
@ -177,7 +188,7 @@ while (<STDIN>)
$trimmed =~ s/,//g;
# string to array
@incoming_array = split(/\s+/, $trimmed);
@incoming_array = split(/ /, $trimmed);
print ".macro @incoming_array[0]\n";
@ -197,8 +208,7 @@ while (<STDIN>)
# For macros, use \ to reference formal params
# s/\$/\\/g; # End macro definition
s/\bMEND\b/.endm/; # No need to tell it where to stop assembling
s/MEND/.endm/; # No need to tell it where to stop assembling
next if /^\s*END\s*$/;
print;
}

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
@ -13,20 +13,20 @@
verbose=0
set -- $*
for i; do
if [ "$i" = "-o" ]; then
if [ "$i" == "-o" ]; then
on_of=1
elif [ "$i" = "-v" ]; then
elif [ "$i" == "-v" ]; then
verbose=1
elif [ "$i" = "-g" ]; then
elif [ "$i" == "-g" ]; then
args="${args} --debug"
elif [ "$on_of" = "1" ]; then
elif [ "$on_of" == "1" ]; then
outfile=$i
on_of=0
elif [ -f "$i" ]; then
infiles="$infiles $i"
elif [ "${i#-l}" != "$i" ]; then
elif [ "${i:0:2}" == "-l" ]; then
libs="$libs ${i#-l}"
elif [ "${i#-L}" != "$i" ]; then
elif [ "${i:0:2}" == "-L" ]; then
libpaths="${libpaths} ${i#-L}"
else
args="${args} ${i}"

1954
build/make/configure.sh Normal file → Executable file

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
@ -42,7 +42,7 @@ done
[ -n "$srcfile" ] || show_help
sfx=${sfx:-asm}
includes=$(LC_ALL=C egrep -i "include +\"?[a-z0-9_/]+\.${sfx}" $srcfile |
includes=$(egrep -i "include +\"?+[a-z0-9_/]+\.${sfx}" $srcfile |
perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;")
#" restore editor state
for inc in ${includes}; do

573
build/make/gen_msvs_proj.sh Executable file
View File

@ -0,0 +1,573 @@
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
self=$0
self_basename=${self##*/}
self_dirname=$(dirname "$0")
EOL=$'\n'
show_help() {
cat <<EOF
Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
This script generates a Visual Studio project file from a list of source
code files.
Options:
--help Print this message
--exe Generate a project for building an Application
--lib Generate a project for creating a static library
--static-crt Use the static C runtime (/MT)
--target=isa-os-cc Target specifier (required)
--out=filename Write output to a file [stdout]
--name=project_name Name of the project (required)
--proj-guid=GUID GUID to use for the project
--module-def=filename File containing export definitions (for DLLs)
--ver=version Version (7,8,9) of visual studio to generate for
--src-path-bare=dir Path to root of source tree
-Ipath/to/include Additional include directories
-DFLAG[=value] Preprocessor macros to define
-Lpath/to/lib Additional library search paths
-llibname Library to link against
EOF
exit 1
}
die() {
echo "${self_basename}: $@" >&2
exit 1
}
die_unknown(){
echo "Unknown option \"$1\"." >&2
echo "See ${self_basename} --help for available options." >&2
exit 1
}
generate_uuid() {
local hex="0123456789ABCDEF"
local i
local uuid=""
local j
#93995380-89BD-4b04-88EB-625FBE52EBFB
for ((i=0; i<32; i++)); do
(( j = $RANDOM % 16 ))
uuid="${uuid}${hex:$j:1}"
done
echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
}
indent1=" "
indent=""
indent_push() {
indent="${indent}${indent1}"
}
indent_pop() {
indent="${indent%${indent1}}"
}
tag_attributes() {
for opt in "$@"; do
optval="${opt#*=}"
[ -n "${optval}" ] ||
die "Missing attribute value in '$opt' while generating $tag tag"
echo "${indent}${opt%%=*}=\"${optval}\""
done
}
open_tag() {
local tag=$1
shift
if [ $# -ne 0 ]; then
echo "${indent}<${tag}"
indent_push
tag_attributes "$@"
echo "${indent}>"
else
echo "${indent}<${tag}>"
indent_push
fi
}
close_tag() {
local tag=$1
indent_pop
echo "${indent}</${tag}>"
}
tag() {
local tag=$1
shift
if [ $# -ne 0 ]; then
echo "${indent}<${tag}"
indent_push
tag_attributes "$@"
indent_pop
echo "${indent}/>"
else
echo "${indent}<${tag}/>"
fi
}
generate_filter() {
local var=$1
local name=$2
local pats=$3
local file_list_sz
local i
local f
local saveIFS="$IFS"
local pack
echo "generating filter '$name' from ${#file_list[@]} files" >&2
IFS=*
open_tag Filter \
Name=$name \
Filter=$pats \
UniqueIdentifier=`generate_uuid` \
file_list_sz=${#file_list[@]}
for i in ${!file_list[@]}; do
f=${file_list[i]}
for pat in ${pats//;/$IFS}; do
if [ "${f##*.}" == "$pat" ]; then
unset file_list[i]
open_tag File RelativePath="./$f"
if [ "$pat" == "asm" ] && $asm_use_custom_step; then
for plat in "${platforms[@]}"; do
for cfg in Debug Release; do
open_tag FileConfiguration \
Name="${cfg}|${plat}" \
tag Tool \
Name="VCCustomBuildTool" \
Description="Assembling \$(InputFileName)" \
CommandLine="$(eval echo \$asm_${cfg}_cmdline)" \
Outputs="\$(InputName).obj" \
close_tag FileConfiguration
done
done
fi
close_tag File
break
fi
done
done
close_tag Filter
IFS="$saveIFS"
}
# Process command line
unset target
for opt in "$@"; do
optval="${opt#*=}"
case "$opt" in
--help|-h) show_help
;;
--target=*) target="${optval}"
;;
--out=*) outfile="$optval"
;;
--name=*) name="${optval}"
;;
--proj-guid=*) guid="${optval}"
;;
--module-def=*) link_opts="${link_opts} ModuleDefinitionFile=${optval}"
;;
--exe) proj_kind="exe"
;;
--lib) proj_kind="lib"
;;
--src-path-bare=*) src_path_bare="$optval"
;;
--static-crt) use_static_runtime=true
;;
--ver=*)
vs_ver="$optval"
case "$optval" in
[789])
;;
*) die Unrecognized Visual Studio Version in $opt
;;
esac
;;
-I*)
opt="${opt%/}"
incs="${incs}${incs:+;}&quot;${opt##-I}&quot;"
yasmincs="${yasmincs} ${opt}"
;;
-D*) defines="${defines}${defines:+;}${opt##-D}"
;;
-L*) # fudge . to $(OutDir)
if [ "${opt##-L}" == "." ]; then
libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
else
# Also try directories for this platform/configuration
libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}&quot;"
libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)/\$(ConfigurationName)&quot;"
libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)&quot;"
fi
;;
-l*) libs="${libs}${libs:+ }${opt##-l}.lib"
;;
-*) die_unknown $opt
;;
*)
file_list[${#file_list[@]}]="$opt"
case "$opt" in
*.asm) uses_asm=true
;;
esac
;;
esac
done
outfile=${outfile:-/dev/stdout}
guid=${guid:-`generate_uuid`}
asm_use_custom_step=false
uses_asm=${uses_asm:-false}
case "${vs_ver:-8}" in
7) vs_ver_id="7.10"
asm_use_custom_step=$uses_asm
;;
8) vs_ver_id="8.00"
;;
9) vs_ver_id="9.00"
;;
esac
[ -n "$name" ] || die "Project name (--name) must be specified!"
[ -n "$target" ] || die "Target (--target) must be specified!"
if ${use_static_runtime:-false}; then
release_runtime=0
debug_runtime=1
lib_sfx=mt
else
release_runtime=2
debug_runtime=3
lib_sfx=md
fi
# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
# debug exe, so this may need to be refactored later.
for lib in ${libs}; do
if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
lib=${lib%.lib}d.lib
fi
debug_libs="${debug_libs}${debug_libs:+ }${lib}"
done
# List Keyword for this target
case "$target" in
x86*) keyword="ManagedCProj"
;;
*) die "Unsupported target $target!"
esac
# List of all platforms supported for this target
case "$target" in
x86_64*)
platforms[0]="x64"
;;
x86*)
platforms[0]="Win32"
# these are only used by vs7
asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} &quot;\$(InputPath)&quot;"
;;
*) die "Unsupported target $target!"
;;
esac
generate_vcproj() {
case "$proj_kind" in
exe) vs_ConfigurationType=1
;;
*) vs_ConfigurationType=4
;;
esac
echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
open_tag VisualStudioProject \
ProjectType="Visual C++" \
Version="${vs_ver_id}" \
Name="${name}" \
ProjectGUID="{${guid}}" \
RootNamespace="${name}" \
Keyword="${keyword}" \
open_tag Platforms
for plat in "${platforms[@]}"; do
tag Platform Name="$plat"
done
close_tag Platforms
open_tag ToolFiles
case "$target" in
x86*) $uses_asm && tag ToolFile RelativePath="$self_dirname/../x86-msvs/yasm.rules"
;;
esac
close_tag ToolFiles
open_tag Configurations
for plat in "${platforms[@]}"; do
plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
open_tag Configuration \
Name="Debug|$plat" \
OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
ConfigurationType="$vs_ConfigurationType" \
CharacterSet="1" \
case "$target" in
x86*)
case "$name" in
obj_int_extract)
tag Tool \
Name="VCCLCompilerTool" \
Optimization="0" \
AdditionalIncludeDirectories="$incs" \
PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
RuntimeLibrary="$debug_runtime" \
WarningLevel="3" \
Detect64BitPortabilityProblems="true" \
DebugInformationFormat="1" \
;;
vpx)
tag Tool \
Name="VCPreBuildEventTool" \
CommandLine="call obj_int_extract.bat $src_path_bare" \
tag Tool \
Name="VCCLCompilerTool" \
Optimization="0" \
AdditionalIncludeDirectories="$incs" \
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
RuntimeLibrary="$debug_runtime" \
UsePrecompiledHeader="0" \
WarningLevel="3" \
DebugInformationFormat="1" \
Detect64BitPortabilityProblems="true" \
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true"
;;
*)
tag Tool \
Name="VCCLCompilerTool" \
Optimization="0" \
AdditionalIncludeDirectories="$incs" \
PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
RuntimeLibrary="$debug_runtime" \
UsePrecompiledHeader="0" \
WarningLevel="3" \
DebugInformationFormat="1" \
Detect64BitPortabilityProblems="true" \
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="true"
;;
esac
;;
esac
case "$proj_kind" in
exe)
case "$target" in
x86*)
case "$name" in
obj_int_extract)
tag Tool \
Name="VCLinkerTool" \
OutputFile="${name}.exe" \
GenerateDebugInformation="true" \
;;
*)
tag Tool \
Name="VCLinkerTool" \
AdditionalDependencies="$debug_libs \$(NoInherit)" \
AdditionalLibraryDirectories="$libdirs" \
GenerateDebugInformation="true" \
ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
;;
esac
;;
esac
;;
lib)
case "$target" in
x86*)
tag Tool \
Name="VCLibrarianTool" \
OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
;;
esac
;;
dll)
tag Tool \
Name="VCLinkerTool" \
AdditionalDependencies="\$(NoInherit)" \
LinkIncremental="2" \
GenerateDebugInformation="true" \
AssemblyDebug="1" \
TargetMachine="1" \
$link_opts \
;;
esac
close_tag Configuration
open_tag Configuration \
Name="Release|$plat" \
OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
ConfigurationType="$vs_ConfigurationType" \
CharacterSet="1" \
WholeProgramOptimization="0" \
case "$target" in
x86*)
case "$name" in
obj_int_extract)
tag Tool \
Name="VCCLCompilerTool" \
Optimization="2" \
FavorSizeorSpeed="1" \
AdditionalIncludeDirectories="$incs" \
PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE" \
RuntimeLibrary="$release_runtime" \
UsePrecompiledHeader="0" \
WarningLevel="3" \
Detect64BitPortabilityProblems="true" \
DebugInformationFormat="0" \
;;
vpx)
tag Tool \
Name="VCPreBuildEventTool" \
CommandLine="call obj_int_extract.bat $src_path_bare" \
tag Tool \
Name="VCCLCompilerTool" \
Optimization="2" \
FavorSizeorSpeed="1" \
AdditionalIncludeDirectories="$incs" \
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
RuntimeLibrary="$release_runtime" \
UsePrecompiledHeader="0" \
WarningLevel="3" \
DebugInformationFormat="0" \
Detect64BitPortabilityProblems="true" \
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
;;
*)
tag Tool \
Name="VCCLCompilerTool" \
AdditionalIncludeDirectories="$incs" \
Optimization="2" \
FavorSizeorSpeed="1" \
PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE;$defines" \
RuntimeLibrary="$release_runtime" \
UsePrecompiledHeader="0" \
WarningLevel="3" \
DebugInformationFormat="0" \
Detect64BitPortabilityProblems="true" \
$uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
;;
esac
;;
esac
case "$proj_kind" in
exe)
case "$target" in
x86*)
case "$name" in
obj_int_extract)
tag Tool \
Name="VCLinkerTool" \
OutputFile="${name}.exe" \
GenerateDebugInformation="true" \
;;
*)
tag Tool \
Name="VCLinkerTool" \
AdditionalDependencies="$libs \$(NoInherit)" \
AdditionalLibraryDirectories="$libdirs" \
;;
esac
;;
esac
;;
lib)
case "$target" in
x86*)
tag Tool \
Name="VCLibrarianTool" \
OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
;;
esac
;;
dll) # note differences to debug version: LinkIncremental, AssemblyDebug
tag Tool \
Name="VCLinkerTool" \
AdditionalDependencies="\$(NoInherit)" \
LinkIncremental="1" \
GenerateDebugInformation="true" \
TargetMachine="1" \
$link_opts \
;;
esac
close_tag Configuration
done
close_tag Configurations
open_tag Files
generate_filter srcs "Source Files" "c;cc;def;odl;idl;hpj;bat;asm;asmx"
generate_filter hdrs "Header Files" "h;hm;inl;inc;xsd"
generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
generate_filter resrcs "Build Files" "mk"
close_tag Files
tag Globals
close_tag VisualStudioProject
# This must be done from within the {} subshell
echo "Ignored files list (${#file_list[@]} items) is:" >&2
for f in "${file_list[@]}"; do
echo " $f" >&2
done
}
generate_vcproj |
sed -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
exit
<!--
TODO: Add any files not captured by filters.
<File
RelativePath=".\ReadMe.txt"
>
</File>
-->

View File

@ -19,13 +19,13 @@ show_help() {
cat <<EOF
Usage: ${self_basename} [options] file1 [file2 ...]
This script generates a Visual Studio solution file from a list of project
This script generates a Visual Studio 2005 solution file from a list of project
files.
Options:
--help Print this message
--out=outfile Redirect output to a file
--ver=version Version (7,8,9,10,11,12,14,15) of visual studio to generate for
--ver=version Version (7,8,9) of visual studio to generate for
--target=isa-os-cc Target specifier
EOF
exit 1
@ -55,28 +55,22 @@ indent_pop() {
parse_project() {
local file=$1
local name=`grep RootNamespace "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
local guid=`grep ProjectGuid "$file" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
# save the project GUID to a varaible, normalizing to the basename of the
# vcxproj file without the extension
# vcproj file without the extension
local var
var=${file##*/}
var=${var%%.${sfx}}
var=${var%%.vcproj}
eval "${var}_file=\"$1\""
eval "${var}_name=$name"
eval "${var}_guid=$guid"
cur_config_list=`grep -B1 'Label="Configuration"' $file |
grep Condition | cut -d\' -f4`
new_config_list=$(for i in $config_list $cur_config_list; do
echo $i
done | sort | uniq)
if [ "$config_list" != "" ] && [ "$config_list" != "$new_config_list" ]; then
mixed_platforms=1
fi
config_list="$new_config_list"
eval "${var}_config_list=\"$cur_config_list\""
# assume that all projects have the same list of possible configurations,
# so overwriting old config_lists is not a problem
config_list=`grep -A1 '<Configuration' $file |
grep Name | cut -d\" -f2`
proj_list="${proj_list} ${var}"
}
@ -89,10 +83,29 @@ process_project() {
# vcproj file without the extension
local var
var=${file##*/}
var=${var%%.${sfx}}
var=${var%%.vcproj}
eval "${var}_guid=$guid"
echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\""
indent_push
eval "local deps=\"\${${var}_deps}\""
if [ -n "$deps" ]; then
echo "${indent}ProjectSection(ProjectDependencies) = postProject"
indent_push
for dep in $deps; do
eval "local dep_guid=\${${dep}_guid}"
[ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)"
echo "${indent}$dep_guid = $dep_guid"
done
indent_pop
echo "${indent}EndProjectSection"
fi
indent_pop
echo "EndProject"
}
@ -107,11 +120,6 @@ process_global() {
indent_push
IFS_bak=${IFS}
IFS=$'\r'$'\n'
if [ "$mixed_platforms" != "" ]; then
config_list="
Release|Mixed Platforms
Debug|Mixed Platforms"
fi
for config in ${config_list}; do
echo "${indent}$config = $config"
done
@ -126,17 +134,10 @@ Debug|Mixed Platforms"
indent_push
for proj in ${proj_list}; do
eval "local proj_guid=\${${proj}_guid}"
eval "local proj_config_list=\${${proj}_config_list}"
IFS=$'\r'$'\n'
for config in ${proj_config_list}; do
if [ "$mixed_platforms" != "" ]; then
local c=${config%%|*}
echo "${indent}${proj_guid}.${c}|Mixed Platforms.ActiveCfg = ${config}"
echo "${indent}${proj_guid}.${c}|Mixed Platforms.Build.0 = ${config}"
else
echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}"
echo "${indent}${proj_guid}.${config}.Build.0 = ${config}"
fi
for config in ${config_list}; do
echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}"
echo "${indent}${proj_guid}.${config}.Build.0 = ${config}"
done
IFS=${IFS_bak}
@ -162,16 +163,15 @@ process_makefile() {
IFS=$'\r'$'\n'
local TAB=$'\t'
cat <<EOF
MSBUILD_TOOL := msbuild.exe
found_devenv := \$(shell which \$(MSBUILD_TOOL) >/dev/null 2>&1 && echo yes)
found_devenv := \$(shell which devenv.com >/dev/null 2>&1 && echo yes)
.nodevenv.once:
${TAB}@echo " * \$(MSBUILD_TOOL) not found in path."
${TAB}@echo " * devenv.com not found in path."
${TAB}@echo " * "
${TAB}@echo " * You will have to build all configurations manually using the"
${TAB}@echo " * Visual Studio IDE. To allow make to build them automatically,"
${TAB}@echo " * add the Common7/IDE directory of your Visual Studio"
${TAB}@echo " * installation to your path, eg:"
${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE"
${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"
${TAB}@echo " * "
${TAB}@touch \$@
CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
@ -188,12 +188,18 @@ clean::
${TAB}rm -rf "$platform"/"$config"
.PHONY: $nows_sln_config
ifneq (\$(found_devenv),)
ifeq (\$(CONFIG_VS_VERSION),7)
$nows_sln_config: $outfile
${TAB}\$(MSBUILD_TOOL) $outfile -m -t:Build \\
${TAB}${TAB}-p:Configuration="$config" -p:Platform="$platform"
${TAB}devenv.com $outfile -build "$config"
else
$nows_sln_config: $outfile
${TAB}devenv.com $outfile -build "$sln_config"
endif
else
$nows_sln_config: $outfile .nodevenv.once
${TAB}@echo " * Skipping build of $sln_config (\$(MSBUILD_TOOL) not in path)."
${TAB}@echo " * Skipping build of $sln_config (devenv.com not in path)."
${TAB}@echo " * "
endif
@ -215,12 +221,23 @@ for opt in "$@"; do
;;
--ver=*) vs_ver="$optval"
case $optval in
10|11|12|14|15)
[789])
;;
*) die Unrecognized Visual Studio Version in $opt
;;
esac
;;
--ver=*) vs_ver="$optval"
case $optval in
7) sln_vers="8.00"
sln_vers_str="Visual Studio .NET 2003"
;;
[89])
;;
*) die "Unrecognized Visual Studio Version '$optval' in $opt"
;;
esac
;;
--target=*) target="${optval}"
;;
-*) die_unknown $opt
@ -230,24 +247,17 @@ for opt in "$@"; do
done
outfile=${outfile:-/dev/stdout}
mkoutfile=${mkoutfile:-/dev/stdout}
case "${vs_ver:-10}" in
10) sln_vers="11.00"
sln_vers_str="Visual Studio 2010"
case "${vs_ver:-8}" in
7) sln_vers="8.00"
sln_vers_str="Visual Studio .NET 2003"
;;
11) sln_vers="12.00"
sln_vers_str="Visual Studio 2012"
8) sln_vers="9.00"
sln_vers_str="Visual Studio 2005"
;;
12) sln_vers="12.00"
sln_vers_str="Visual Studio 2013"
;;
14) sln_vers="12.00"
sln_vers_str="Visual Studio 2015"
;;
15) sln_vers="12.00"
sln_vers_str="Visual Studio 2017"
9) sln_vers="10.00"
sln_vers_str="Visual Studio 2008"
;;
esac
sfx=vcxproj
for f in "${file_list[@]}"; do
parse_project $f

View File

@ -1,493 +0,0 @@
#!/bin/bash
##
## Copyright (c) 2013 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
self=$0
self_basename=${self##*/}
self_dirname=$(dirname "$0")
. "$self_dirname/msvs_common.sh"|| exit 127
show_help() {
cat <<EOF
Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
This script generates a Visual Studio project file from a list of source
code files.
Options:
--help Print this message
--exe Generate a project for building an Application
--lib Generate a project for creating a static library
--dll Generate a project for creating a dll
--static-crt Use the static C runtime (/MT)
--enable-werror Treat warnings as errors (/WX)
--target=isa-os-cc Target specifier (required)
--out=filename Write output to a file [stdout]
--name=project_name Name of the project (required)
--proj-guid=GUID GUID to use for the project
--module-def=filename File containing export definitions (for DLLs)
--ver=version Version (10,11,12,14,15) of visual studio to generate for
--src-path-bare=dir Path to root of source tree
-Ipath/to/include Additional include directories
-DFLAG[=value] Preprocessor macros to define
-Lpath/to/lib Additional library search paths
-llibname Library to link against
EOF
exit 1
}
tag_content() {
local tag=$1
local content=$2
shift
shift
if [ $# -ne 0 ]; then
echo "${indent}<${tag}"
indent_push
tag_attributes "$@"
echo "${indent}>${content}</${tag}>"
indent_pop
else
echo "${indent}<${tag}>${content}</${tag}>"
fi
}
generate_filter() {
local name=$1
local pats=$2
local file_list_sz
local i
local f
local saveIFS="$IFS"
local pack
echo "generating filter '$name' from ${#file_list[@]} files" >&2
IFS=*
file_list_sz=${#file_list[@]}
for i in ${!file_list[@]}; do
f=${file_list[i]}
for pat in ${pats//;/$IFS}; do
if [ "${f##*.}" == "$pat" ]; then
unset file_list[i]
objf=$(echo ${f%.*}.obj \
| sed -e "s,$src_path_bare,," \
-e 's/^[\./]\+//g' -e 's,[:/ ],_,g')
if ([ "$pat" == "asm" ] || [ "$pat" == "s" ] || [ "$pat" == "S" ]) && $asm_use_custom_step; then
# Avoid object file name collisions, i.e. vpx_config.c and
# vpx_config.asm produce the same object file without
# this additional suffix.
objf=${objf%.obj}_asm.obj
open_tag CustomBuild \
Include="$f"
for plat in "${platforms[@]}"; do
for cfg in Debug Release; do
tag_content Message "Assembling %(Filename)%(Extension)" \
Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
tag_content Command "$(eval echo \$asm_${cfg}_cmdline) -o \$(IntDir)$objf" \
Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
tag_content Outputs "\$(IntDir)$objf" \
Condition="'\$(Configuration)|\$(Platform)'=='$cfg|$plat'"
done
done
close_tag CustomBuild
elif [ "$pat" == "c" ] || \
[ "$pat" == "cc" ] || [ "$pat" == "cpp" ]; then
open_tag ClCompile \
Include="$f"
# Separate file names with Condition?
tag_content ObjectFileName "\$(IntDir)$objf"
# Check for AVX and turn it on to avoid warnings.
if [[ $f =~ avx.?\.c$ ]]; then
tag_content AdditionalOptions "/arch:AVX"
fi
close_tag ClCompile
elif [ "$pat" == "h" ] ; then
tag ClInclude \
Include="$f"
elif [ "$pat" == "vcxproj" ] ; then
open_tag ProjectReference \
Include="$f"
depguid=`grep ProjectGuid "$f" | sed 's,.*<.*>\(.*\)</.*>.*,\1,'`
tag_content Project "$depguid"
tag_content ReferenceOutputAssembly false
close_tag ProjectReference
else
tag None \
Include="$f"
fi
break
fi
done
done
IFS="$saveIFS"
}
# Process command line
unset target
for opt in "$@"; do
optval="${opt#*=}"
case "$opt" in
--help|-h) show_help
;;
--target=*) target="${optval}"
;;
--out=*) outfile="$optval"
;;
--name=*) name="${optval}"
;;
--proj-guid=*) guid="${optval}"
;;
--module-def=*) module_def="${optval}"
;;
--exe) proj_kind="exe"
;;
--dll) proj_kind="dll"
;;
--lib) proj_kind="lib"
;;
--src-path-bare=*)
src_path_bare=$(fix_path "$optval")
src_path_bare=${src_path_bare%/}
;;
--static-crt) use_static_runtime=true
;;
--enable-werror) werror=true
;;
--ver=*)
vs_ver="$optval"
case "$optval" in
10|11|12|14|15)
;;
*) die Unrecognized Visual Studio Version in $opt
;;
esac
;;
-I*)
opt=${opt##-I}
opt=$(fix_path "$opt")
opt="${opt%/}"
incs="${incs}${incs:+;}&quot;${opt}&quot;"
yasmincs="${yasmincs} -I&quot;${opt}&quot;"
;;
-D*) defines="${defines}${defines:+;}${opt##-D}"
;;
-L*) # fudge . to $(OutDir)
if [ "${opt##-L}" == "." ]; then
libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
else
# Also try directories for this platform/configuration
opt=${opt##-L}
opt=$(fix_path "$opt")
libdirs="${libdirs}${libdirs:+;}&quot;${opt}&quot;"
libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)/\$(Configuration)&quot;"
libdirs="${libdirs}${libdirs:+;}&quot;${opt}/\$(PlatformName)&quot;"
fi
;;
-l*) libs="${libs}${libs:+ }${opt##-l}.lib"
;;
-*) die_unknown $opt
;;
*)
# The paths in file_list are fixed outside of the loop.
file_list[${#file_list[@]}]="$opt"
case "$opt" in
*.asm|*.[Ss]) uses_asm=true
;;
esac
;;
esac
done
# Make one call to fix_path for file_list to improve performance.
fix_file_list file_list
outfile=${outfile:-/dev/stdout}
guid=${guid:-`generate_uuid`}
asm_use_custom_step=false
uses_asm=${uses_asm:-false}
case "${vs_ver:-11}" in
10|11|12|14|15)
asm_use_custom_step=$uses_asm
;;
esac
[ -n "$name" ] || die "Project name (--name) must be specified!"
[ -n "$target" ] || die "Target (--target) must be specified!"
if ${use_static_runtime:-false}; then
release_runtime=MultiThreaded
debug_runtime=MultiThreadedDebug
lib_sfx=mt
else
release_runtime=MultiThreadedDLL
debug_runtime=MultiThreadedDebugDLL
lib_sfx=md
fi
# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
# debug exe, so this may need to be refactored later.
for lib in ${libs}; do
if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
lib=${lib%.lib}d.lib
fi
debug_libs="${debug_libs}${debug_libs:+ }${lib}"
done
debug_libs=${debug_libs// /;}
libs=${libs// /;}
# List of all platforms supported for this target
case "$target" in
x86_64*)
platforms[0]="x64"
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
asm_Release_cmdline="yasm -Xvc -f win64 ${yasmincs} &quot;%(FullPath)&quot;"
;;
x86*)
platforms[0]="Win32"
asm_Debug_cmdline="yasm -Xvc -g cv8 -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
asm_Release_cmdline="yasm -Xvc -f win32 ${yasmincs} &quot;%(FullPath)&quot;"
;;
arm*)
platforms[0]="ARM"
asm_Debug_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
asm_Release_cmdline="armasm -nologo -oldit &quot;%(FullPath)&quot;"
;;
*) die "Unsupported target $target!"
;;
esac
generate_vcxproj() {
echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
open_tag Project \
DefaultTargets="Build" \
ToolsVersion="4.0" \
xmlns="http://schemas.microsoft.com/developer/msbuild/2003" \
open_tag ItemGroup \
Label="ProjectConfigurations"
for plat in "${platforms[@]}"; do
for config in Debug Release; do
open_tag ProjectConfiguration \
Include="$config|$plat"
tag_content Configuration $config
tag_content Platform $plat
close_tag ProjectConfiguration
done
done
close_tag ItemGroup
open_tag PropertyGroup \
Label="Globals"
tag_content ProjectGuid "{${guid}}"
tag_content RootNamespace ${name}
tag_content Keyword ManagedCProj
if [ $vs_ver -ge 12 ] && [ "${platforms[0]}" = "ARM" ]; then
tag_content AppContainerApplication true
# The application type can be one of "Windows Store",
# "Windows Phone" or "Windows Phone Silverlight". The
# actual value doesn't matter from the libvpx point of view,
# since a static library built for one works on the others.
# The PlatformToolset field needs to be set in sync with this;
# for Windows Store and Windows Phone Silverlight it should be
# v120 while it should be v120_wp81 if the type is Windows Phone.
tag_content ApplicationType "Windows Store"
tag_content ApplicationTypeRevision 8.1
fi
close_tag PropertyGroup
tag Import \
Project="\$(VCTargetsPath)\\Microsoft.Cpp.Default.props"
for plat in "${platforms[@]}"; do
for config in Release Debug; do
open_tag PropertyGroup \
Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'" \
Label="Configuration"
if [ "$proj_kind" = "exe" ]; then
tag_content ConfigurationType Application
elif [ "$proj_kind" = "dll" ]; then
tag_content ConfigurationType DynamicLibrary
else
tag_content ConfigurationType StaticLibrary
fi
if [ "$vs_ver" = "11" ]; then
if [ "$plat" = "ARM" ]; then
# Setting the wp80 toolchain automatically sets the
# WINAPI_FAMILY define, which is required for building
# code for arm with the windows headers. Alternatively,
# one could add AppContainerApplication=true in the Globals
# section and add PrecompiledHeader=NotUsing and
# CompileAsWinRT=false in ClCompile and SubSystem=Console
# in Link.
tag_content PlatformToolset v110_wp80
else
tag_content PlatformToolset v110
fi
fi
if [ "$vs_ver" = "12" ]; then
# Setting a PlatformToolset indicating windows phone isn't
# enough to build code for arm with MSVC 2013, one strictly
# has to enable AppContainerApplication as well.
tag_content PlatformToolset v120
fi
if [ "$vs_ver" = "14" ]; then
tag_content PlatformToolset v140
fi
if [ "$vs_ver" = "15" ]; then
tag_content PlatformToolset v141
fi
tag_content CharacterSet Unicode
if [ "$config" = "Release" ]; then
tag_content WholeProgramOptimization true
fi
close_tag PropertyGroup
done
done
tag Import \
Project="\$(VCTargetsPath)\\Microsoft.Cpp.props"
open_tag ImportGroup \
Label="PropertySheets"
tag Import \
Project="\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props" \
Condition="exists('\$(UserRootDir)\\Microsoft.Cpp.\$(Platform).user.props')" \
Label="LocalAppDataPlatform"
close_tag ImportGroup
tag PropertyGroup \
Label="UserMacros"
for plat in "${platforms[@]}"; do
plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
for config in Debug Release; do
open_tag PropertyGroup \
Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
tag_content OutDir "\$(SolutionDir)$plat_no_ws\\\$(Configuration)\\"
tag_content IntDir "$plat_no_ws\\\$(Configuration)\\${name}\\"
if [ "$proj_kind" == "lib" ]; then
if [ "$config" == "Debug" ]; then
config_suffix=d
else
config_suffix=""
fi
tag_content TargetName "${name}${lib_sfx}${config_suffix}"
fi
close_tag PropertyGroup
done
done
for plat in "${platforms[@]}"; do
for config in Debug Release; do
open_tag ItemDefinitionGroup \
Condition="'\$(Configuration)|\$(Platform)'=='$config|$plat'"
if [ "$name" == "vpx" ]; then
hostplat=$plat
if [ "$hostplat" == "ARM" ]; then
hostplat=Win32
fi
fi
open_tag ClCompile
if [ "$config" = "Debug" ]; then
opt=Disabled
runtime=$debug_runtime
curlibs=$debug_libs
debug=_DEBUG
else
opt=MaxSpeed
runtime=$release_runtime
curlibs=$libs
tag_content FavorSizeOrSpeed Speed
debug=NDEBUG
fi
extradefines=";$defines"
tag_content Optimization $opt
tag_content AdditionalIncludeDirectories "$incs;%(AdditionalIncludeDirectories)"
tag_content PreprocessorDefinitions "WIN32;$debug;_CRT_SECURE_NO_WARNINGS;_CRT_SECURE_NO_DEPRECATE$extradefines;%(PreprocessorDefinitions)"
tag_content RuntimeLibrary $runtime
tag_content WarningLevel Level3
if ${werror:-false}; then
tag_content TreatWarningAsError true
fi
if [ $vs_ver -ge 11 ]; then
# We need to override the defaults for these settings
# if AppContainerApplication is set.
tag_content CompileAsWinRT false
tag_content PrecompiledHeader NotUsing
tag_content SDLCheck false
fi
close_tag ClCompile
case "$proj_kind" in
exe)
open_tag Link
tag_content GenerateDebugInformation true
# Console is the default normally, but if
# AppContainerApplication is set, we need to override it.
tag_content SubSystem Console
close_tag Link
;;
dll)
open_tag Link
tag_content GenerateDebugInformation true
tag_content ModuleDefinitionFile $module_def
close_tag Link
;;
lib)
;;
esac
close_tag ItemDefinitionGroup
done
done
open_tag ItemGroup
generate_filter "Source Files" "c;cc;cpp;def;odl;idl;hpj;bat;asm;asmx;s;S"
close_tag ItemGroup
open_tag ItemGroup
generate_filter "Header Files" "h;hm;inl;inc;xsd"
close_tag ItemGroup
open_tag ItemGroup
generate_filter "Build Files" "mk"
close_tag ItemGroup
open_tag ItemGroup
generate_filter "References" "vcxproj"
close_tag ItemGroup
tag Import \
Project="\$(VCTargetsPath)\\Microsoft.Cpp.targets"
open_tag ImportGroup \
Label="ExtensionTargets"
close_tag ImportGroup
close_tag Project
# This must be done from within the {} subshell
echo "Ignored files list (${#file_list[@]} items) is:" >&2
for f in "${file_list[@]}"; do
echo " $f" >&2
done
}
# This regexp doesn't catch most of the strings in the vcxproj format,
# since they're like <tag>path</tag> instead of <tag attr="path" />
# as previously. It still seems to work ok despite this.
generate_vcxproj |
sed -e '/"/s;\([^ "]\)/;\1\\;g' |
sed -e '/xmlns/s;\\;/;g' > ${outfile}
exit

View File

@ -1,383 +0,0 @@
#!/bin/sh
##
## Copyright (c) 2014 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
##
## This script generates 'VPX.framework'. An iOS app can encode and decode VPx
## video by including 'VPX.framework'.
##
## Run iosbuild.sh to create 'VPX.framework' in the current directory.
##
set -e
devnull='> /dev/null 2>&1'
BUILD_ROOT="_iosbuild"
CONFIGURE_ARGS="--disable-docs
--disable-examples
--disable-libyuv
--disable-unit-tests"
DIST_DIR="_dist"
FRAMEWORK_DIR="VPX.framework"
FRAMEWORK_LIB="VPX.framework/VPX"
HEADER_DIR="${FRAMEWORK_DIR}/Headers/vpx"
SCRIPT_DIR=$(dirname "$0")
LIBVPX_SOURCE_DIR=$(cd ${SCRIPT_DIR}/../..; pwd)
LIPO=$(xcrun -sdk iphoneos${SDK} -find lipo)
ORIG_PWD="$(pwd)"
ARM_TARGETS="arm64-darwin-gcc
armv7-darwin-gcc
armv7s-darwin-gcc"
SIM_TARGETS="x86-iphonesimulator-gcc
x86_64-iphonesimulator-gcc"
OSX_TARGETS="x86-darwin16-gcc
x86_64-darwin16-gcc"
TARGETS="${ARM_TARGETS} ${SIM_TARGETS}"
# Configures for the target specified by $1, and invokes make with the dist
# target using $DIST_DIR as the distribution output directory.
build_target() {
local target="$1"
local old_pwd="$(pwd)"
local target_specific_flags=""
vlog "***Building target: ${target}***"
case "${target}" in
x86-*)
target_specific_flags="--enable-pic"
vlog "Enabled PIC for ${target}"
;;
esac
mkdir "${target}"
cd "${target}"
eval "${LIBVPX_SOURCE_DIR}/configure" --target="${target}" \
${CONFIGURE_ARGS} ${EXTRA_CONFIGURE_ARGS} ${target_specific_flags} \
${devnull}
export DIST_DIR
eval make dist ${devnull}
cd "${old_pwd}"
vlog "***Done building target: ${target}***"
}
# Returns the preprocessor symbol for the target specified by $1.
target_to_preproc_symbol() {
target="$1"
case "${target}" in
arm64-*)
echo "__aarch64__"
;;
armv7-*)
echo "__ARM_ARCH_7A__"
;;
armv7s-*)
echo "__ARM_ARCH_7S__"
;;
x86-*)
echo "__i386__"
;;
x86_64-*)
echo "__x86_64__"
;;
*)
echo "#error ${target} unknown/unsupported"
return 1
;;
esac
}
# Create a vpx_config.h shim that, based on preprocessor settings for the
# current target CPU, includes the real vpx_config.h for the current target.
# $1 is the list of targets.
create_vpx_framework_config_shim() {
local targets="$1"
local config_file="${HEADER_DIR}/vpx_config.h"
local preproc_symbol=""
local target=""
local include_guard="VPX_FRAMEWORK_HEADERS_VPX_VPX_CONFIG_H_"
local file_header="/*
* Copyright (c) $(date +%Y) The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/* GENERATED FILE: DO NOT EDIT! */
#ifndef ${include_guard}
#define ${include_guard}
#if defined"
printf "%s" "${file_header}" > "${config_file}"
for target in ${targets}; do
preproc_symbol=$(target_to_preproc_symbol "${target}")
printf " ${preproc_symbol}\n" >> "${config_file}"
printf "#define VPX_FRAMEWORK_TARGET \"${target}\"\n" >> "${config_file}"
printf "#include \"VPX/vpx/${target}/vpx_config.h\"\n" >> "${config_file}"
printf "#elif defined" >> "${config_file}"
mkdir "${HEADER_DIR}/${target}"
cp -p "${BUILD_ROOT}/${target}/vpx_config.h" "${HEADER_DIR}/${target}"
done
# Consume the last line of output from the loop: We don't want it.
sed -i '' -e '$d' "${config_file}"
printf "#endif\n\n" >> "${config_file}"
printf "#endif // ${include_guard}" >> "${config_file}"
}
# Verifies that $FRAMEWORK_LIB fat library contains requested builds.
verify_framework_targets() {
local requested_cpus=""
local cpu=""
# Extract CPU from full target name.
for target; do
cpu="${target%%-*}"
if [ "${cpu}" = "x86" ]; then
# lipo -info outputs i386 for libvpx x86 targets.
cpu="i386"
fi
requested_cpus="${requested_cpus}${cpu} "
done
# Get target CPUs present in framework library.
local targets_built=$(${LIPO} -info ${FRAMEWORK_LIB})
# $LIPO -info outputs a string like the following:
# Architectures in the fat file: $FRAMEWORK_LIB <architectures>
# Capture only the architecture strings.
targets_built=${targets_built##*: }
# Sort CPU strings to make the next step a simple string compare.
local actual=$(echo ${targets_built} | tr " " "\n" | sort | tr "\n" " ")
local requested=$(echo ${requested_cpus} | tr " " "\n" | sort | tr "\n" " ")
vlog "Requested ${FRAMEWORK_LIB} CPUs: ${requested}"
vlog "Actual ${FRAMEWORK_LIB} CPUs: ${actual}"
if [ "${requested}" != "${actual}" ]; then
elog "Actual ${FRAMEWORK_LIB} targets do not match requested target list."
elog " Requested target CPUs: ${requested}"
elog " Actual target CPUs: ${actual}"
return 1
fi
}
# Configures and builds each target specified by $1, and then builds
# VPX.framework.
build_framework() {
local lib_list=""
local targets="$1"
local target=""
local target_dist_dir=""
# Clean up from previous build(s).
rm -rf "${BUILD_ROOT}" "${FRAMEWORK_DIR}"
# Create output dirs.
mkdir -p "${BUILD_ROOT}"
mkdir -p "${HEADER_DIR}"
cd "${BUILD_ROOT}"
for target in ${targets}; do
build_target "${target}"
target_dist_dir="${BUILD_ROOT}/${target}/${DIST_DIR}"
if [ "${ENABLE_SHARED}" = "yes" ]; then
local suffix="dylib"
else
local suffix="a"
fi
lib_list="${lib_list} ${target_dist_dir}/lib/libvpx.${suffix}"
done
cd "${ORIG_PWD}"
# The basic libvpx API includes are all the same; just grab the most recent
# set.
cp -p "${target_dist_dir}"/include/vpx/* "${HEADER_DIR}"
# Build the fat library.
${LIPO} -create ${lib_list} -output ${FRAMEWORK_DIR}/VPX
# Create the vpx_config.h shim that allows usage of vpx_config.h from
# within VPX.framework.
create_vpx_framework_config_shim "${targets}"
# Copy in vpx_version.h.
cp -p "${BUILD_ROOT}/${target}/vpx_version.h" "${HEADER_DIR}"
if [ "${ENABLE_SHARED}" = "yes" ]; then
# Adjust the dylib's name so dynamic linking in apps works as expected.
install_name_tool -id '@rpath/VPX.framework/VPX' ${FRAMEWORK_DIR}/VPX
# Copy in Info.plist.
cat "${SCRIPT_DIR}/ios-Info.plist" \
| sed "s/\${FULLVERSION}/${FULLVERSION}/g" \
| sed "s/\${VERSION}/${VERSION}/g" \
| sed "s/\${IOS_VERSION_MIN}/${IOS_VERSION_MIN}/g" \
> "${FRAMEWORK_DIR}/Info.plist"
fi
# Confirm VPX.framework/VPX contains the targets requested.
verify_framework_targets ${targets}
vlog "Created fat library ${FRAMEWORK_LIB} containing:"
for lib in ${lib_list}; do
vlog " $(echo ${lib} | awk -F / '{print $2, $NF}')"
done
}
# Trap function. Cleans up the subtree used to build all targets contained in
# $TARGETS.
cleanup() {
local readonly res=$?
cd "${ORIG_PWD}"
if [ $res -ne 0 ]; then
elog "build exited with error ($res)"
fi
if [ "${PRESERVE_BUILD_OUTPUT}" != "yes" ]; then
rm -rf "${BUILD_ROOT}"
fi
}
print_list() {
local indent="$1"
shift
local list="$@"
for entry in ${list}; do
echo "${indent}${entry}"
done
}
iosbuild_usage() {
cat << EOF
Usage: ${0##*/} [arguments]
--help: Display this message and exit.
--enable-shared: Build a dynamic framework for use on iOS 8 or later.
--extra-configure-args <args>: Extra args to pass when configuring libvpx.
--macosx: Uses darwin16 targets instead of iphonesimulator targets for x86
and x86_64. Allows linking to framework when builds target MacOSX
instead of iOS.
--preserve-build-output: Do not delete the build directory.
--show-build-output: Show output from each library build.
--targets <targets>: Override default target list. Defaults:
$(print_list " " ${TARGETS})
--test-link: Confirms all targets can be linked. Functionally identical to
passing --enable-examples via --extra-configure-args.
--verbose: Output information about the environment and each stage of the
build.
EOF
}
elog() {
echo "${0##*/} failed because: $@" 1>&2
}
vlog() {
if [ "${VERBOSE}" = "yes" ]; then
echo "$@"
fi
}
trap cleanup EXIT
# Parse the command line.
while [ -n "$1" ]; do
case "$1" in
--extra-configure-args)
EXTRA_CONFIGURE_ARGS="$2"
shift
;;
--help)
iosbuild_usage
exit
;;
--enable-shared)
ENABLE_SHARED=yes
;;
--preserve-build-output)
PRESERVE_BUILD_OUTPUT=yes
;;
--show-build-output)
devnull=
;;
--test-link)
EXTRA_CONFIGURE_ARGS="${EXTRA_CONFIGURE_ARGS} --enable-examples"
;;
--targets)
TARGETS="$2"
shift
;;
--macosx)
TARGETS="${ARM_TARGETS} ${OSX_TARGETS}"
;;
--verbose)
VERBOSE=yes
;;
*)
iosbuild_usage
exit 1
;;
esac
shift
done
if [ "${ENABLE_SHARED}" = "yes" ]; then
CONFIGURE_ARGS="--enable-shared ${CONFIGURE_ARGS}"
fi
FULLVERSION=$("${SCRIPT_DIR}"/version.sh --bare "${LIBVPX_SOURCE_DIR}")
VERSION=$(echo "${FULLVERSION}" | sed -E 's/^v([0-9]+\.[0-9]+\.[0-9]+).*$/\1/')
if [ "$ENABLE_SHARED" = "yes" ]; then
IOS_VERSION_OPTIONS="--enable-shared"
IOS_VERSION_MIN="8.0"
else
IOS_VERSION_OPTIONS=""
IOS_VERSION_MIN="6.0"
fi
if [ "${VERBOSE}" = "yes" ]; then
cat << EOF
BUILD_ROOT=${BUILD_ROOT}
DIST_DIR=${DIST_DIR}
CONFIGURE_ARGS=${CONFIGURE_ARGS}
EXTRA_CONFIGURE_ARGS=${EXTRA_CONFIGURE_ARGS}
FRAMEWORK_DIR=${FRAMEWORK_DIR}
FRAMEWORK_LIB=${FRAMEWORK_LIB}
HEADER_DIR=${HEADER_DIR}
LIBVPX_SOURCE_DIR=${LIBVPX_SOURCE_DIR}
LIPO=${LIPO}
MAKEFLAGS=${MAKEFLAGS}
ORIG_PWD=${ORIG_PWD}
PRESERVE_BUILD_OUTPUT=${PRESERVE_BUILD_OUTPUT}
TARGETS="$(print_list "" ${TARGETS})"
ENABLE_SHARED=${ENABLE_SHARED}
OSX_TARGETS="${OSX_TARGETS}"
SIM_TARGETS="${SIM_TARGETS}"
SCRIPT_DIR="${SCRIPT_DIR}"
FULLVERSION="${FULLVERSION}"
VERSION="${VERSION}"
IOS_VERSION_MIN="${IOS_VERSION_MIN}"
EOF
fi
build_framework "${TARGETS}"
echo "Successfully built '${FRAMEWORK_DIR}' for:"
print_list "" ${TARGETS}

View File

@ -1,123 +0,0 @@
#!/bin/bash
##
## Copyright (c) 2014 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
if [ "$(uname -o 2>/dev/null)" = "Cygwin" ] \
&& cygpath --help >/dev/null 2>&1; then
FIXPATH='cygpath -m'
else
FIXPATH='echo_path'
fi
die() {
echo "${self_basename}: $@" >&2
exit 1
}
die_unknown(){
echo "Unknown option \"$1\"." >&2
echo "See ${self_basename} --help for available options." >&2
exit 1
}
echo_path() {
for path; do
echo "$path"
done
}
# Output one, possibly changed based on the system, path per line.
fix_path() {
$FIXPATH "$@"
}
# Corrects the paths in file_list in one pass for efficiency.
# $1 is the name of the array to be modified.
fix_file_list() {
if [ "${FIXPATH}" = "echo_path" ] ; then
# When used with echo_path, fix_file_list is a no-op. Avoid warning about
# unsupported 'declare -n' when it is not important.
return 0
elif [ "${BASH_VERSINFO}" -lt 4 ] ; then
echo "Cygwin path conversion has failed. Please use a version of bash"
echo "which supports nameref (-n), introduced in bash 4.3"
return 1
fi
declare -n array_ref=$1
files=$(fix_path "${array_ref[@]}")
local IFS=$'\n'
array_ref=($files)
}
generate_uuid() {
local hex="0123456789ABCDEF"
local i
local uuid=""
local j
#93995380-89BD-4b04-88EB-625FBE52EBFB
for ((i=0; i<32; i++)); do
(( j = $RANDOM % 16 ))
uuid="${uuid}${hex:$j:1}"
done
echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
}
indent1=" "
indent=""
indent_push() {
indent="${indent}${indent1}"
}
indent_pop() {
indent="${indent%${indent1}}"
}
tag_attributes() {
for opt in "$@"; do
optval="${opt#*=}"
[ -n "${optval}" ] ||
die "Missing attribute value in '$opt' while generating $tag tag"
echo "${indent}${opt%%=*}=\"${optval}\""
done
}
open_tag() {
local tag=$1
shift
if [ $# -ne 0 ]; then
echo "${indent}<${tag}"
indent_push
tag_attributes "$@"
echo "${indent}>"
else
echo "${indent}<${tag}>"
indent_push
fi
}
close_tag() {
local tag=$1
indent_pop
echo "${indent}</${tag}>"
}
tag() {
local tag=$1
shift
if [ $# -ne 0 ]; then
echo "${indent}<${tag}"
indent_push
tag_attributes "$@"
indent_pop
echo "${indent}/>"
else
echo "${indent}<${tag}/>"
fi
}

View File

@ -0,0 +1,914 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vpx_config.h"
#include "vpx/vpx_integer.h"
typedef enum
{
OUTPUT_FMT_PLAIN,
OUTPUT_FMT_RVDS,
OUTPUT_FMT_GAS,
} output_fmt_t;
int log_msg(const char *fmt, ...)
{
int res;
va_list ap;
va_start(ap, fmt);
res = vfprintf(stderr, fmt, ap);
va_end(ap);
return res;
}
#if defined(__GNUC__) && __GNUC__
#if defined(__MACH__)
#include <mach-o/loader.h>
#include <mach-o/nlist.h>
int parse_macho(uint8_t *base_buf, size_t sz)
{
int i, j;
struct mach_header header;
uint8_t *buf = base_buf;
int base_data_section = 0;
int bits = 0;
/* We can read in mach_header for 32 and 64 bit architectures
* because it's identical to mach_header_64 except for the last
* element (uint32_t reserved), which we don't use. Then, when
* we know which architecture we're looking at, increment buf
* appropriately.
*/
memcpy(&header, buf, sizeof(struct mach_header));
if (header.magic == MH_MAGIC)
{
if (header.cputype == CPU_TYPE_ARM
|| header.cputype == CPU_TYPE_X86)
{
bits = 32;
buf += sizeof(struct mach_header);
}
else
{
log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_[ARM|X86].\n");
goto bail;
}
}
else if (header.magic == MH_MAGIC_64)
{
if (header.cputype == CPU_TYPE_X86_64)
{
bits = 64;
buf += sizeof(struct mach_header_64);
}
else
{
log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_X86_64.\n");
goto bail;
}
}
else
{
log_msg("Bad magic number for object file. 0x%x or 0x%x expected, 0x%x found.\n",
MH_MAGIC, MH_MAGIC_64, header.magic);
goto bail;
}
if (header.filetype != MH_OBJECT)
{
log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
goto bail;
}
for (i = 0; i < header.ncmds; i++)
{
struct load_command lc;
memcpy(&lc, buf, sizeof(struct load_command));
if (lc.cmd == LC_SEGMENT)
{
uint8_t *seg_buf = buf;
struct section s;
struct segment_command seg_c;
memcpy(&seg_c, seg_buf, sizeof(struct segment_command));
seg_buf += sizeof(struct segment_command);
/* Although each section is given it's own offset, nlist.n_value
* references the offset of the first section. This isn't
* apparent without debug information because the offset of the
* data section is the same as the first section. However, with
* debug sections mixed in, the offset of the debug section
* increases but n_value still references the first section.
*/
if (seg_c.nsects < 1)
{
log_msg("Not enough sections\n");
goto bail;
}
memcpy(&s, seg_buf, sizeof(struct section));
base_data_section = s.offset;
}
else if (lc.cmd == LC_SEGMENT_64)
{
uint8_t *seg_buf = buf;
struct section_64 s;
struct segment_command_64 seg_c;
memcpy(&seg_c, seg_buf, sizeof(struct segment_command_64));
seg_buf += sizeof(struct segment_command_64);
/* Explanation in LG_SEGMENT */
if (seg_c.nsects < 1)
{
log_msg("Not enough sections\n");
goto bail;
}
memcpy(&s, seg_buf, sizeof(struct section_64));
base_data_section = s.offset;
}
else if (lc.cmd == LC_SYMTAB)
{
if (base_data_section != 0)
{
struct symtab_command sc;
uint8_t *sym_buf = base_buf;
uint8_t *str_buf = base_buf;
memcpy(&sc, buf, sizeof(struct symtab_command));
if (sc.cmdsize != sizeof(struct symtab_command))
{
log_msg("Can't find symbol table!\n");
goto bail;
}
sym_buf += sc.symoff;
str_buf += sc.stroff;
for (j = 0; j < sc.nsyms; j++)
{
/* Location of string is cacluated each time from the
* start of the string buffer. On darwin the symbols
* are prefixed by "_", so we bump the pointer by 1.
* The target value is defined as an int in asm_*_offsets.c,
* which is 4 bytes on all targets we currently use.
*/
if (bits == 32)
{
struct nlist nl;
int val;
memcpy(&nl, sym_buf, sizeof(struct nlist));
sym_buf += sizeof(struct nlist);
memcpy(&val, base_buf + base_data_section + nl.n_value,
sizeof(val));
printf("%-40s EQU %5d\n",
str_buf + nl.n_un.n_strx + 1, val);
}
else /* if (bits == 64) */
{
struct nlist_64 nl;
int val;
memcpy(&nl, sym_buf, sizeof(struct nlist_64));
sym_buf += sizeof(struct nlist_64);
memcpy(&val, base_buf + base_data_section + nl.n_value,
sizeof(val));
printf("%-40s EQU %5d\n",
str_buf + nl.n_un.n_strx + 1, val);
}
}
}
}
buf += lc.cmdsize;
}
return 0;
bail:
return 1;
}
#elif defined(__ELF__)
#include "elf.h"
#define COPY_STRUCT(dst, buf, ofst, sz) do {\
if(ofst + sizeof((*(dst))) > sz) goto bail;\
memcpy(dst, buf+ofst, sizeof((*(dst))));\
} while(0)
#define ENDIAN_ASSIGN(val, memb) do {\
if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
(val) = (memb);\
} while(0)
#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
ENDIAN_ASSIGN(memb, memb);\
} while(0)
typedef struct
{
uint8_t *buf; /* Buffer containing ELF data */
size_t sz; /* Buffer size */
int le_data; /* Data is little-endian */
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
int bits; /* 32 or 64 */
Elf32_Ehdr hdr32;
Elf64_Ehdr hdr64;
} elf_obj_t;
int parse_elf_header(elf_obj_t *elf)
{
int res;
/* Verify ELF Magic numbers */
COPY_STRUCT(&elf->e_ident, elf->buf, 0, elf->sz);
res = elf->e_ident[EI_MAG0] == ELFMAG0;
res &= elf->e_ident[EI_MAG1] == ELFMAG1;
res &= elf->e_ident[EI_MAG2] == ELFMAG2;
res &= elf->e_ident[EI_MAG3] == ELFMAG3;
res &= elf->e_ident[EI_CLASS] == ELFCLASS32
|| elf->e_ident[EI_CLASS] == ELFCLASS64;
res &= elf->e_ident[EI_DATA] == ELFDATA2LSB;
if (!res) goto bail;
elf->le_data = elf->e_ident[EI_DATA] == ELFDATA2LSB;
/* Read in relevant values */
if (elf->e_ident[EI_CLASS] == ELFCLASS32)
{
elf->bits = 32;
COPY_STRUCT(&elf->hdr32, elf->buf, 0, elf->sz);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_type);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_machine);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_version);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_entry);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phoff);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shoff);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_flags);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_ehsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phentsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_phnum);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shentsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shnum);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr32.e_shstrndx);
}
else /* if (elf->e_ident[EI_CLASS] == ELFCLASS64) */
{
elf->bits = 64;
COPY_STRUCT(&elf->hdr64, elf->buf, 0, elf->sz);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_type);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_machine);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_version);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_entry);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phoff);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shoff);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_flags);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_ehsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phentsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_phnum);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shentsize);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shnum);
ENDIAN_ASSIGN_IN_PLACE(elf->hdr64.e_shstrndx);
}
return 0;
bail:
log_msg("Failed to parse ELF file header");
return 1;
}
int parse_elf_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr32, Elf64_Shdr *hdr64)
{
if (hdr32)
{
if (idx >= elf->hdr32.e_shnum)
goto bail;
COPY_STRUCT(hdr32, elf->buf, elf->hdr32.e_shoff + idx * elf->hdr32.e_shentsize,
elf->sz);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_name);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_type);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_flags);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addr);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_offset);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_size);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_link);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_info);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_addralign);
ENDIAN_ASSIGN_IN_PLACE(hdr32->sh_entsize);
}
else /* if (hdr64) */
{
if (idx >= elf->hdr64.e_shnum)
goto bail;
COPY_STRUCT(hdr64, elf->buf, elf->hdr64.e_shoff + idx * elf->hdr64.e_shentsize,
elf->sz);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_name);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_type);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_flags);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addr);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_offset);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_size);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_link);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_info);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_addralign);
ENDIAN_ASSIGN_IN_PLACE(hdr64->sh_entsize);
}
return 0;
bail:
return 1;
}
char *parse_elf_string_table(elf_obj_t *elf, int s_idx, int idx)
{
if (elf->bits == 32)
{
Elf32_Shdr shdr;
if (parse_elf_section(elf, s_idx, &shdr, NULL))
{
log_msg("Failed to parse ELF string table: section %d, index %d\n",
s_idx, idx);
return "";
}
return (char *)(elf->buf + shdr.sh_offset + idx);
}
else /* if (elf->bits == 64) */
{
Elf64_Shdr shdr;
if (parse_elf_section(elf, s_idx, NULL, &shdr))
{
log_msg("Failed to parse ELF string table: section %d, index %d\n",
s_idx, idx);
return "";
}
return (char *)(elf->buf + shdr.sh_offset + idx);
}
}
int parse_elf_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym32, Elf64_Sym *sym64)
{
if (sym32)
{
COPY_STRUCT(sym32, elf->buf, ofst, elf->sz);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_name);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_value);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_size);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_info);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_other);
ENDIAN_ASSIGN_IN_PLACE(sym32->st_shndx);
}
else /* if (sym64) */
{
COPY_STRUCT(sym64, elf->buf, ofst, elf->sz);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_name);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_value);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_size);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_info);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_other);
ENDIAN_ASSIGN_IN_PLACE(sym64->st_shndx);
}
return 0;
bail:
return 1;
}
int parse_elf(uint8_t *buf, size_t sz, output_fmt_t mode)
{
elf_obj_t elf;
unsigned int ofst;
int i;
Elf32_Off strtab_off32;
Elf64_Off strtab_off64; /* save String Table offset for later use */
memset(&elf, 0, sizeof(elf));
elf.buf = buf;
elf.sz = sz;
/* Parse Header */
if (parse_elf_header(&elf))
goto bail;
if (elf.bits == 32)
{
Elf32_Shdr shdr;
for (i = 0; i < elf.hdr32.e_shnum; i++)
{
parse_elf_section(&elf, i, &shdr, NULL);
if (shdr.sh_type == SHT_STRTAB)
{
char strtsb_name[128];
strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
if (!(strcmp(strtsb_name, ".shstrtab")))
{
/* log_msg("found section: %s\n", strtsb_name); */
strtab_off32 = shdr.sh_offset;
break;
}
}
}
}
else /* if (elf.bits == 64) */
{
Elf64_Shdr shdr;
for (i = 0; i < elf.hdr64.e_shnum; i++)
{
parse_elf_section(&elf, i, NULL, &shdr);
if (shdr.sh_type == SHT_STRTAB)
{
char strtsb_name[128];
strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
if (!(strcmp(strtsb_name, ".shstrtab")))
{
/* log_msg("found section: %s\n", strtsb_name); */
strtab_off64 = shdr.sh_offset;
break;
}
}
}
}
/* Parse all Symbol Tables */
if (elf.bits == 32)
{
Elf32_Shdr shdr;
for (i = 0; i < elf.hdr32.e_shnum; i++)
{
parse_elf_section(&elf, i, &shdr, NULL);
if (shdr.sh_type == SHT_SYMTAB)
{
for (ofst = shdr.sh_offset;
ofst < shdr.sh_offset + shdr.sh_size;
ofst += shdr.sh_entsize)
{
Elf32_Sym sym;
parse_elf_symbol(&elf, ofst, &sym, NULL);
/* For all OBJECTS (data objects), extract the value from the
* proper data segment.
*/
/* if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
log_msg("found data object %s\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name));
*/
if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
&& sym.st_size == 4)
{
Elf32_Shdr dhdr;
int val = 0;
char section_name[128];
parse_elf_section(&elf, sym.st_shndx, &dhdr, NULL);
/* For explanition - refer to _MSC_VER version of code */
strcpy(section_name, (char *)(elf.buf + strtab_off32 + dhdr.sh_name));
/* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
if (strcmp(section_name, ".bss"))
{
if (sizeof(val) != sym.st_size)
{
/* The target value is declared as an int in
* asm_*_offsets.c, which is 4 bytes on all
* targets we currently use. Complain loudly if
* this is not true.
*/
log_msg("Symbol size is wrong\n");
goto bail;
}
memcpy(&val,
elf.buf + dhdr.sh_offset + sym.st_value,
sym.st_size);
}
if (!elf.le_data)
{
log_msg("Big Endian data not supported yet!\n");
goto bail;
}
switch (mode)
{
case OUTPUT_FMT_RVDS:
printf("%-40s EQU %5d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
break;
case OUTPUT_FMT_GAS:
printf(".equ %-40s, %5d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
break;
default:
printf("%s = %d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
}
}
}
}
}
}
else /* if (elf.bits == 64) */
{
Elf64_Shdr shdr;
for (i = 0; i < elf.hdr64.e_shnum; i++)
{
parse_elf_section(&elf, i, NULL, &shdr);
if (shdr.sh_type == SHT_SYMTAB)
{
for (ofst = shdr.sh_offset;
ofst < shdr.sh_offset + shdr.sh_size;
ofst += shdr.sh_entsize)
{
Elf64_Sym sym;
parse_elf_symbol(&elf, ofst, NULL, &sym);
/* For all OBJECTS (data objects), extract the value from the
* proper data segment.
*/
/* if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
log_msg("found data object %s\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name));
*/
if (ELF64_ST_TYPE(sym.st_info) == STT_OBJECT
&& sym.st_size == 4)
{
Elf64_Shdr dhdr;
int val = 0;
char section_name[128];
parse_elf_section(&elf, sym.st_shndx, NULL, &dhdr);
/* For explanition - refer to _MSC_VER version of code */
strcpy(section_name, (char *)(elf.buf + strtab_off64 + dhdr.sh_name));
/* log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type); */
if ((strcmp(section_name, ".bss")))
{
if (sizeof(val) != sym.st_size)
{
/* The target value is declared as an int in
* asm_*_offsets.c, which is 4 bytes on all
* targets we currently use. Complain loudly if
* this is not true.
*/
log_msg("Symbol size is wrong\n");
goto bail;
}
memcpy(&val,
elf.buf + dhdr.sh_offset + sym.st_value,
sym.st_size);
}
if (!elf.le_data)
{
log_msg("Big Endian data not supported yet!\n");
goto bail;
}
switch (mode)
{
case OUTPUT_FMT_RVDS:
printf("%-40s EQU %5d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
break;
case OUTPUT_FMT_GAS:
printf(".equ %-40s, %5d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
break;
default:
printf("%s = %d\n",
parse_elf_string_table(&elf,
shdr.sh_link,
sym.st_name),
val);
}
}
}
}
}
}
if (mode == OUTPUT_FMT_RVDS)
printf(" END\n");
return 0;
bail:
log_msg("Parse error: File does not appear to be valid ELF32 or ELF64\n");
return 1;
}
#endif
#endif /* defined(__GNUC__) && __GNUC__ */
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
/* See "Microsoft Portable Executable and Common Object File Format Specification"
for reference.
*/
#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
#define get_le16(x) ((*(x)) | (*(x+1)) << 8)
int parse_coff(uint8_t *buf, size_t sz)
{
unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
unsigned int sectionrawdata_ptr;
unsigned int i;
uint8_t *ptr;
uint32_t symoffset;
char **sectionlist; //this array holds all section names in their correct order.
//it is used to check if the symbol is in .bss or .data section.
nsections = get_le16(buf + 2);
symtab_ptr = get_le32(buf + 8);
symtab_sz = get_le32(buf + 12);
strtab_ptr = symtab_ptr + symtab_sz * 18;
if (nsections > 96)
{
log_msg("Too many sections\n");
return 1;
}
sectionlist = malloc(nsections * sizeof(sectionlist));
if (sectionlist == NULL)
{
log_msg("Allocating first level of section list failed\n");
return 1;
}
//log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
/*
The size of optional header is always zero for an obj file. So, the section header
follows the file header immediately.
*/
ptr = buf + 20; //section header
for (i = 0; i < nsections; i++)
{
char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
strncpy(sectionname, ptr, 8);
//log_msg("COFF: Parsing section %s\n",sectionname);
sectionlist[i] = malloc(strlen(sectionname) + 1);
if (sectionlist[i] == NULL)
{
log_msg("Allocating storage for %s failed\n", sectionname);
goto bail;
}
strcpy(sectionlist[i], sectionname);
if (!strcmp(sectionname, ".data")) sectionrawdata_ptr = get_le32(ptr + 20);
ptr += 40;
}
//log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
//log_msg("COFF: raw data pointer ofset for section .data is %u\n", sectionrawdata_ptr);
/* The compiler puts the data with non-zero offset in .data section, but puts the data with
zero offset in .bss section. So, if the data in in .bss section, set offset=0.
Note from Wiki: In an object module compiled from C, the bss section contains
the local variables (but not functions) that were declared with the static keyword,
except for those with non-zero initial values. (In C, static variables are initialized
to zero by default.) It also contains the non-local (both extern and static) variables
that are also initialized to zero (either explicitly or by default).
*/
//move to symbol table
/* COFF symbol table:
offset field
0 Name(*)
8 Value
12 SectionNumber
14 Type
16 StorageClass
17 NumberOfAuxSymbols
*/
ptr = buf + symtab_ptr;
for (i = 0; i < symtab_sz; i++)
{
int16_t section = get_le16(ptr + 12); //section number
if (section > 0 && ptr[16] == 2)
{
//if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
if (get_le32(ptr))
{
char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
strncpy(name, ptr, 8);
//log_msg("COFF: Parsing symbol %s\n",name);
/* The 64bit Windows compiler doesn't prefix with an _.
* Check what's there, and bump if necessary
*/
if (name[0] == '_')
printf("%-40s EQU ", name + 1);
else
printf("%-40s EQU ", name);
}
else
{
//log_msg("COFF: Parsing symbol %s\n",
// buf + strtab_ptr + get_le32(ptr+4));
if ((buf + strtab_ptr + get_le32(ptr + 4))[0] == '_')
printf("%-40s EQU ",
buf + strtab_ptr + get_le32(ptr + 4) + 1);
else
printf("%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
}
if (!(strcmp(sectionlist[section-1], ".bss")))
{
symoffset = 0;
}
else
{
symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
}
//log_msg(" Section: %d\n",section);
//log_msg(" Class: %d\n",ptr[16]);
//log_msg(" Address: %u\n",get_le32(ptr+8));
//log_msg(" Offset: %u\n", symoffset);
printf("%5d\n", symoffset);
}
ptr += 18;
}
printf(" END\n");
for (i = 0; i < nsections; i++)
{
free(sectionlist[i]);
}
free(sectionlist);
return 0;
bail:
for (i = 0; i < nsections; i++)
{
free(sectionlist[i]);
}
free(sectionlist);
return 1;
}
#endif /* defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) */
int main(int argc, char **argv)
{
output_fmt_t mode = OUTPUT_FMT_PLAIN;
const char *f;
uint8_t *file_buf;
int res;
FILE *fp;
long int file_size;
if (argc < 2 || argc > 3)
{
fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
fprintf(stderr, " <obj file>\tobject file to parse\n");
fprintf(stderr, "Output Formats:\n");
fprintf(stderr, " gas - compatible with GNU assembler\n");
fprintf(stderr, " rvds - compatible with armasm\n");
goto bail;
}
f = argv[2];
if (!strcmp(argv[1], "rvds"))
mode = OUTPUT_FMT_RVDS;
else if (!strcmp(argv[1], "gas"))
mode = OUTPUT_FMT_GAS;
else
f = argv[1];
fp = fopen(f, "rb");
if (!fp)
{
perror("Unable to open file");
goto bail;
}
if (fseek(fp, 0, SEEK_END))
{
perror("stat");
goto bail;
}
file_size = ftell(fp);
file_buf = malloc(file_size);
if (!file_buf)
{
perror("malloc");
goto bail;
}
rewind(fp);
if (fread(file_buf, sizeof(char), file_size, fp) != file_size)
{
perror("read");
goto bail;
}
if (fclose(fp))
{
perror("close");
goto bail;
}
#if defined(__GNUC__) && __GNUC__
#if defined(__MACH__)
res = parse_macho(file_buf, file_size);
#elif defined(__ELF__)
res = parse_elf(file_buf, file_size, mode);
#endif
#endif
#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__)
res = parse_coff(file_buf, file_size);
#endif
free(file_buf);
if (!res)
return EXIT_SUCCESS;
bail:
return EXIT_FAILURE;
}

View File

@ -1,468 +0,0 @@
#!/usr/bin/env perl
##
## Copyright (c) 2017 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
no strict 'refs';
use warnings;
use Getopt::Long;
Getopt::Long::Configure("auto_help") if $Getopt::Long::VERSION > 2.32;
my %ALL_FUNCS = ();
my @ALL_ARCHS;
my @ALL_FORWARD_DECLS;
my @REQUIRES;
my %opts = ();
my %disabled = ();
my %required = ();
my @argv;
foreach (@ARGV) {
$disabled{$1} = 1, next if /--disable-(.*)/;
$required{$1} = 1, next if /--require-(.*)/;
push @argv, $_;
}
# NB: use GetOptions() instead of GetOptionsFromArray() for compatibility.
@ARGV = @argv;
GetOptions(
\%opts,
'arch=s',
'sym=s',
'config=s',
);
foreach my $opt (qw/arch config/) {
if (!defined($opts{$opt})) {
warn "--$opt is required!\n";
Getopt::Long::HelpMessage('-exit' => 1);
}
}
foreach my $defs_file (@ARGV) {
if (!-f $defs_file) {
warn "$defs_file: $!\n";
Getopt::Long::HelpMessage('-exit' => 1);
}
}
open CONFIG_FILE, $opts{config} or
die "Error opening config file '$opts{config}': $!\n";
my %config = ();
while (<CONFIG_FILE>) {
next if !/^(?:CONFIG_|HAVE_)/;
chomp;
my @pair = split /=/;
$config{$pair[0]} = $pair[1];
}
close CONFIG_FILE;
#
# Routines for the RTCD DSL to call
#
sub vpx_config($) {
return (defined $config{$_[0]}) ? $config{$_[0]} : "";
}
sub specialize {
my $fn=$_[0];
shift;
foreach my $opt (@_) {
eval "\$${fn}_${opt}=${fn}_${opt}";
}
}
sub add_proto {
my $fn = splice(@_, -2, 1);
$ALL_FUNCS{$fn} = \@_;
specialize $fn, "c";
}
sub require {
foreach my $fn (keys %ALL_FUNCS) {
foreach my $opt (@_) {
my $ofn = eval "\$${fn}_${opt}";
next if !$ofn;
# if we already have a default, then we can disable it, as we know
# we can do better.
my $best = eval "\$${fn}_default";
if ($best) {
my $best_ofn = eval "\$${best}";
if ($best_ofn && "$best_ofn" ne "$ofn") {
eval "\$${best}_link = 'false'";
}
}
eval "\$${fn}_default=${fn}_${opt}";
eval "\$${fn}_${opt}_link='true'";
}
}
}
sub forward_decls {
push @ALL_FORWARD_DECLS, @_;
}
#
# Include the user's directives
#
foreach my $f (@ARGV) {
open FILE, "<", $f or die "cannot open $f: $!\n";
my $contents = join('', <FILE>);
close FILE;
eval $contents or warn "eval failed: $@\n";
}
#
# Process the directives according to the command line
#
sub process_forward_decls() {
foreach (@ALL_FORWARD_DECLS) {
$_->();
}
}
sub determine_indirection {
vpx_config("CONFIG_RUNTIME_CPU_DETECT") eq "yes" or &require(@ALL_ARCHS);
foreach my $fn (keys %ALL_FUNCS) {
my $n = "";
my @val = @{$ALL_FUNCS{$fn}};
my $args = pop @val;
my $rtyp = "@val";
my $dfn = eval "\$${fn}_default";
$dfn = eval "\$${dfn}";
foreach my $opt (@_) {
my $ofn = eval "\$${fn}_${opt}";
next if !$ofn;
my $link = eval "\$${fn}_${opt}_link";
next if $link && $link eq "false";
$n .= "x";
}
if ($n eq "x") {
eval "\$${fn}_indirect = 'false'";
} else {
eval "\$${fn}_indirect = 'true'";
}
}
}
sub declare_function_pointers {
foreach my $fn (sort keys %ALL_FUNCS) {
my @val = @{$ALL_FUNCS{$fn}};
my $args = pop @val;
my $rtyp = "@val";
my $dfn = eval "\$${fn}_default";
$dfn = eval "\$${dfn}";
foreach my $opt (@_) {
my $ofn = eval "\$${fn}_${opt}";
next if !$ofn;
print "$rtyp ${ofn}($args);\n";
}
if (eval "\$${fn}_indirect" eq "false") {
print "#define ${fn} ${dfn}\n";
} else {
print "RTCD_EXTERN $rtyp (*${fn})($args);\n";
}
print "\n";
}
}
sub set_function_pointers {
foreach my $fn (sort keys %ALL_FUNCS) {
my @val = @{$ALL_FUNCS{$fn}};
my $args = pop @val;
my $rtyp = "@val";
my $dfn = eval "\$${fn}_default";
$dfn = eval "\$${dfn}";
if (eval "\$${fn}_indirect" eq "true") {
print " $fn = $dfn;\n";
foreach my $opt (@_) {
my $ofn = eval "\$${fn}_${opt}";
next if !$ofn;
next if "$ofn" eq "$dfn";
my $link = eval "\$${fn}_${opt}_link";
next if $link && $link eq "false";
my $cond = eval "\$have_${opt}";
print " if (${cond}) $fn = $ofn;\n"
}
}
}
}
sub filter {
my @filtered;
foreach (@_) { push @filtered, $_ unless $disabled{$_}; }
return @filtered;
}
#
# Helper functions for generating the arch specific RTCD files
#
sub common_top() {
my $include_guard = uc($opts{sym})."_H_";
print <<EOF;
// This file is generated. Do not edit.
#ifndef ${include_guard}
#define ${include_guard}
#ifdef RTCD_C
#define RTCD_EXTERN
#else
#define RTCD_EXTERN extern
#endif
EOF
process_forward_decls();
print <<EOF;
#ifdef __cplusplus
extern "C" {
#endif
EOF
declare_function_pointers("c", @ALL_ARCHS);
print <<EOF;
void $opts{sym}(void);
EOF
}
sub common_bottom() {
print <<EOF;
#ifdef __cplusplus
} // extern "C"
#endif
#endif
EOF
}
sub x86() {
determine_indirection("c", @ALL_ARCHS);
# Assign the helper variable for each enabled extension
foreach my $opt (@ALL_ARCHS) {
my $opt_uc = uc $opt;
eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
}
common_top;
print <<EOF;
#ifdef RTCD_C
#include "vpx_ports/x86.h"
static void setup_rtcd_internal(void)
{
int flags = x86_simd_caps();
(void)flags;
EOF
set_function_pointers("c", @ALL_ARCHS);
print <<EOF;
}
#endif
EOF
common_bottom;
}
sub arm() {
determine_indirection("c", @ALL_ARCHS);
# Assign the helper variable for each enabled extension
foreach my $opt (@ALL_ARCHS) {
my $opt_uc = uc $opt;
# Enable neon assembly based on HAVE_NEON logic instead of adding new
# HAVE_NEON_ASM logic
if ($opt eq 'neon_asm') { $opt_uc = 'NEON' }
eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
}
common_top;
print <<EOF;
#include "vpx_config.h"
#ifdef RTCD_C
#include "vpx_ports/arm.h"
static void setup_rtcd_internal(void)
{
int flags = arm_cpu_caps();
(void)flags;
EOF
set_function_pointers("c", @ALL_ARCHS);
print <<EOF;
}
#endif
EOF
common_bottom;
}
sub mips() {
determine_indirection("c", @ALL_ARCHS);
common_top;
print <<EOF;
#include "vpx_config.h"
#ifdef RTCD_C
static void setup_rtcd_internal(void)
{
EOF
set_function_pointers("c", @ALL_ARCHS);
print <<EOF;
#if HAVE_DSPR2
void vpx_dsputil_static_init();
#if CONFIG_VP8
void dsputil_static_init();
#endif
vpx_dsputil_static_init();
#if CONFIG_VP8
dsputil_static_init();
#endif
#endif
}
#endif
EOF
common_bottom;
}
sub ppc() {
determine_indirection("c", @ALL_ARCHS);
# Assign the helper variable for each enabled extension
foreach my $opt (@ALL_ARCHS) {
my $opt_uc = uc $opt;
eval "\$have_${opt}=\"flags & HAS_${opt_uc}\"";
}
common_top;
print <<EOF;
#include "vpx_config.h"
#ifdef RTCD_C
#include "vpx_ports/ppc.h"
static void setup_rtcd_internal(void)
{
int flags = ppc_simd_caps();
(void)flags;
EOF
set_function_pointers("c", @ALL_ARCHS);
print <<EOF;
}
#endif
EOF
common_bottom;
}
sub unoptimized() {
determine_indirection "c";
common_top;
print <<EOF;
#include "vpx_config.h"
#ifdef RTCD_C
static void setup_rtcd_internal(void)
{
EOF
set_function_pointers "c";
print <<EOF;
}
#endif
EOF
common_bottom;
}
#
# Main Driver
#
&require("c");
if ($opts{arch} eq 'x86') {
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
x86;
} elsif ($opts{arch} eq 'x86_64') {
@ALL_ARCHS = filter(qw/mmx sse sse2 sse3 ssse3 sse4_1 avx avx2 avx512/);
@REQUIRES = filter(keys %required ? keys %required : qw/mmx sse sse2/);
&require(@REQUIRES);
x86;
} elsif ($opts{arch} eq 'mips32' || $opts{arch} eq 'mips64') {
@ALL_ARCHS = filter("$opts{arch}");
open CONFIG_FILE, $opts{config} or
die "Error opening config file '$opts{config}': $!\n";
while (<CONFIG_FILE>) {
if (/HAVE_DSPR2=yes/) {
@ALL_ARCHS = filter("$opts{arch}", qw/dspr2/);
last;
}
if (/HAVE_MSA=yes/) {
@ALL_ARCHS = filter("$opts{arch}", qw/msa/);
last;
}
if (/HAVE_MMI=yes/) {
@ALL_ARCHS = filter("$opts{arch}", qw/mmi/);
last;
}
}
close CONFIG_FILE;
mips;
} elsif ($opts{arch} =~ /armv7\w?/) {
@ALL_ARCHS = filter(qw/neon_asm neon/);
arm;
} elsif ($opts{arch} eq 'armv8' || $opts{arch} eq 'arm64' ) {
@ALL_ARCHS = filter(qw/neon/);
arm;
} elsif ($opts{arch} =~ /^ppc/ ) {
@ALL_ARCHS = filter(qw/vsx/);
ppc;
} else {
unoptimized;
}
__END__
=head1 NAME
rtcd -
=head1 SYNOPSIS
Usage: rtcd.pl [options] FILE
See 'perldoc rtcd.pl' for more details.
=head1 DESCRIPTION
Reads the Run Time CPU Detections definitions from FILE and generates a
C header file on stdout.
=head1 OPTIONS
Options:
--arch=ARCH Architecture to generate defs for (required)
--disable-EXT Disable support for EXT extensions
--require-EXT Require support for EXT extensions
--sym=SYMBOL Unique symbol to use for RTCD initialization function
--config=FILE File with CONFIG_FOO=yes lines to parse

View File

@ -1,63 +0,0 @@
#!/usr/bin/env perl
##
## Copyright (c) 2013 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
package thumb;
sub FixThumbInstructions($$)
{
my $short_branches = $_[1];
my $branch_shift_offset = $short_branches ? 1 : 0;
# Write additions with shifts, such as "add r10, r11, lsl #8",
# in three operand form, "add r10, r10, r11, lsl #8".
s/(add\s+)(r\d+),\s*(r\d+),\s*(lsl #\d+)/$1$2, $2, $3, $4/g;
# Convert additions with a non-constant shift into a sequence
# with left shift, addition and a right shift (to restore the
# register to the original value). Currently the right shift
# isn't necessary in the code base since the values in these
# registers aren't used, but doing the shift for consistency.
# This converts instructions such as "add r12, r12, r5, lsl r4"
# into the sequence "lsl r5, r4", "add r12, r12, r5", "lsr r5, r4".
s/^(\s*)(add)(\s+)(r\d+),\s*(r\d+),\s*(r\d+),\s*lsl (r\d+)/$1lsl$3$6, $7\n$1$2$3$4, $5, $6\n$1lsr$3$6, $7/g;
# Convert loads with right shifts in the indexing into a
# sequence of an add, load and sub. This converts
# "ldrb r4, [r9, lr, asr #1]" into "add r9, r9, lr, asr #1",
# "ldrb r9, [r9]", "sub r9, r9, lr, asr #1".
s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+),\s*(asr #\d+)\]/$1add $3$5, $5, $6, $7\n$1$2$3$4, [$5]\n$1sub $3$5, $5, $6, $7/g;
# Convert register indexing with writeback into a separate add
# instruction. This converts "ldrb r12, [r1, r2]!" into
# "ldrb r12, [r1, r2]", "add r1, r1, r2".
s/^(\s*)(ldrb)(\s+)(r\d+),\s*\[(\w+),\s*(\w+)\]!/$1$2$3$4, [$5, $6]\n$1add $3$5, $6/g;
# Convert negative register indexing into separate sub/add instructions.
# This converts "ldrne r4, [src, -pstep, lsl #1]" into
# "subne src, src, pstep, lsl #1", "ldrne r4, [src]",
# "addne src, src, pstep, lsl #1". In a couple of cases where
# this is used, it's used for two subsequent load instructions,
# where a hand-written version of it could merge two subsequent
# add and sub instructions.
s/^(\s*)((ldr|str|pld)(ne)?)(\s+)(r\d+,\s*)?\[(\w+), -([^\]]+)\]/$1sub$4$5$7, $7, $8\n$1$2$5$6\[$7\]\n$1add$4$5$7, $7, $8/g;
# Convert register post indexing to a separate add instruction.
# This converts "ldrneb r9, [r0], r2" into "ldrneb r9, [r0]",
# "addne r0, r0, r2".
s/^(\s*)((ldr|str)(ne)?[bhd]?)(\s+)(\w+),(\s*\w+,)?\s*\[(\w+)\],\s*(\w+)/$1$2$5$6,$7 [$8]\n$1add$4$5$8, $8, $9/g;
# Convert "mov pc, lr" into "bx lr", since the former only works
# for switching from arm to thumb (and only in armv7), but not
# from thumb to arm.
s/mov(\s*)pc\s*,\s*lr/bx$1lr/g;
}
1;

View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
@ -24,10 +24,9 @@ out_file=${2}
id=${3:-VERSION_STRING}
git_version_id=""
if [ -e "${source_path}/.git" ]; then
if [ -d ${source_path}/.git ]; then
# Source Path is a git working copy. Check for local modifications.
# Note that git submodules may have a file as .git, not a directory.
export GIT_DIR="${source_path}/.git"
export GIT_DIR=${source_path}/.git
git_version_id=`git describe --match=v[0-9]* 2>/dev/null`
fi
@ -60,7 +59,6 @@ if [ ${bare} ]; then
echo "${changelog_version}${git_version_id}" > $$.tmp
else
cat<<EOF>$$.tmp
// This file is generated. Do not edit.
#define VERSION_MAJOR $major_version
#define VERSION_MINOR $minor_version
#define VERSION_PATCH $patch_version

View File

@ -0,0 +1,15 @@
REM Copyright (c) 2011 The WebM project authors. All Rights Reserved.
REM
REM Use of this source code is governed by a BSD-style license
REM that can be found in the LICENSE file in the root of the source
REM tree. An additional intellectual property rights grant can be found
REM in the file PATENTS. All contributing project authors may
REM be found in the AUTHORS file in the root of the source tree.
echo on
cl /I "./" /I "%1" /nologo /c "%1/vp8/common/asm_com_offsets.c"
cl /I "./" /I "%1" /nologo /c "%1/vp8/decoder/asm_dec_offsets.c"
cl /I "./" /I "%1" /nologo /c "%1/vp8/encoder/asm_enc_offsets.c"
obj_int_extract.exe rvds "asm_com_offsets.obj" > "asm_com_offsets.asm"
obj_int_extract.exe rvds "asm_dec_offsets.obj" > "asm_dec_offsets.asm"
obj_int_extract.exe rvds "asm_enc_offsets.obj" > "asm_enc_offsets.asm"

115
build/x86-msvs/yasm.rules Normal file
View File

@ -0,0 +1,115 @@
<?xml version="1.0" encoding="utf-8"?>
<VisualStudioToolFile
Name="Yasm"
Version="8.00"
>
<Rules>
<CustomBuildRule
Name="YASM"
DisplayName="Yasm Assembler"
CommandLine="yasm -Xvc -f $(PlatformName) [AllOptions] [AdditionalOptions] [Inputs]"
Outputs="[$ObjectFileName]"
FileExtensions="*.asm"
ExecutionDescription="Assembling $(InputFileName)"
ShowOnlyRuleProperties="false"
>
<Properties>
<StringProperty
Name="Defines"
DisplayName="Definitions"
Category="Pre-Defined Symbols"
Description="Specify pre-defined symbols (&apos;symbol&apos; or &apos;symbol = value&apos;) "
Switch="-D [value]"
Delimited="true"
Inheritable="true"
/>
<StringProperty
Name="IncludePaths"
DisplayName="Include Paths"
Category="Configuration"
Description="Set the paths for any additional include files"
Switch="-I [value]"
Delimited="true"
Inheritable="true"
/>
<StringProperty
Name="UnDefines"
DisplayName="Remove Definitions"
Category="Pre-Defined Symbols"
Description="Remove pre-defined symbols "
Switch="-U [value]"
Delimited="true"
Inheritable="true"
/>
<StringProperty
Name="ObjectFileName"
DisplayName="Object File Name"
Category="Output"
Description="Select the output file name"
Switch="-o [value]"
DefaultValue="$(IntDir)\$(InputName).obj"
/>
<StringProperty
Name="ListFileName"
DisplayName="List File Name"
Category="Output"
Description="Select an output listing by setting its file name"
Switch="-l [value]"
/>
<StringProperty
Name="PreIncludeFile"
DisplayName="Pre Include File"
Category="Configuration"
Description="Select a pre-included file by setting its name"
Switch="-P [value]"
/>
<BooleanProperty
Name="Debug"
DisplayName="Debug Information"
Category="Output"
Description="Generate debugging information"
Switch="-g cv8"
/>
<EnumProperty
Name="PreProc"
DisplayName="Pre-Processor"
Category="Configuration"
Description="Select the pre-processor (&apos;nasm&apos; or &apos;raw&apos;)"
>
<Values>
<EnumValue
Value="0"
Switch="-rnasm"
DisplayName="Nasm "
/>
<EnumValue
Value="1"
Switch="-rraw"
DisplayName="Raw"
/>
</Values>
</EnumProperty>
<EnumProperty
Name="Parser"
DisplayName="Parser"
Category="Configuration"
Description="Select the parser for Intel (&apos;nasm&apos;) or AT&amp;T ( &apos;gas&apos;) syntax"
>
<Values>
<EnumValue
Value="0"
Switch="-pnasm"
DisplayName="Nasm"
/>
<EnumValue
Value="1"
Switch="-pgas"
DisplayName="Gas"
/>
</Values>
</EnumProperty>
</Properties>
</CustomBuildRule>
</Rules>
</VisualStudioToolFile>

View File

@ -1,4 +0,0 @@
# This file is used by git cl to get repository specific information.
GERRIT_HOST: True
CODE_REVIEW_SERVER: chromium-review.googlesource.com
GERRIT_SQUASH_UPLOADS: False

487
configure vendored
View File

@ -1,4 +1,4 @@
#!/bin/sh
#!/bin/bash
##
## configure
##
@ -20,49 +20,32 @@ show_help(){
show_help_pre
cat << EOF
Advanced options:
${toggle_libs} libraries
${toggle_examples} examples
${toggle_tools} tools
${toggle_docs} documentation
${toggle_unit_tests} unit tests
${toggle_decode_perf_tests} build decoder perf tests with unit tests
${toggle_encode_perf_tests} build encoder perf tests with unit tests
--cpu=CPU tune for the specified CPU (ARM: cortex-a8, X86: sse3)
${toggle_libs} don't build libraries
${toggle_examples} don't build examples
${toggle_unit_tests} build unit tests
--libc=PATH path to alternate libc
--size-limit=WxH max size to allow in the decoder
--as={yasm|nasm|auto} use specified assembler [auto, yasm preferred]
--sdk-path=PATH path to root of sdk (android builds only)
--sdk-path=PATH path to root of sdk (iOS, android builds only)
${toggle_fast_unaligned} don't use unaligned accesses, even when
supported by hardware [auto]
${toggle_codec_srcs} in/exclude codec library source code
${toggle_debug_libs} in/exclude debug version of libraries
${toggle_md5} support for output of checksum data
${toggle_static_msvcrt} use static MSVCRT (VS builds only)
${toggle_vp9_highbitdepth} use VP9 high bit depth (10/12) profiles
${toggle_better_hw_compatibility}
enable encoder to produce streams with better
hardware decoder compatibility
${toggle_vp8} VP8 codec support
${toggle_vp9} VP9 codec support
${toggle_internal_stats} output of encoder internal stats for debug, if supported (encoders)
${toggle_mem_tracker} track memory usage
${toggle_postproc} postprocessing
${toggle_vp9_postproc} vp9 specific postprocessing
${toggle_multithread} multithreaded encoding and decoding
${toggle_spatial_resampling} spatial sampling (scaling) support
${toggle_realtime_only} enable this option while building for real-time encoding
${toggle_onthefly_bitpacking} enable on-the-fly bitpacking in real-time encoding
${toggle_error_concealment} enable this option to get a decoder which is able to conceal losses
${toggle_coefficient_range_checking}
enable decoder to check if intermediate
transform coefficients are in valid range
${toggle_runtime_cpu_detect} runtime cpu detection
${toggle_shared} shared library support
${toggle_static} static library support
${toggle_small} favor smaller size over speed
${toggle_postproc_visualizer} macro block / block level visualizers
${toggle_multi_res_encoding} enable multiple-resolution encoding
${toggle_temporal_denoising} enable temporal denoising and disable the spatial denoiser
${toggle_vp9_temporal_denoising}
enable vp9 temporal denoising
${toggle_webm_io} enable input from and output to WebM container
${toggle_libyuv} enable libyuv
Codecs:
Codecs can be selectively enabled or disabled individually, or by family:
@ -75,10 +58,10 @@ Codecs:
EOF
#restore editor state '
family="";
last_family="";
c="";
str="";
local family;
local last_family;
local c;
local str;
for c in ${CODECS}; do
family=${c%_*}
if [ "${family}" != "${last_family}" ]; then
@ -98,97 +81,61 @@ EOF
# all_platforms is a list of all supported target platforms. Maintain
# alphabetically by architecture, generic-gnu last.
all_platforms="${all_platforms} arm64-android-gcc"
all_platforms="${all_platforms} arm64-darwin-gcc"
all_platforms="${all_platforms} arm64-linux-gcc"
all_platforms="${all_platforms} arm64-win64-gcc"
all_platforms="${all_platforms} armv5te-android-gcc"
all_platforms="${all_platforms} armv5te-linux-rvct"
all_platforms="${all_platforms} armv5te-linux-gcc"
all_platforms="${all_platforms} armv5te-none-rvct"
all_platforms="${all_platforms} armv6-darwin-gcc"
all_platforms="${all_platforms} armv6-linux-rvct"
all_platforms="${all_platforms} armv6-linux-gcc"
all_platforms="${all_platforms} armv6-none-rvct"
all_platforms="${all_platforms} armv7-android-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8
all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8
all_platforms="${all_platforms} armv7-none-rvct" #neon Cortex-A8
all_platforms="${all_platforms} armv7-win32-gcc"
all_platforms="${all_platforms} armv7-win32-vs11"
all_platforms="${all_platforms} armv7-win32-vs12"
all_platforms="${all_platforms} armv7-win32-vs14"
all_platforms="${all_platforms} armv7-win32-vs15"
all_platforms="${all_platforms} armv7s-darwin-gcc"
all_platforms="${all_platforms} armv8-linux-gcc"
all_platforms="${all_platforms} mips32-linux-gcc"
all_platforms="${all_platforms} mips64-linux-gcc"
all_platforms="${all_platforms} ppc32-darwin8-gcc"
all_platforms="${all_platforms} ppc32-darwin9-gcc"
all_platforms="${all_platforms} ppc32-linux-gcc"
all_platforms="${all_platforms} ppc64-darwin8-gcc"
all_platforms="${all_platforms} ppc64-darwin9-gcc"
all_platforms="${all_platforms} ppc64-linux-gcc"
all_platforms="${all_platforms} ppc64le-linux-gcc"
all_platforms="${all_platforms} sparc-solaris-gcc"
all_platforms="${all_platforms} x86-android-gcc"
all_platforms="${all_platforms} x86-darwin8-gcc"
all_platforms="${all_platforms} x86-darwin8-icc"
all_platforms="${all_platforms} x86-darwin9-gcc"
all_platforms="${all_platforms} x86-darwin9-icc"
all_platforms="${all_platforms} x86-darwin10-gcc"
all_platforms="${all_platforms} x86-darwin11-gcc"
all_platforms="${all_platforms} x86-darwin12-gcc"
all_platforms="${all_platforms} x86-darwin13-gcc"
all_platforms="${all_platforms} x86-darwin14-gcc"
all_platforms="${all_platforms} x86-darwin15-gcc"
all_platforms="${all_platforms} x86-darwin16-gcc"
all_platforms="${all_platforms} x86-darwin17-gcc"
all_platforms="${all_platforms} x86-iphonesimulator-gcc"
all_platforms="${all_platforms} x86-linux-gcc"
all_platforms="${all_platforms} x86-linux-icc"
all_platforms="${all_platforms} x86-os2-gcc"
all_platforms="${all_platforms} x86-solaris-gcc"
all_platforms="${all_platforms} x86-win32-gcc"
all_platforms="${all_platforms} x86-win32-vs10"
all_platforms="${all_platforms} x86-win32-vs11"
all_platforms="${all_platforms} x86-win32-vs12"
all_platforms="${all_platforms} x86-win32-vs14"
all_platforms="${all_platforms} x86-win32-vs15"
all_platforms="${all_platforms} x86_64-android-gcc"
all_platforms="${all_platforms} x86-win32-vs7"
all_platforms="${all_platforms} x86-win32-vs8"
all_platforms="${all_platforms} x86-win32-vs9"
all_platforms="${all_platforms} x86_64-darwin9-gcc"
all_platforms="${all_platforms} x86_64-darwin10-gcc"
all_platforms="${all_platforms} x86_64-darwin11-gcc"
all_platforms="${all_platforms} x86_64-darwin12-gcc"
all_platforms="${all_platforms} x86_64-darwin13-gcc"
all_platforms="${all_platforms} x86_64-darwin14-gcc"
all_platforms="${all_platforms} x86_64-darwin15-gcc"
all_platforms="${all_platforms} x86_64-darwin16-gcc"
all_platforms="${all_platforms} x86_64-darwin17-gcc"
all_platforms="${all_platforms} x86_64-iphonesimulator-gcc"
all_platforms="${all_platforms} x86_64-linux-gcc"
all_platforms="${all_platforms} x86_64-linux-icc"
all_platforms="${all_platforms} x86_64-solaris-gcc"
all_platforms="${all_platforms} x86_64-win64-gcc"
all_platforms="${all_platforms} x86_64-win64-vs10"
all_platforms="${all_platforms} x86_64-win64-vs11"
all_platforms="${all_platforms} x86_64-win64-vs12"
all_platforms="${all_platforms} x86_64-win64-vs14"
all_platforms="${all_platforms} x86_64-win64-vs15"
all_platforms="${all_platforms} x86_64-win64-vs8"
all_platforms="${all_platforms} x86_64-win64-vs9"
all_platforms="${all_platforms} universal-darwin8-gcc"
all_platforms="${all_platforms} universal-darwin9-gcc"
all_platforms="${all_platforms} generic-gnu"
# all_targets is a list of all targets that can be configured
# note that these should be in dependency order for now.
all_targets="libs examples tools docs"
all_targets="libs examples docs"
# all targets available are enabled, by default.
for t in ${all_targets}; do
[ -f "${source_path}/${t}.mk" ] && enable_feature ${t}
[ -f ${source_path}/${t}.mk ] && enable ${t}
done
if ! diff --version >/dev/null; then
die "diff missing: Try installing diffutils via your package manager."
fi
if ! perl --version >/dev/null; then
die "Perl is required to build"
fi
if [ "`cd \"${source_path}\" && pwd`" != "`pwd`" ]; then
# test to see if source_path already configured
if [ -f "${source_path}/vpx_config.h" ]; then
die "source directory already configured; run 'make distclean' there first"
fi
fi
# check installed doxygen version
doxy_version=$(doxygen --version 2>/dev/null)
doxy_major=${doxy_version%%.*}
@ -197,91 +144,79 @@ if [ ${doxy_major:-0} -ge 1 ]; then
doxy_minor=${doxy_version%%.*}
doxy_patch=${doxy_version##*.}
[ $doxy_major -gt 1 ] && enable_feature doxygen
[ $doxy_minor -gt 5 ] && enable_feature doxygen
[ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable_feature doxygen
[ $doxy_major -gt 1 ] && enable doxygen
[ $doxy_minor -gt 5 ] && enable doxygen
[ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable doxygen
fi
# disable codecs when their source directory does not exist
[ -d "${source_path}/vp8" ] || disable_codec vp8
[ -d "${source_path}/vp9" ] || disable_codec vp9
# install everything except the sources, by default. sources will have
# to be enabled when doing dist builds, since that's no longer a common
# case.
enabled doxygen && enable_feature install_docs
enable_feature install_bins
enable_feature install_libs
enabled doxygen && php -v >/dev/null 2>&1 && enable install_docs
enable install_bins
enable install_libs
enable_feature static
enable_feature optimizations
enable_feature dependency_tracking
enable_feature spatial_resampling
enable_feature multithread
enable_feature os_support
enable_feature temporal_denoising
enable static
enable optimizations
enable fast_unaligned #allow unaligned accesses, if supported by hw
enable md5
enable spatial_resampling
enable multithread
enable os_support
CODECS="
vp8_encoder
vp8_decoder
vp9_encoder
vp9_decoder
"
CODEC_FAMILIES="
vp8
vp9
"
[ -d ${source_path}/../include ] && enable alt_tree_layout
for d in vp8; do
[ -d ${source_path}/${d} ] && disable alt_tree_layout;
done
if ! enabled alt_tree_layout; then
# development environment
[ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
else
# customer environment
[ -f ${source_path}/../include/vpx/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
[ -f ${source_path}/../include/vpx/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
[ -f ${source_path}/../lib/*/*mt.lib ] && soft_enable static_msvcrt
fi
CODECS="$(echo ${CODECS} | tr ' ' '\n')"
CODEC_FAMILIES="$(for c in ${CODECS}; do echo ${c%_*}; done | sort | uniq)"
ARCH_LIST="
arm
mips
x86
x86_64
ppc
ppc32
ppc64
"
ARCH_EXT_LIST_X86="
ARCH_EXT_LIST="
armv5te
armv6
armv7
mips32
mmx
sse
sse2
sse3
ssse3
sse4_1
avx
avx2
avx512
"
ARCH_EXT_LIST_LOONGSON="
mmi
"
ARCH_EXT_LIST="
neon
neon_asm
mips32
dspr2
msa
mips64
${ARCH_EXT_LIST_X86}
vsx
${ARCH_EXT_LIST_LOONGSON}
altivec
"
HAVE_LIST="
${ARCH_EXT_LIST}
vpx_ports
stdint_h
alt_tree_layout
pthread_h
sys_mman_h
unistd_h
"
EXPERIMENT_LIST="
fp_mb_stats
emulate_hardware
"
CONFIG_LIST="
dependency_tracking
external_build
install_docs
install_bins
@ -298,12 +233,16 @@ CONFIG_LIST="
codec_srcs
debug_libs
fast_unaligned
mem_manager
mem_tracker
mem_checks
md5
dequant_tokens
dc_recon
runtime_cpu_detect
postproc
vp9_postproc
multithread
internal_stats
${CODECS}
@ -313,7 +252,6 @@ CONFIG_LIST="
static_msvcrt
spatial_resampling
realtime_only
onthefly_bitpacking
error_concealment
shared
static
@ -321,24 +259,9 @@ CONFIG_LIST="
postproc_visualizer
os_support
unit_tests
webm_io
libyuv
decode_perf_tests
encode_perf_tests
multi_res_encoding
temporal_denoising
vp9_temporal_denoising
coefficient_range_checking
vp9_highbitdepth
better_hw_compatibility
experimental
size_limit
always_adjust_bpm
${EXPERIMENT_LIST}
"
CMDLINE_SELECT="
dependency_tracking
external_build
extra_warnings
werror
install_docs
@ -352,71 +275,41 @@ CMDLINE_SELECT="
optimizations
ccache
runtime_cpu_detect
thumb
libs
examples
tools
docs
libc
as
size_limit
fast_unaligned
codec_srcs
debug_libs
md5
dequant_tokens
dc_recon
postproc
vp9_postproc
multithread
internal_stats
${CODECS}
${CODEC_FAMILIES}
static_msvcrt
mem_tracker
spatial_resampling
realtime_only
onthefly_bitpacking
error_concealment
shared
static
small
postproc_visualizer
unit_tests
webm_io
libyuv
decode_perf_tests
encode_perf_tests
multi_res_encoding
temporal_denoising
vp9_temporal_denoising
coefficient_range_checking
better_hw_compatibility
vp9_highbitdepth
experimental
always_adjust_bpm
"
process_cmdline() {
for opt do
optval="${opt#*=}"
case "$opt" in
--disable-codecs)
for c in ${CODEC_FAMILIES}; do disable_codec $c; done
;;
--enable-?*|--disable-?*)
eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
if is_in ${option} ${EXPERIMENT_LIST}; then
if enabled experimental; then
${action}_feature $option
else
log_echo "Ignoring $opt -- not in experimental mode."
fi
elif is_in ${option} "${CODECS} ${CODEC_FAMILIES}"; then
${action}_codec ${option}
else
process_common_cmdline $opt
fi
;;
--disable-codecs) for c in ${CODECS}; do disable $c; done ;;
*) process_common_cmdline "$opt"
;;
esac
@ -424,31 +317,55 @@ process_cmdline() {
}
post_process_cmdline() {
c=""
local c
# If the codec family is disabled, disable all components of that family.
# If the codec family is enabled, enable all components of that family.
log_echo "Configuring selected codecs"
for c in ${CODECS}; do
disabled ${c%%_*} && disable ${c}
enabled ${c%%_*} && enable ${c}
done
# Enable all detected codecs, if they haven't been disabled
for c in ${CODECS}; do soft_enable $c; done
# Enable the codec family if any component of that family is enabled
for c in ${CODECS}; do
enabled $c && enable_feature ${c%_*}
enabled $c && enable ${c%_*}
done
# Set the {en,de}coders variable if any algorithm in that class is enabled
for c in ${CODECS}; do
enabled ${c} && enable_feature ${c##*_}s
enabled ${c} && enable ${c##*_}s
done
}
process_targets() {
enabled child || write_common_config_banner
write_common_target_config_h ${BUILD_PFX}vpx_config.h
enabled universal || write_common_target_config_h ${BUILD_PFX}vpx_config.h
# TODO: add host tools target (obj_int_extract, etc)
# For fat binaries, call configure recursively to configure for each
# binary architecture to be included.
if enabled universal; then
# Call configure (ourselves) for each subarchitecture
for arch in $fat_bin_archs; do
BUILD_PFX=${arch}/ toolchain=${arch} $self --child $cmdline_args || exit $?
done
fi
# The write_common_config (config.mk) logic is deferred until after the
# recursive calls to configure complete, becuase we want our universal
# targets to be executed last.
write_common_config_targets
enabled universal && echo "FAT_ARCHS=${fat_bin_archs}" >> config.mk
# Calculate the default distribution name, based on the enabled features
cf=""
DIST_DIR=vpx
local cf
local DIST_DIR=vpx
for cf in $CODEC_FAMILIES; do
if enabled ${cf}_encoder && enabled ${cf}_decoder; then
DIST_DIR="${DIST_DIR}-${cf}"
@ -460,7 +377,7 @@ process_targets() {
done
enabled debug_libs && DIST_DIR="${DIST_DIR}-debug"
enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
! enabled postproc && ! enabled vp9_postproc && DIST_DIR="${DIST_DIR}-nopost"
! enabled postproc && DIST_DIR="${DIST_DIR}-nopost"
! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
@ -470,7 +387,7 @@ process_targets() {
;;
esac
if [ -f "${source_path}/build/make/version.sh" ]; then
ver=`"$source_path/build/make/version.sh" --bare "$source_path"`
local ver=`"$source_path/build/make/version.sh" --bare $source_path`
DIST_DIR="${DIST_DIR}-${ver}"
VERSION_STRING=${ver}
ver=${ver%%-*}
@ -503,8 +420,8 @@ EOF
#
# Write makefiles for all enabled targets
#
for tgt in libs examples tools docs solution; do
tgt_fn="$tgt-$toolchain.mk"
for tgt in libs examples docs solution; do
local tgt_fn="$tgt-$toolchain.mk"
if enabled $tgt; then
echo "Creating makefiles for ${toolchain} ${tgt}"
@ -520,55 +437,28 @@ process_detect() {
# Can only build shared libs on a subset of platforms. Doing this check
# here rather than at option parse time because the target auto-detect
# magic happens after the command line has been parsed.
case "${tgt_os}" in
linux|os2|darwin*|iphonesimulator*)
# Supported platforms
;;
*)
if enabled gnu; then
echo "--enable-shared is only supported on ELF; assuming this is OK"
else
die "--enable-shared only supported on ELF, OS/2, and Darwin for now"
fi
;;
esac
enabled linux || die "--enable-shared only supported on ELF for now"
fi
if [ -z "$CC" ] || enabled external_build; then
if [ -z "$CC" ]; then
echo "Bypassing toolchain for environment detection."
enable_feature external_build
enable external_build
check_header() {
log fake_check_header "$@"
header=$1
shift
var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
disable_feature $var
# Headers common to all environments
disable $var
case $header in
stdio.h)
true;
;;
*)
result=false
local result=false
for d in "$@"; do
[ -f "${d##-I}/$header" ] && result=true && break
done
${result:-true}
esac && enable_feature $var
# Specialize windows and POSIX environments.
case $toolchain in
*-win*-*)
# Don't check for any headers in Windows builds.
false
;;
*)
case $header in
pthread.h) true;;
unistd.h) true;;
*) false;;
esac && enable_feature $var
esac
enabled $var
esac && enable $var
}
check_ld() {
true
@ -579,46 +469,41 @@ process_detect() {
int main(void) {return 0;}
EOF
# check system headers
check_header stdint.h
check_header pthread.h
check_header unistd.h # for sysconf(3) and friends.
check_header sys/mman.h
check_header vpx/vpx_integer.h -I${source_path} && enable_feature vpx_ports
check_header vpx/vpx_integer.h -I${source_path} && enable vpx_ports
}
process_toolchain() {
process_common_toolchain
# Handle universal binaries for this architecture
case $toolchain in
universal-darwin*)
local darwin_ver=${tgt_os##darwin}
fat_bin_archs="$fat_bin_archs ppc32-${tgt_os}-gcc"
# Intel
fat_bin_archs="$fat_bin_archs x86-${tgt_os}-${tgt_cc}"
if [ $darwin_ver -gt 8 ]; then
fat_bin_archs="$fat_bin_archs x86_64-${tgt_os}-${tgt_cc}"
fi
;;
esac
# Enable some useful compiler flags
if enabled gcc; then
enabled werror && check_add_cflags -Werror
check_add_cflags -Wall
check_add_cflags -Wdeclaration-after-statement
check_add_cflags -Wdisabled-optimization
check_add_cflags -Wfloat-conversion
check_add_cflags -Wparentheses-equality
check_add_cflags -Wpointer-arith
check_add_cflags -Wtype-limits
check_add_cflags -Wcast-qual
check_add_cflags -Wvla
check_add_cflags -Wimplicit-function-declaration
check_add_cflags -Wuninitialized
check_add_cflags -Wunused
# -Wextra has some tricky cases. Rather than fix them all now, get the
# flag for as many files as possible and fix the remaining issues
# piecemeal.
# https://bugs.chromium.org/p/webm/issues/detail?id=1069
check_add_cflags -Wextra
# check_add_cflags also adds to cxxflags. gtest does not do well with
# these flags so add them explicitly to CFLAGS only.
check_cflags -Wundef && add_cflags_only -Wundef
check_cflags -Wframe-larger-than=52000 && \
add_cflags_only -Wframe-larger-than=52000
if enabled mips || [ -z "${INLINE}" ]; then
enabled extra_warnings || check_add_cflags -Wno-unused-function
fi
# Avoid this warning for third_party C++ sources. Some reorganization
# would be needed to apply this only to test/*.cc.
check_cflags -Wshorten-64-to-32 && add_cflags_only -Wshorten-64-to-32
enabled extra_warnings || check_add_cflags -Wno-unused-function
fi
if enabled icc; then
@ -653,92 +538,25 @@ process_toolchain() {
# ccache only really works on gcc toolchains
enabled gcc || soft_disable ccache
if enabled mips; then
enable_feature dequant_tokens
enable_feature dc_recon
fi
if enabled internal_stats; then
enable_feature vp9_postproc
enable dequant_tokens
enable dc_recon
fi
# Enable the postbuild target if building for visual studio.
case "$tgt_cc" in
vs*) enable_feature msvs
enable_feature solution
vs*) enable msvs
enable solution
vs_version=${tgt_cc##vs}
VCPROJ_SFX=vcxproj
gen_vcproj_cmd=${source_path}/build/make/gen_msvs_vcxproj.sh
enabled werror && gen_vcproj_cmd="${gen_vcproj_cmd} --enable-werror"
all_targets="${all_targets} solution"
INLINE="__inline"
;;
esac
# Other toolchain specific defaults
case $toolchain in x86*) soft_enable postproc;; esac
case $toolchain in x86*|ppc*|universal*) soft_enable postproc;; esac
if enabled postproc_visualizer; then
enabled postproc || die "postproc_visualizer requires postproc to be enabled"
fi
# Enable unit tests by default if we have a working C++ compiler.
case "$toolchain" in
*-vs*)
soft_enable unit_tests
soft_enable webm_io
soft_enable libyuv
;;
*-android-*)
soft_enable webm_io
soft_enable libyuv
# GTestLog must be modified to use Android logging utilities.
;;
*-darwin-*)
# iOS/ARM builds do not work with gtest. This does not match
# x86 targets.
;;
*-iphonesimulator-*)
soft_enable webm_io
soft_enable libyuv
;;
*-win*)
# Some mingw toolchains don't have pthread available by default.
# Treat these more like visual studio where threading in gtest
# would be disabled for the same reason.
check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
check_cxx "$@" <<EOF && soft_enable webm_io
int z;
EOF
check_cxx "$@" <<EOF && soft_enable libyuv
int z;
EOF
;;
*)
enabled pthread_h && check_cxx "$@" <<EOF && soft_enable unit_tests
int z;
EOF
check_cxx "$@" <<EOF && soft_enable webm_io
int z;
EOF
check_cxx "$@" <<EOF && soft_enable libyuv
int z;
EOF
;;
esac
# libwebm needs to be linked with C++ standard library
enabled webm_io && LD=${CXX}
# append any user defined extra cflags
if [ -n "${extra_cflags}" ] ; then
check_add_cflags ${extra_cflags} || \
die "Requested extra CFLAGS '${extra_cflags}' not supported by compiler"
fi
if [ -n "${extra_cxxflags}" ]; then
check_add_cxxflags ${extra_cxxflags} || \
die "Requested extra CXXFLAGS '${extra_cxxflags}' not supported by compiler"
fi
}
@ -749,7 +567,6 @@ CONFIGURE_ARGS="$@"
process "$@"
print_webm_license ${BUILD_PFX}vpx_config.c "/*" " */"
cat <<EOF >> ${BUILD_PFX}vpx_config.c
#include "vpx/vpx_codec.h"
static const char* const cfg = "$CONFIGURE_ARGS";
const char *vpx_codec_build_config(void) {return cfg;}
EOF

10
docs.mk
View File

@ -21,10 +21,18 @@ CODEC_DOX := mainpage.dox \
usage_dx.dox \
# Other doxy files sourced in Markdown
TXT_DOX-$(CONFIG_VP8) += vp8_api1_migration.dox
vp8_api1_migration.dox.DESC = VP8 API 1.x Migration
TXT_DOX = $(call enabled,TXT_DOX)
%.dox: %.txt
@echo " [DOXY] $@"
@$(SRC_PATH_BARE)/examples/gen_example_doxy.php \
$(@:.dox=) "$($@.DESC)" > $@ < $<
EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
EXAMPLE_PATH += $(SRC_PATH_BARE)/examples
doxyfile: $(if $(findstring examples, $(ALL_TARGETS)),examples.doxy)
doxyfile: libs.doxy_template libs.doxy

214
example_xma.c Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/* This is a simple program showing how to initialize the decoder in XMA mode */
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx_config.h"
#include "vpx/vpx_decoder.h"
#include "vpx/vpx_integer.h"
#if CONFIG_VP8_DECODER
#include "vpx/vp8dx.h"
#endif
static char *exec_name;
static int verbose = 0;
static const struct
{
const char *name;
const vpx_codec_iface_t *iface;
} ifaces[] =
{
#if CONFIG_VP8_DECODER
{"vp8", &vpx_codec_vp8_dx_algo},
#endif
};
static void usage_exit(void)
{
int i;
printf("Usage: %s <options>\n\n"
"Options:\n"
"\t--codec <name>\tCodec to use (default=%s)\n"
"\t-h <height>\tHeight of the simulated video frame, in pixels\n"
"\t-w <width> \tWidth of the simulated video frame, in pixels\n"
"\t-v \tVerbose mode (show individual segment sizes)\n"
"\t--help \tShow this message\n"
"\n"
"Included decoders:\n"
"\n",
exec_name,
ifaces[0].name);
for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
printf(" %-6s - %s\n",
ifaces[i].name,
vpx_codec_iface_name(ifaces[i].iface));
exit(EXIT_FAILURE);
}
static void usage_error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
printf("\n");
usage_exit();
}
void my_mem_dtor(vpx_codec_mmap_t *mmap)
{
if (verbose)
printf("freeing segment %d\n", mmap->id);
free(mmap->priv);
}
int main(int argc, char **argv)
{
vpx_codec_ctx_t decoder;
vpx_codec_iface_t *iface = ifaces[0].iface;
vpx_codec_iter_t iter;
vpx_codec_dec_cfg_t cfg;
vpx_codec_err_t res = VPX_CODEC_OK;
unsigned int alloc_sz = 0;
unsigned int w = 352;
unsigned int h = 288;
int i;
exec_name = argv[0];
for (i = 1; i < argc; i++)
{
if (!strcmp(argv[i], "--codec"))
{
if (i + 1 < argc)
{
int j, k = -1;
i++;
for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
if (!strcmp(ifaces[j].name, argv[i]))
k = j;
if (k >= 0)
iface = ifaces[k].iface;
else
usage_error("Error: Unrecognized argument (%s) to --codec\n",
argv[i]);
}
else
usage_error("Error: Option --codec requires argument.\n");
}
else if (!strcmp(argv[i], "-v"))
verbose = 1;
else if (!strcmp(argv[i], "-h"))
if (i + 1 < argc)
{
h = atoi(argv[++i]);
}
else
usage_error("Error: Option -h requires argument.\n");
else if (!strcmp(argv[i], "-w"))
if (i + 1 < argc)
{
w = atoi(argv[++i]);
}
else
usage_error("Error: Option -w requires argument.\n");
else if (!strcmp(argv[i], "--help"))
usage_exit();
else
usage_error("Error: Unrecognized option %s\n\n", argv[i]);
}
if (argc == 1)
printf("Using built-in defaults. For options, rerun with --help\n\n");
/* XMA mode is not supported on all decoders! */
if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA))
{
printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
return EXIT_FAILURE;
}
/* The codec knows how much memory to allocate based on the size of the
* encoded frames. This data can be parsed from the bitstream with
* vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
* a fixed size can be used that will be the upper limit on the frame
* size the decoder can decode.
*/
cfg.w = w;
cfg.h = h;
/* Initialize the decoder in XMA mode. */
if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA))
{
printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder));
return EXIT_FAILURE;
}
/* Iterate through the list of memory maps, allocating them with the
* requested alignment.
*/
iter = NULL;
do
{
vpx_codec_mmap_t mmap;
unsigned int align;
res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
align = mmap.align ? mmap.align - 1 : 0;
if (!res)
{
if (verbose)
printf("Allocating segment %u, size %lu, align %u %s\n",
mmap.id, mmap.sz, mmap.align,
mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
if (mmap.flags & VPX_CODEC_MEM_ZERO)
mmap.priv = calloc(1, mmap.sz + align);
else
mmap.priv = malloc(mmap.sz + align);
mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align);
mmap.dtor = my_mem_dtor;
alloc_sz += mmap.sz + align;
if (vpx_codec_set_mem_map(&decoder, &mmap, 1))
{
printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
return EXIT_FAILURE;
}
}
else if (res != VPX_CODEC_LIST_END)
{
printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
return EXIT_FAILURE;
}
}
while (res != VPX_CODEC_LIST_END);
printf("%s\n %d bytes external memory required for %dx%d.\n",
decoder.name, alloc_sz, cfg.w, cfg.h);
vpx_codec_destroy(&decoder);
return EXIT_SUCCESS;
}

View File

@ -8,237 +8,105 @@
## be found in the AUTHORS file in the root of the source tree.
##
LIBYUV_SRCS += third_party/libyuv/include/libyuv/basic_types.h \
third_party/libyuv/include/libyuv/convert.h \
third_party/libyuv/include/libyuv/convert_argb.h \
third_party/libyuv/include/libyuv/convert_from.h \
third_party/libyuv/include/libyuv/cpu_id.h \
third_party/libyuv/include/libyuv/planar_functions.h \
third_party/libyuv/include/libyuv/rotate.h \
third_party/libyuv/include/libyuv/row.h \
third_party/libyuv/include/libyuv/scale.h \
third_party/libyuv/include/libyuv/scale_row.h \
third_party/libyuv/source/cpu_id.cc \
third_party/libyuv/source/planar_functions.cc \
third_party/libyuv/source/row_any.cc \
third_party/libyuv/source/row_common.cc \
third_party/libyuv/source/row_gcc.cc \
third_party/libyuv/source/row_mips.cc \
third_party/libyuv/source/row_neon.cc \
third_party/libyuv/source/row_neon64.cc \
third_party/libyuv/source/row_win.cc \
third_party/libyuv/source/scale.cc \
third_party/libyuv/source/scale_any.cc \
third_party/libyuv/source/scale_common.cc \
third_party/libyuv/source/scale_gcc.cc \
third_party/libyuv/source/scale_mips.cc \
third_party/libyuv/source/scale_neon.cc \
third_party/libyuv/source/scale_neon64.cc \
third_party/libyuv/source/scale_win.cc \
LIBWEBM_COMMON_SRCS += third_party/libwebm/common/hdr_util.cc \
third_party/libwebm/common/hdr_util.h \
third_party/libwebm/common/webmids.h
LIBWEBM_MUXER_SRCS += third_party/libwebm/mkvmuxer/mkvmuxer.cc \
third_party/libwebm/mkvmuxer/mkvmuxerutil.cc \
third_party/libwebm/mkvmuxer/mkvwriter.cc \
third_party/libwebm/mkvmuxer/mkvmuxer.h \
third_party/libwebm/mkvmuxer/mkvmuxertypes.h \
third_party/libwebm/mkvmuxer/mkvmuxerutil.h \
third_party/libwebm/mkvparser/mkvparser.h \
third_party/libwebm/mkvmuxer/mkvwriter.h
LIBWEBM_PARSER_SRCS = third_party/libwebm/mkvparser/mkvparser.cc \
third_party/libwebm/mkvparser/mkvreader.cc \
third_party/libwebm/mkvparser/mkvparser.h \
third_party/libwebm/mkvparser/mkvreader.h
# Add compile flags and include path for libwebm sources.
ifeq ($(CONFIG_WEBM_IO),yes)
CXXFLAGS += -D__STDC_CONSTANT_MACROS -D__STDC_LIMIT_MACROS
INC_PATH-yes += $(SRC_PATH_BARE)/third_party/libwebm
endif
# List of examples to build. UTILS are tools meant for distribution
# while EXAMPLES demonstrate specific portions of the API.
# List of examples to build. UTILS are files that are taken from the source
# tree directly, and GEN_EXAMPLES are files that are created from the
# examples folder.
UTILS-$(CONFIG_DECODERS) += vpxdec.c
vpxdec.SRCS += md5_utils.c md5_utils.h
vpxdec.SRCS += vpx_ports/mem_ops.h
vpxdec.SRCS += vpx_ports/mem_ops_aligned.h
vpxdec.SRCS += vpx_ports/msvc.h
vpxdec.SRCS += vpx_ports/vpx_timer.h
vpxdec.SRCS += vpx/vpx_integer.h
vpxdec.SRCS += args.c args.h
vpxdec.SRCS += ivfdec.c ivfdec.h
vpxdec.SRCS += tools_common.c tools_common.h
vpxdec.SRCS += y4menc.c y4menc.h
ifeq ($(CONFIG_LIBYUV),yes)
vpxdec.SRCS += $(LIBYUV_SRCS)
$(BUILD_PFX)third_party/libyuv/%.cc.o: CXXFLAGS += -Wno-unused-parameter
endif
ifeq ($(CONFIG_WEBM_IO),yes)
vpxdec.SRCS += $(LIBWEBM_COMMON_SRCS)
vpxdec.SRCS += $(LIBWEBM_MUXER_SRCS)
vpxdec.SRCS += $(LIBWEBM_PARSER_SRCS)
vpxdec.SRCS += webmdec.cc webmdec.h
endif
vpxdec.SRCS += nestegg/halloc/halloc.h
vpxdec.SRCS += nestegg/halloc/src/align.h
vpxdec.SRCS += nestegg/halloc/src/halloc.c
vpxdec.SRCS += nestegg/halloc/src/hlist.h
vpxdec.SRCS += nestegg/halloc/src/macros.h
vpxdec.SRCS += nestegg/include/nestegg/nestegg.h
vpxdec.SRCS += nestegg/src/nestegg.c
vpxdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
vpxdec.DESCRIPTION = Full featured decoder
UTILS-$(CONFIG_ENCODERS) += vpxenc.c
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h vpxenc.h
vpxenc.SRCS += ivfdec.c ivfdec.h
vpxenc.SRCS += ivfenc.c ivfenc.h
vpxenc.SRCS += rate_hist.c rate_hist.h
vpxenc.SRCS += args.c args.h y4minput.c y4minput.h
vpxenc.SRCS += tools_common.c tools_common.h
vpxenc.SRCS += warnings.c warnings.h
vpxenc.SRCS += vpx_ports/mem_ops.h
vpxenc.SRCS += vpx_ports/mem_ops_aligned.h
vpxenc.SRCS += vpx_ports/msvc.h
vpxenc.SRCS += vpx_ports/vpx_timer.h
vpxenc.SRCS += vpxstats.c vpxstats.h
ifeq ($(CONFIG_LIBYUV),yes)
vpxenc.SRCS += $(LIBYUV_SRCS)
endif
ifeq ($(CONFIG_WEBM_IO),yes)
vpxenc.SRCS += $(LIBWEBM_COMMON_SRCS)
vpxenc.SRCS += $(LIBWEBM_MUXER_SRCS)
vpxenc.SRCS += $(LIBWEBM_PARSER_SRCS)
vpxenc.SRCS += webmenc.cc webmenc.h
endif
vpxenc.SRCS += libmkv/EbmlIDs.h
vpxenc.SRCS += libmkv/EbmlWriter.c
vpxenc.SRCS += libmkv/EbmlWriter.h
vpxenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
vpxenc.DESCRIPTION = Full featured encoder
UTILS-$(CONFIG_ENCODERS) += vp8_scalable_patterns.c
vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
vp8_scalable_patterns.DESCRIPTION = Temporal Scalability Encoder
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_spatial_svc_encoder.c
vp9_spatial_svc_encoder.SRCS += args.c args.h
vp9_spatial_svc_encoder.SRCS += ivfenc.c ivfenc.h
vp9_spatial_svc_encoder.SRCS += tools_common.c tools_common.h
vp9_spatial_svc_encoder.SRCS += video_common.h
vp9_spatial_svc_encoder.SRCS += video_writer.h video_writer.c
vp9_spatial_svc_encoder.SRCS += vpx_ports/msvc.h
vp9_spatial_svc_encoder.SRCS += vpxstats.c vpxstats.h
vp9_spatial_svc_encoder.GUID = 4A38598D-627D-4505-9C7B-D4020C84100D
vp9_spatial_svc_encoder.DESCRIPTION = VP9 Spatial SVC Encoder
ifneq ($(CONFIG_SHARED),yes)
EXAMPLES-$(CONFIG_VP9_ENCODER) += resize_util.c
# Clean up old ivfenc, ivfdec binaries.
ifeq ($(CONFIG_MSVS),yes)
CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfenc.exe)
CLEAN-OBJS += $(foreach p,$(VS_PLATFORMS),$(p)/Release/ivfdec.exe)
else
CLEAN-OBJS += ivfenc{.c.o,.c.d,.dox,.exe,}
CLEAN-OBJS += ivfdec{.c.o,.c.d,.dox,.exe,}
endif
EXAMPLES-$(CONFIG_ENCODERS) += vpx_temporal_svc_encoder.c
vpx_temporal_svc_encoder.SRCS += ivfenc.c ivfenc.h
vpx_temporal_svc_encoder.SRCS += tools_common.c tools_common.h
vpx_temporal_svc_encoder.SRCS += video_common.h
vpx_temporal_svc_encoder.SRCS += video_writer.h video_writer.c
vpx_temporal_svc_encoder.SRCS += vpx_ports/msvc.h
vpx_temporal_svc_encoder.GUID = B18C08F2-A439-4502-A78E-849BE3D60947
vpx_temporal_svc_encoder.DESCRIPTION = Temporal SVC Encoder
EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
simple_decoder.SRCS += ivfdec.h ivfdec.c
simple_decoder.SRCS += tools_common.h tools_common.c
simple_decoder.SRCS += video_common.h
simple_decoder.SRCS += video_reader.h video_reader.c
simple_decoder.SRCS += vpx_ports/mem_ops.h
simple_decoder.SRCS += vpx_ports/mem_ops_aligned.h
simple_decoder.SRCS += vpx_ports/msvc.h
simple_decoder.DESCRIPTION = Simplified decoder loop
EXAMPLES-$(CONFIG_DECODERS) += postproc.c
postproc.SRCS += ivfdec.h ivfdec.c
postproc.SRCS += tools_common.h tools_common.c
postproc.SRCS += video_common.h
postproc.SRCS += video_reader.h video_reader.c
postproc.SRCS += vpx_ports/mem_ops.h
postproc.SRCS += vpx_ports/mem_ops_aligned.h
postproc.SRCS += vpx_ports/msvc.h
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
postproc.DESCRIPTION = Decoder postprocessor control
EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
decode_to_md5.SRCS += md5_utils.h md5_utils.c
decode_to_md5.SRCS += ivfdec.h ivfdec.c
decode_to_md5.SRCS += tools_common.h tools_common.c
decode_to_md5.SRCS += video_common.h
decode_to_md5.SRCS += video_reader.h video_reader.c
decode_to_md5.SRCS += vpx_ports/mem_ops.h
decode_to_md5.SRCS += vpx_ports/mem_ops_aligned.h
decode_to_md5.SRCS += vpx_ports/msvc.h
decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
simple_encoder.SRCS += ivfenc.h ivfenc.c
simple_encoder.SRCS += tools_common.h tools_common.c
simple_encoder.SRCS += video_common.h
simple_encoder.SRCS += video_writer.h video_writer.c
simple_encoder.SRCS += vpx_ports/msvc.h
# XMA example disabled for now, not used in VP8
#UTILS-$(CONFIG_DECODERS) += example_xma.c
#example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
#example_xma.DESCRIPTION = External Memory Allocation mode usage
GEN_EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
simple_decoder.DESCRIPTION = Simplified decoder loop
GEN_EXAMPLES-$(CONFIG_DECODERS) += postproc.c
postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
postproc.DESCRIPTION = Decoder postprocessor control
GEN_EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
decode_to_md5.SRCS += md5_utils.h md5_utils.c
decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
GEN_EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
simple_encoder.DESCRIPTION = Simplified encoder loop
EXAMPLES-$(CONFIG_VP9_ENCODER) += vp9_lossless_encoder.c
vp9_lossless_encoder.SRCS += ivfenc.h ivfenc.c
vp9_lossless_encoder.SRCS += tools_common.h tools_common.c
vp9_lossless_encoder.SRCS += video_common.h
vp9_lossless_encoder.SRCS += video_writer.h video_writer.c
vp9_lossless_encoder.SRCS += vpx_ports/msvc.h
vp9_lossless_encoder.GUID = B63C7C88-5348-46DC-A5A6-CC151EF93366
vp9_lossless_encoder.DESCRIPTION = Simplified lossless VP9 encoder
EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
twopass_encoder.SRCS += ivfenc.h ivfenc.c
twopass_encoder.SRCS += tools_common.h tools_common.c
twopass_encoder.SRCS += video_common.h
twopass_encoder.SRCS += video_writer.h video_writer.c
twopass_encoder.SRCS += vpx_ports/msvc.h
GEN_EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
twopass_encoder.GUID = 73494FA6-4AF9-4763-8FBB-265C92402FD8
twopass_encoder.DESCRIPTION = Two-pass encoder loop
EXAMPLES-$(CONFIG_DECODERS) += decode_with_drops.c
decode_with_drops.SRCS += ivfdec.h ivfdec.c
decode_with_drops.SRCS += tools_common.h tools_common.c
decode_with_drops.SRCS += video_common.h
decode_with_drops.SRCS += video_reader.h video_reader.c
decode_with_drops.SRCS += vpx_ports/mem_ops.h
decode_with_drops.SRCS += vpx_ports/mem_ops_aligned.h
decode_with_drops.SRCS += vpx_ports/msvc.h
GEN_EXAMPLES-$(CONFIG_ENCODERS) += force_keyframe.c
force_keyframe.GUID = 3C67CADF-029F-4C86-81F5-D6D4F51177F0
force_keyframe.DESCRIPTION = Force generation of keyframes
ifeq ($(CONFIG_DECODERS),yes)
GEN_EXAMPLES-$(CONFIG_ENCODERS) += decode_with_drops.c
endif
decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
decode_with_drops.DESCRIPTION = Drops frames while decoding
EXAMPLES-$(CONFIG_ENCODERS) += set_maps.c
set_maps.SRCS += ivfenc.h ivfenc.c
set_maps.SRCS += tools_common.h tools_common.c
set_maps.SRCS += video_common.h
set_maps.SRCS += video_writer.h video_writer.c
set_maps.SRCS += vpx_ports/msvc.h
set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
set_maps.DESCRIPTION = Set active and ROI maps
EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
vp8cx_set_ref.SRCS += ivfenc.h ivfenc.c
vp8cx_set_ref.SRCS += tools_common.h tools_common.c
vp8cx_set_ref.SRCS += video_common.h
vp8cx_set_ref.SRCS += video_writer.h video_writer.c
vp8cx_set_ref.SRCS += vpx_ports/msvc.h
ifeq ($(CONFIG_DECODERS),yes)
GEN_EXAMPLES-$(CONFIG_ERROR_CONCEALMENT) += decode_with_partial_drops.c
endif
decode_with_partial_drops.GUID = 61C2D026-5754-46AC-916F-1343ECC5537E
decode_with_partial_drops.DESCRIPTION = Drops parts of frames while decoding
GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
error_resilient.DESCRIPTION = Error Resiliency Feature
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
vp8_set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
vp8_set_maps.DESCRIPTION = VP8 set active and ROI maps
GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
vp8cx_set_ref.GUID = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame
ifeq ($(CONFIG_VP9_ENCODER),yes)
ifeq ($(CONFIG_DECODERS),yes)
EXAMPLES-yes += vp9cx_set_ref.c
vp9cx_set_ref.SRCS += ivfenc.h ivfenc.c
vp9cx_set_ref.SRCS += tools_common.h tools_common.c
vp9cx_set_ref.SRCS += video_common.h
vp9cx_set_ref.SRCS += video_writer.h video_writer.c
vp9cx_set_ref.GUID = 65D7F14A-2EE6-4293-B958-AB5107A03B55
vp9cx_set_ref.DESCRIPTION = VP9 set encoder reference frame
endif
endif
ifeq ($(CONFIG_MULTI_RES_ENCODING),yes)
ifeq ($(CONFIG_LIBYUV),yes)
EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_multi_resolution_encoder.c
vp8_multi_resolution_encoder.SRCS += ivfenc.h ivfenc.c
vp8_multi_resolution_encoder.SRCS += tools_common.h tools_common.c
vp8_multi_resolution_encoder.SRCS += video_writer.h video_writer.c
vp8_multi_resolution_encoder.SRCS += vpx_ports/msvc.h
vp8_multi_resolution_encoder.SRCS += $(LIBYUV_SRCS)
vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de
vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
endif
endif
# C file is provided, not generated automatically.
GEN_EXAMPLES-$(CONFIG_MULTI_RES_ENCODING) += vp8_multi_resolution_encoder.c
vp8_multi_resolution_encoder.SRCS \
+= third_party/libyuv/include/libyuv/basic_types.h \
third_party/libyuv/include/libyuv/cpu_id.h \
third_party/libyuv/include/libyuv/scale.h \
third_party/libyuv/source/row.h \
third_party/libyuv/source/scale.c \
third_party/libyuv/source/cpu_id.c
vp8_multi_resolution_encoder.GUID = 04f8738e-63c8-423b-90fa-7c2703a374de
vp8_multi_resolution_encoder.DESCRIPTION = VP8 Multiple-resolution Encoding
# Handle extra library flags depending on codec configuration
@ -246,11 +114,9 @@ endif
# when building for bare-metal targets
ifeq ($(CONFIG_OS_SUPPORT), yes)
CODEC_EXTRA_LIBS-$(CONFIG_VP8) += m
CODEC_EXTRA_LIBS-$(CONFIG_VP9) += m
else
ifeq ($(CONFIG_GCC), yes)
CODEC_EXTRA_LIBS-$(CONFIG_VP8) += m
CODEC_EXTRA_LIBS-$(CONFIG_VP9) += m
endif
endif
#
@ -263,66 +129,74 @@ endif
# from an installed tree or a version controlled tree. Determine
# the proper paths.
ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
LIB_PATH-yes := $(SRC_PATH_BARE)/../lib
INC_PATH-yes := $(SRC_PATH_BARE)/../include
LIB_PATH := $(SRC_PATH_BARE)/../lib
INC_PATH := $(SRC_PATH_BARE)/../include
else
LIB_PATH-yes += $(if $(BUILD_PFX),$(BUILD_PFX),.)
INC_PATH-$(CONFIG_VP8_DECODER) += $(SRC_PATH_BARE)/vp8
INC_PATH-$(CONFIG_VP8_ENCODER) += $(SRC_PATH_BARE)/vp8
INC_PATH-$(CONFIG_VP9_DECODER) += $(SRC_PATH_BARE)/vp9
INC_PATH-$(CONFIG_VP9_ENCODER) += $(SRC_PATH_BARE)/vp9
LIB_PATH := $(call enabled,LIB_PATH)
INC_PATH := $(call enabled,INC_PATH)
endif
INC_PATH-$(CONFIG_LIBYUV) += $(SRC_PATH_BARE)/third_party/libyuv/include
LIB_PATH := $(call enabled,LIB_PATH)
INC_PATH := $(call enabled,INC_PATH)
INTERNAL_CFLAGS = $(addprefix -I,$(INC_PATH))
INTERNAL_LDFLAGS += $(addprefix -L,$(LIB_PATH))
# Expand list of selected examples to build (as specified above)
UTILS = $(call enabled,UTILS)
EXAMPLES = $(addprefix examples/,$(call enabled,EXAMPLES))
ALL_EXAMPLES = $(UTILS) $(EXAMPLES)
GEN_EXAMPLES = $(call enabled,GEN_EXAMPLES)
ALL_EXAMPLES = $(UTILS) $(GEN_EXAMPLES)
UTIL_SRCS = $(foreach ex,$(UTILS),$($(ex:.c=).SRCS))
ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(notdir $(ex:.c=)).SRCS))
ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
# Expand all example sources into a variable containing all sources
# for that example (not just them main one specified in UTILS/EXAMPLES)
# for that example (not just them main one specified in UTILS/GEN_EXAMPLES)
# and add this file to the list (for MSVS workspace generation)
$(foreach ex,$(ALL_EXAMPLES),$(eval $(notdir $(ex:.c=)).SRCS += $(ex) examples.mk))
$(foreach ex,$(ALL_EXAMPLES),$(eval $(ex:.c=).SRCS += $(ex) examples.mk))
# If this is a universal (fat) binary, then all the subarchitectures have
# already been built and our job is to stitch them together. The
# BUILD_OBJS variable indicates whether we should be building
# (compiling, linking) the library. The LIPO_OBJS variable indicates
# that we're stitching.
$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_OBJS,BUILD_OBJS):=yes)
# Create build/install dependencies for all examples. The common case
# is handled here. The MSVS case is handled below.
NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
DIST-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=$(EXE_SFX)))
INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(UTILS:.c=$(EXE_SFX)))
DIST-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=))
INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(UTILS:.c=))
DIST-SRCS-yes += $(ALL_SRCS)
INSTALL-SRCS-yes += $(UTIL_SRCS)
OBJS-$(NOT_MSVS) += $(call objs,$(ALL_SRCS))
BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=$(EXE_SFX)))
OBJS-$(NOT_MSVS) += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=))
# Instantiate linker template for all examples.
CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
ifneq ($(filter darwin%,$(TGT_OS)),)
SHARED_LIB_SUF=.dylib
else
ifneq ($(filter os2%,$(TGT_OS)),)
SHARED_LIB_SUF=_dll.a
else
SHARED_LIB_SUF=.so
endif
endif
CODEC_LIB_SUF=$(if $(CONFIG_SHARED),$(SHARED_LIB_SUF),.a)
CODEC_LIB_SUF=$(if $(CONFIG_SHARED),.so,.a)
$(foreach bin,$(BINS-yes),\
$(eval $(bin):$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF))\
$(eval $(call linker_template,$(bin),\
$(call objs,$($(notdir $(bin:$(EXE_SFX)=)).SRCS)) \
$(if $(BUILD_OBJS),$(eval $(bin):\
$(LIB_PATH)/lib$(CODEC_LIB)$(CODEC_LIB_SUF)))\
$(if $(BUILD_OBJS),$(eval $(call linker_template,$(bin),\
$(call objs,$($(notdir $(bin)).SRCS)) \
-l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\
)))
)))\
$(if $(LIPO_OBJS),$(eval $(call lipo_bin_template,$(bin))))\
)
# Rules to generate the GEN_EXAMPLES sources
.PRECIOUS: %.c
CLEAN-OBJS += $(GEN_EXAMPLES)
%.c: examples/%.txt
@echo " [EXAMPLE] $@"
@$(SRC_PATH_BARE)/examples/gen_example_code.sh $< > $@
# The following pairs define a mapping of locations in the distribution
# tree to locations in the source/build trees.
@ -334,7 +208,7 @@ INSTALL_MAPS += % %
# Set up additional MSVS environment
ifeq ($(CONFIG_MSVS),yes)
CODEC_LIB=$(if $(CONFIG_SHARED),vpx,$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd))
CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
# This variable uses deferred expansion intentionally, since the results of
# $(wildcard) may change during the course of the Make.
VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
@ -349,56 +223,62 @@ endif
# even though there is no real dependency there (the dependency is on
# the makefiles). We may want to revisit this.
define vcproj_template
$(1): $($(1:.$(VCPROJ_SFX)=).SRCS) vpx.$(VCPROJ_SFX)
$(if $(quiet),@echo " [vcproj] $$@")
$(qexec)$$(GEN_VCPROJ)\
$(1): $($(1:.vcproj=).SRCS)
@echo " [vcproj] $$@"
$$(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
--exe\
--target=$$(TOOLCHAIN)\
--name=$$(@:.$(VCPROJ_SFX)=)\
--name=$$(@:.vcproj=)\
--ver=$$(CONFIG_VS_VERSION)\
--proj-guid=$$($$(@:.$(VCPROJ_SFX)=).GUID)\
--src-path-bare="$(SRC_PATH_BARE)" \
--proj-guid=$$($$(@:.vcproj=).GUID)\
$$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
--out=$$@ $$(INTERNAL_CFLAGS) $$(CFLAGS) \
$$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) $$^
$$(INTERNAL_LDFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) -lwinmm $$^
endef
ALL_EXAMPLES_BASENAME := $(notdir $(ALL_EXAMPLES))
PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES_BASENAME:.c=.$(VCPROJ_SFX))
PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES:.c=.vcproj)
INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\
$(addprefix bin/$(p)/,$(ALL_EXAMPLES_BASENAME:.c=.exe)))
$(addprefix bin/$(p)/,$(ALL_EXAMPLES:.c=.exe)))
$(foreach proj,$(call enabled,PROJECTS),\
$(eval $(call vcproj_template,$(proj))))
#
# Documentation Rules
#
%.dox: examples/%.txt
@echo " [DOXY] $@"
@$(SRC_PATH_BARE)/examples/gen_example_text.sh $< | \
$(SRC_PATH_BARE)/examples/gen_example_doxy.php \
example_$(@:.dox=) $(@:.dox=.c) > $@
%.dox: %.c
@echo " [DOXY] $@"
@mkdir -p $(dir $@)
@echo "/*!\page example_$(@F:.dox=) $(@F:.dox=)" > $@
@echo " \includelineno $(<F)" >> $@
@echo "/*!\page example_$(@:.dox=) $(@:.dox=)" > $@
@echo " \includelineno $(notdir $<)" >> $@
@echo "*/" >> $@
samples.dox: examples.mk
@echo " [DOXY] $@"
@echo "/*!\page samples Sample Code" > $@
@echo " This SDK includes a number of sample applications."\
"Each sample documents a feature of the SDK in both prose"\
"and the associated C code."\
"The following samples are included: ">>$@
@$(foreach ex,$(sort $(notdir $(EXAMPLES:.c=))),\
"each sample documents a feature of the SDK in both prose"\
"and the associated C code. In general, later samples"\
"build upon prior samples, so it is best to work through the"\
"list in order. The following samples are included: ">>$@
@$(foreach ex,$(GEN_EXAMPLES:.c=),\
echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
@echo >> $@
@echo " In addition, the SDK contains a number of utilities."\
"Since these utilities are built upon the concepts described"\
"in the sample code listed above, they are not documented in"\
"pieces like the samples are. Their source is included here"\
"pieces like the samples are. Thir sourcre is included here"\
"for reference. The following utilities are included:" >> $@
@$(foreach ex,$(sort $(UTILS:.c=)),\
@$(foreach ex,$(UTILS:.c=),\
echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
@echo "*/" >> $@
CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
DOCS-yes += examples.doxy samples.dox
DOCS-yes += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox)
@echo "INPUT += $^" > $@

View File

@ -1,132 +0,0 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Frame-by-frame MD5 Checksum
// ===========================
//
// This example builds upon the simple decoder loop to show how checksums
// of the decoded output can be generated. These are used for validating
// decoder implementations against the reference implementation, for example.
//
// MD5 algorithm
// -------------
// The Message-Digest 5 (MD5) is a well known hash function. We have provided
// an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
// Algorithm for your use. Our implmentation only changes the interface of this
// reference code. You must include the `md5_utils.h` header for access to these
// functions.
//
// Processing The Decoded Data
// ---------------------------
// Each row of the image is passed to the MD5 accumulator. First the Y plane
// is processed, then U, then V. It is important to honor the image's `stride`
// values.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"
#include "../md5_utils.h"
#include "../tools_common.h"
#include "../video_reader.h"
#include "./vpx_config.h"
static void get_image_md5(const vpx_image_t *img, unsigned char digest[16]) {
int plane, y;
MD5Context md5;
MD5Init(&md5);
for (plane = 0; plane < 3; ++plane) {
const unsigned char *buf = img->planes[plane];
const int stride = img->stride[plane];
const int w = plane ? (img->d_w + 1) >> 1 : img->d_w;
const int h = plane ? (img->d_h + 1) >> 1 : img->d_h;
for (y = 0; y < h; ++y) {
MD5Update(&md5, buf, w);
buf += stride;
}
}
MD5Final(digest, &md5);
}
static void print_md5(FILE *stream, unsigned char digest[16]) {
int i;
for (i = 0; i < 16; ++i) fprintf(stream, "%02x", digest[i]);
}
static const char *exec_name;
void usage_exit(void) {
fprintf(stderr, "Usage: %s <infile> <outfile>\n", exec_name);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
int frame_cnt = 0;
FILE *outfile = NULL;
vpx_codec_ctx_t codec;
VpxVideoReader *reader = NULL;
const VpxVideoInfo *info = NULL;
const VpxInterface *decoder = NULL;
exec_name = argv[0];
if (argc != 3) die("Invalid number of arguments.");
reader = vpx_video_reader_open(argv[1]);
if (!reader) die("Failed to open %s for reading.", argv[1]);
if (!(outfile = fopen(argv[2], "wb")))
die("Failed to open %s for writing.", argv[2]);
info = vpx_video_reader_get_info(reader);
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
if (!decoder) die("Unknown input codec.");
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
die_codec(&codec, "Failed to initialize decoder");
while (vpx_video_reader_read_frame(reader)) {
vpx_codec_iter_t iter = NULL;
vpx_image_t *img = NULL;
size_t frame_size = 0;
const unsigned char *frame =
vpx_video_reader_get_frame(reader, &frame_size);
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
die_codec(&codec, "Failed to decode frame");
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL) {
unsigned char digest[16];
get_image_md5(img, digest);
print_md5(outfile, digest);
fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
++frame_cnt);
}
}
printf("Processed %d frames.\n", frame_cnt);
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
vpx_video_reader_close(reader);
fclose(outfile);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,48 @@
@TEMPLATE decoder_tmpl.c
Frame-by-frame MD5 Checksum
===========================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This example builds upon the simple decoder loop to show how checksums
of the decoded output can be generated. These are used for validating
decoder implementations against the reference implementation, for example.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
MD5 algorithm
-------------
The Message-Digest 5 (MD5) is a well known hash function. We have provided
an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
Algorithm for your use. Our implmentation only changes the interface of this
reference code. You must include the `md5_utils.h` header for access to these
functions.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
#include "md5_utils.h"
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
Processing The Decoded Data
---------------------------
Each row of the image is passed to the MD5 accumulator. First the Y plane
is processed, then U, then V. It is important to honor the image's `stride`
values.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
unsigned char md5_sum[16];
MD5Context md5;
int i;
MD5Init(&md5);
for(plane=0; plane < 3; plane++) {
unsigned char *buf =img->planes[plane];
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
MD5Update(&md5, buf, (plane ? (img->d_w + 1) >> 1 : img->d_w));
buf += img->stride[plane];
}
}
MD5Final(md5_sum, &md5);
for(i=0; i<16; i++)
fprintf(outfile, "%02x",md5_sum[i]);
fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
frame_cnt);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX

View File

@ -1,148 +0,0 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
// Decode With Drops Example
// =========================
//
// This is an example utility which drops a series of frames, as specified
// on the command line. This is useful for observing the error recovery
// features of the codec.
//
// Usage
// -----
// This example adds a single argument to the `simple_decoder` example,
// which specifies the range or pattern of frames to drop. The parameter is
// parsed as follows:
//
// Dropping A Range Of Frames
// --------------------------
// To drop a range of frames, specify the starting frame and the ending
// frame to drop, separated by a dash. The following command will drop
// frames 5 through 10 (base 1).
//
// $ ./decode_with_drops in.ivf out.i420 5-10
//
//
// Dropping A Pattern Of Frames
// ----------------------------
// To drop a pattern of frames, specify the number of frames to drop and
// the number of frames after which to repeat the pattern, separated by
// a forward-slash. The following command will drop 3 of 7 frames.
// Specifically, it will decode 4 frames, then drop 3 frames, and then
// repeat.
//
// $ ./decode_with_drops in.ivf out.i420 3/7
//
//
// Extra Variables
// ---------------
// This example maintains the pattern passed on the command line in the
// `n`, `m`, and `is_range` variables:
//
//
// Making The Drop Decision
// ------------------------
// The example decides whether to drop the frame based on the current
// frame number, immediately before decoding the frame.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vpx/vp8dx.h"
#include "vpx/vpx_decoder.h"
#include "../tools_common.h"
#include "../video_reader.h"
#include "./vpx_config.h"
static const char *exec_name;
void usage_exit(void) {
fprintf(stderr, "Usage: %s <infile> <outfile> <N-M|N/M>\n", exec_name);
exit(EXIT_FAILURE);
}
int main(int argc, char **argv) {
int frame_cnt = 0;
FILE *outfile = NULL;
vpx_codec_ctx_t codec;
const VpxInterface *decoder = NULL;
VpxVideoReader *reader = NULL;
const VpxVideoInfo *info = NULL;
int n = 0;
int m = 0;
int is_range = 0;
char *nptr = NULL;
exec_name = argv[0];
if (argc != 4) die("Invalid number of arguments.");
reader = vpx_video_reader_open(argv[1]);
if (!reader) die("Failed to open %s for reading.", argv[1]);
if (!(outfile = fopen(argv[2], "wb")))
die("Failed to open %s for writing.", argv[2]);
n = (int)strtol(argv[3], &nptr, 0);
m = (int)strtol(nptr + 1, NULL, 0);
is_range = (*nptr == '-');
if (!n || !m || (*nptr != '-' && *nptr != '/'))
die("Couldn't parse pattern %s.\n", argv[3]);
info = vpx_video_reader_get_info(reader);
decoder = get_vpx_decoder_by_fourcc(info->codec_fourcc);
if (!decoder) die("Unknown input codec.");
printf("Using %s\n", vpx_codec_iface_name(decoder->codec_interface()));
if (vpx_codec_dec_init(&codec, decoder->codec_interface(), NULL, 0))
die_codec(&codec, "Failed to initialize decoder.");
while (vpx_video_reader_read_frame(reader)) {
vpx_codec_iter_t iter = NULL;
vpx_image_t *img = NULL;
size_t frame_size = 0;
int skip;
const unsigned char *frame =
vpx_video_reader_get_frame(reader, &frame_size);
if (vpx_codec_decode(&codec, frame, (unsigned int)frame_size, NULL, 0))
die_codec(&codec, "Failed to decode frame.");
++frame_cnt;
skip = (is_range && frame_cnt >= n && frame_cnt <= m) ||
(!is_range && m - (frame_cnt - 1) % m <= n);
if (!skip) {
putc('.', stdout);
while ((img = vpx_codec_get_frame(&codec, &iter)) != NULL)
vpx_img_write(img, outfile);
} else {
putc('X', stdout);
}
fflush(stdout);
}
printf("Processed %d frames.\n", frame_cnt);
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec.");
printf("Play: ffplay -f rawvideo -pix_fmt yuv420p -s %dx%d %s\n",
info->frame_width, info->frame_height, argv[2]);
vpx_video_reader_close(reader);
fclose(outfile);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,73 @@
@TEMPLATE decoder_tmpl.c
Decode With Drops Example
=========================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This is an example utility which drops a series of frames, as specified
on the command line. This is useful for observing the error recovery
features of the codec.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
Usage
-----
This example adds a single argument to the `simple_decoder` example,
which specifies the range or pattern of frames to drop. The parameter is
parsed as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
if(argc!=4)
die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]);
{
char *nptr;
n = strtol(argv[3], &nptr, 0);
m = strtol(nptr+1, NULL, 0);
is_range = *nptr == '-';
if(!n || !m || (*nptr != '-' && *nptr != '/'))
die("Couldn't parse pattern %s\n", argv[3]);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
Dropping A Range Of Frames
--------------------------
To drop a range of frames, specify the starting frame and the ending
frame to drop, separated by a dash. The following command will drop
frames 5 through 10 (base 1).
$ ./decode_with_drops in.ivf out.i420 5-10
Dropping A Pattern Of Frames
----------------------------
To drop a pattern of frames, specify the number of frames to drop and
the number of frames after which to repeat the pattern, separated by
a forward-slash. The following command will drop 3 of 7 frames.
Specifically, it will decode 4 frames, then drop 3 frames, and then
repeat.
$ ./decode_with_drops in.ivf out.i420 3/7
Extra Variables
---------------
This example maintains the pattern passed on the command line in the
`n`, `m`, and `is_range` variables:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
int n, m, is_range;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
Making The Drop Decision
------------------------
The example decides whether to drop the frame based on the current
frame number, immediately before decoding the frame.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
if((is_range && frame_cnt >= n && frame_cnt <= m)
||(!is_range && m - (frame_cnt-1)%m <= n)) {
putc('X', stdout);
continue;
}
putc('.', stdout);
fflush(stdout);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE

View File

@ -0,0 +1,238 @@
@TEMPLATE decoder_tmpl.c
Decode With Partial Drops Example
=========================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This is an example utility which drops a series of frames (or parts of frames),
as specified on the command line. This is useful for observing the error
recovery features of the codec.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
#include <time.h>
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
struct parsed_header
{
char key_frame;
int version;
char show_frame;
int first_part_size;
};
int next_packet(struct parsed_header* hdr, int pos, int length, int mtu)
{
int size = 0;
int remaining = length - pos;
/* Uncompressed part is 3 bytes for P frames and 10 bytes for I frames */
int uncomp_part_size = (hdr->key_frame ? 10 : 3);
/* number of bytes yet to send from header and the first partition */
int remainFirst = uncomp_part_size + hdr->first_part_size - pos;
if (remainFirst > 0)
{
if (remainFirst <= mtu)
{
size = remainFirst;
}
else
{
size = mtu;
}
return size;
}
/* second partition; just slot it up according to MTU */
if (remaining <= mtu)
{
size = remaining;
return size;
}
return mtu;
}
void throw_packets(unsigned char* frame, int* size, int loss_rate,
int* thrown, int* kept)
{
unsigned char loss_frame[256*1024];
int pkg_size = 1;
int pos = 0;
int loss_pos = 0;
struct parsed_header hdr;
unsigned int tmp;
int mtu = 1500;
if (*size < 3)
{
return;
}
putc('|', stdout);
/* parse uncompressed 3 bytes */
tmp = (frame[2] << 16) | (frame[1] << 8) | frame[0];
hdr.key_frame = !(tmp & 0x1); /* inverse logic */
hdr.version = (tmp >> 1) & 0x7;
hdr.show_frame = (tmp >> 4) & 0x1;
hdr.first_part_size = (tmp >> 5) & 0x7FFFF;
/* don't drop key frames */
if (hdr.key_frame)
{
int i;
*kept = *size/mtu + ((*size % mtu > 0) ? 1 : 0); /* approximate */
for (i=0; i < *kept; i++)
putc('.', stdout);
return;
}
while ((pkg_size = next_packet(&hdr, pos, *size, mtu)) > 0)
{
int loss_event = ((rand() + 1.0)/(RAND_MAX + 1.0) < loss_rate/100.0);
if (*thrown == 0 && !loss_event)
{
memcpy(loss_frame + loss_pos, frame + pos, pkg_size);
loss_pos += pkg_size;
(*kept)++;
putc('.', stdout);
}
else
{
(*thrown)++;
putc('X', stdout);
}
pos += pkg_size;
}
memcpy(frame, loss_frame, loss_pos);
memset(frame + loss_pos, 0, *size - loss_pos);
*size = loss_pos;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ HELPERS
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
/* Initialize codec */
flags = VPX_CODEC_USE_ERROR_CONCEALMENT;
res = vpx_codec_dec_init(&codec, interface, &dec_cfg, flags);
if(res)
die_codec(&codec, "Failed to initialize decoder");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
Usage
-----
This example adds a single argument to the `simple_decoder` example,
which specifies the range or pattern of frames to drop. The parameter is
parsed as follows:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
if(argc < 4 || argc > 6)
die("Usage: %s <infile> <outfile> [-t <num threads>] <N-M|N/M|L,S>\n",
argv[0]);
{
char *nptr;
int arg_num = 3;
if (argc == 6 && strncmp(argv[arg_num++], "-t", 2) == 0)
dec_cfg.threads = strtol(argv[arg_num++], NULL, 0);
n = strtol(argv[arg_num], &nptr, 0);
mode = (*nptr == '\0' || *nptr == ',') ? 2 : (*nptr == '-') ? 1 : 0;
m = strtol(nptr+1, NULL, 0);
if((!n && !m) || (*nptr != '-' && *nptr != '/' &&
*nptr != '\0' && *nptr != ','))
die("Couldn't parse pattern %s\n", argv[3]);
}
seed = (m > 0) ? m : (unsigned int)time(NULL);
srand(seed);thrown_frame = 0;
printf("Seed: %u\n", seed);
printf("Threads: %d\n", dec_cfg.threads);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
Dropping A Range Of Frames
--------------------------
To drop a range of frames, specify the starting frame and the ending
frame to drop, separated by a dash. The following command will drop
frames 5 through 10 (base 1).
$ ./decode_with_partial_drops in.ivf out.i420 5-10
Dropping A Pattern Of Frames
----------------------------
To drop a pattern of frames, specify the number of frames to drop and
the number of frames after which to repeat the pattern, separated by
a forward-slash. The following command will drop 3 of 7 frames.
Specifically, it will decode 4 frames, then drop 3 frames, and then
repeat.
$ ./decode_with_partial_drops in.ivf out.i420 3/7
Dropping Random Parts Of Frames
-------------------------------
A third argument tuple is available to split the frame into 1500 bytes pieces
and randomly drop pieces rather than frames. The frame will be split at
partition boundaries where possible. The following example will seed the RNG
with the seed 123 and drop approximately 5% of the pieces. Pieces which
are depending on an already dropped piece will also be dropped.
$ ./decode_with_partial_drops in.ivf out.i420 5,123
Extra Variables
---------------
This example maintains the pattern passed on the command line in the
`n`, `m`, and `is_range` variables:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
int n, m, mode;
unsigned int seed;
int thrown=0, kept=0;
int thrown_frame=0, kept_frame=0;
vpx_codec_dec_cfg_t dec_cfg = {0};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
Making The Drop Decision
------------------------
The example decides whether to drop the frame based on the current
frame number, immediately before decoding the frame.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
/* Decide whether to throw parts of the frame or the whole frame
depending on the drop mode */
thrown_frame = 0;
kept_frame = 0;
switch (mode)
{
case 0:
if (m - (frame_cnt-1)%m <= n)
{
frame_sz = 0;
}
break;
case 1:
if (frame_cnt >= n && frame_cnt <= m)
{
frame_sz = 0;
}
break;
case 2:
throw_packets(frame, &frame_sz, n, &thrown_frame, &kept_frame);
break;
default: break;
}
if (mode < 2)
{
if (frame_sz == 0)
{
putc('X', stdout);
thrown_frame++;
}
else
{
putc('.', stdout);
kept_frame++;
}
}
thrown += thrown_frame;
kept += kept_frame;
fflush(stdout);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE

103
examples/decoder_tmpl.c Normal file
View File

@ -0,0 +1,103 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
@*INTRODUCTION
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h"
#define interface (vpx_codec_vp8_dx())
@EXTRA_INCLUDES
#define IVF_FILE_HDR_SZ (32)
#define IVF_FRAME_HDR_SZ (12)
static unsigned int mem_get_le32(const unsigned char *mem) {
return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
}
static void die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
if(fmt[strlen(fmt)-1] != '\n')
printf("\n");
exit(EXIT_FAILURE);
}
@DIE_CODEC
@HELPERS
int main(int argc, char **argv) {
FILE *infile, *outfile;
vpx_codec_ctx_t codec;
int flags = 0, frame_cnt = 0;
unsigned char file_hdr[IVF_FILE_HDR_SZ];
unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
unsigned char frame[256*1024];
vpx_codec_err_t res;
@@@@EXTRA_VARS
(void)res;
/* Open files */
@@@@USAGE
if(!(infile = fopen(argv[1], "rb")))
die("Failed to open %s for reading", argv[1]);
if(!(outfile = fopen(argv[2], "wb")))
die("Failed to open %s for writing", argv[2]);
/* Read file header */
if(!(fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile) == IVF_FILE_HDR_SZ
&& file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
&& file_hdr[3]=='F'))
die("%s is not an IVF file.", argv[1]);
printf("Using %s\n",vpx_codec_iface_name(interface));
@@@@DEC_INIT
/* Read each frame */
while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
int frame_sz = mem_get_le32(frame_hdr);
vpx_codec_iter_t iter = NULL;
vpx_image_t *img;
frame_cnt++;
if(frame_sz > sizeof(frame))
die("Frame %d data too big for example code buffer", frame_sz);
if(fread(frame, 1, frame_sz, infile) != frame_sz)
die("Frame %d failed to read complete frame", frame_cnt);
@@@@@@@@PRE_DECODE
@@@@@@@@DECODE
/* Write decoded data to disk */
@@@@@@@@GET_FRAME
unsigned int plane, y;
@@@@@@@@@@@@PROCESS_DX
}
}
printf("Processed %d frames.\n",frame_cnt);
@@@@DESTROY
fclose(outfile);
fclose(infile);
return EXIT_SUCCESS;
}

62
examples/decoder_tmpl.txt Normal file
View File

@ -0,0 +1,62 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_decoder.h"
#include "vpx/vp8dx.h"
#define interface (vpx_codec_vp8_dx())
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
const char *detail = vpx_codec_error_detail(ctx);
printf("%s: %s\n", s, vpx_codec_error(ctx));
if(detail)
printf(" %s\n",detail);
exit(EXIT_FAILURE);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
if(argc!=3)
die("Usage: %s <infile> <outfile>\n", argv[0]);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
/* Initialize codec */
if(vpx_codec_dec_init(&codec, interface, NULL, flags))
die_codec(&codec, "Failed to initialize decoder");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
/* Decode the frame */
if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
die_codec(&codec, "Failed to decode frame");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
while((img = vpx_codec_get_frame(&codec, &iter))) {
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
for(plane=0; plane < 3; plane++) {
unsigned char *buf =img->planes[plane];
for(y=0; y < (plane ? (img->d_h + 1) >> 1 : img->d_h); y++) {
if(fwrite(buf, 1, (plane ? (img->d_w + 1) >> 1 : img->d_w),
outfile));
buf += img->stride[plane];
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
if(vpx_codec_destroy(&codec))
die_codec(&codec, "Failed to destroy codec");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY

186
examples/encoder_tmpl.c Normal file
View File

@ -0,0 +1,186 @@
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
/*
@*INTRODUCTION
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_encoder.h"
#include "vpx/vp8cx.h"
#define interface (vpx_codec_vp8_cx())
#define fourcc 0x30385056
@EXTRA_INCLUDES
#define IVF_FILE_HDR_SZ (32)
#define IVF_FRAME_HDR_SZ (12)
static void mem_put_le16(char *mem, unsigned int val) {
mem[0] = val;
mem[1] = val>>8;
}
static void mem_put_le32(char *mem, unsigned int val) {
mem[0] = val;
mem[1] = val>>8;
mem[2] = val>>16;
mem[3] = val>>24;
}
static void die(const char *fmt, ...) {
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
if(fmt[strlen(fmt)-1] != '\n')
printf("\n");
exit(EXIT_FAILURE);
}
@DIE_CODEC
static int read_frame(FILE *f, vpx_image_t *img) {
size_t nbytes, to_read;
int res = 1;
to_read = img->w*img->h*3/2;
nbytes = fread(img->planes[0], 1, to_read, f);
if(nbytes != to_read) {
res = 0;
if(nbytes > 0)
printf("Warning: Read partial frame. Check your width & height!\n");
}
return res;
}
static void write_ivf_file_header(FILE *outfile,
const vpx_codec_enc_cfg_t *cfg,
int frame_cnt) {
char header[32];
if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
return;
header[0] = 'D';
header[1] = 'K';
header[2] = 'I';
header[3] = 'F';
mem_put_le16(header+4, 0); /* version */
mem_put_le16(header+6, 32); /* headersize */
mem_put_le32(header+8, fourcc); /* headersize */
mem_put_le16(header+12, cfg->g_w); /* width */
mem_put_le16(header+14, cfg->g_h); /* height */
mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
mem_put_le32(header+24, frame_cnt); /* length */
mem_put_le32(header+28, 0); /* unused */
if(fwrite(header, 1, 32, outfile));
}
static void write_ivf_frame_header(FILE *outfile,
const vpx_codec_cx_pkt_t *pkt)
{
char header[12];
vpx_codec_pts_t pts;
if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
return;
pts = pkt->data.frame.pts;
mem_put_le32(header, pkt->data.frame.sz);
mem_put_le32(header+4, pts&0xFFFFFFFF);
mem_put_le32(header+8, pts >> 32);
if(fwrite(header, 1, 12, outfile));
}
int main(int argc, char **argv) {
FILE *infile, *outfile;
vpx_codec_ctx_t codec;
vpx_codec_enc_cfg_t cfg;
int frame_cnt = 0;
vpx_image_t raw;
vpx_codec_err_t res;
long width;
long height;
int frame_avail;
int got_data;
int flags = 0;
@@@@TWOPASS_VARS
/* Open files */
@@@@USAGE
width = strtol(argv[1], NULL, 0);
height = strtol(argv[2], NULL, 0);
if(width < 16 || width%2 || height <16 || height%2)
die("Invalid resolution: %ldx%ld", width, height);
if(!vpx_img_alloc(&raw, VPX_IMG_FMT_I420, width, height, 1))
die("Faile to allocate image", width, height);
if(!(outfile = fopen(argv[4], "wb")))
die("Failed to open %s for writing", argv[4]);
printf("Using %s\n",vpx_codec_iface_name(interface));
@@@@ENC_DEF_CFG
@@@@ENC_SET_CFG
@@@@ENC_SET_CFG2
write_ivf_file_header(outfile, &cfg, 0);
@@@@TWOPASS_LOOP_BEGIN
/* Open input file for this encoding pass */
if(!(infile = fopen(argv[3], "rb")))
die("Failed to open %s for reading", argv[3]);
@@@@@@@@ENC_INIT
frame_avail = 1;
got_data = 0;
while(frame_avail || got_data) {
vpx_codec_iter_t iter = NULL;
const vpx_codec_cx_pkt_t *pkt;
@@@@@@@@@@@@PER_FRAME_CFG
@@@@@@@@@@@@ENCODE_FRAME
got_data = 0;
while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
got_data = 1;
switch(pkt->kind) {
@@@@@@@@@@@@@@@@PROCESS_FRAME
@@@@@@@@@@@@@@@@PROCESS_STATS
default:
break;
}
printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
&& (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
fflush(stdout);
}
frame_cnt++;
}
printf("\n");
fclose(infile);
@@@@TWOPASS_LOOP_END
printf("Processed %d frames.\n",frame_cnt-1);
@@@@DESTROY
/* Try to rewrite the file header with the actual frame count */
if(!fseek(outfile, 0, SEEK_SET))
write_ivf_file_header(outfile, &cfg, frame_cnt-1);
fclose(outfile);
return EXIT_SUCCESS;
}

73
examples/encoder_tmpl.txt Normal file
View File

@ -0,0 +1,73 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
#define VPX_CODEC_DISABLE_COMPAT 1
#include "vpx/vpx_encoder.h"
#include "vpx/vp8cx.h"
#define interface (vpx_codec_vp8_cx())
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
const char *detail = vpx_codec_error_detail(ctx);
printf("%s: %s\n", s, vpx_codec_error(ctx));
if(detail)
printf(" %s\n",detail);
exit(EXIT_FAILURE);
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
if(argc!=5)
die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
/* Populate encoder configuration */
res = vpx_codec_enc_config_default(interface, &cfg, 0);
if(res) {
printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
return EXIT_FAILURE;
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
/* Update the default configuration with our settings */
cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
/ cfg.g_w / cfg.g_h;
cfg.g_w = width;
cfg.g_h = height;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
/* Initialize codec */
if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
die_codec(&codec, "Failed to initialize encoder");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
frame_avail = read_frame(infile, &raw);
if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
1, flags, VPX_DL_REALTIME))
die_codec(&codec, "Failed to encode frame");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
case VPX_CODEC_CX_FRAME_PKT:
write_ivf_frame_header(outfile, pkt);
if(fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
outfile));
break;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
if(vpx_codec_destroy(&codec))
die_codec(&codec, "Failed to destroy codec");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY

View File

@ -0,0 +1,25 @@
@TEMPLATE encoder_tmpl.c
Error Resiliency Features
=========================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This is an example demonstrating how to enable the error resiliency
features of the codec.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
Configuration
-------------
Error resiliency is controlled by the g_error_resilient member of the
configuration structure.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
/* Enable error resilient mode */
cfg.g_error_resilient = 1;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
Observing The Effects
---------------------
Use the `decode_with_drops` example to decode with frames 5-10 dropped.
Compare the output for a file encoded with this example versus one
encoded with the `simple_encoder` example.

View File

@ -0,0 +1,28 @@
@TEMPLATE encoder_tmpl.c
Forcing A Keyframe
==================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
This is an example demonstrating how to control placement of keyframes
on a frame-by-frame basis.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
Configuration
-------------
Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
flags passed to `vpx_codec_control()`. In this example, we force a
keyframe every 8 frames.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
if(!(frame_cnt & 7))
flags |= VPX_EFLAG_FORCE_KF;
else
flags &= ~VPX_EFLAG_FORCE_KF;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
Observing The Effects
---------------------
The output of the encoder examples shows a 'K' rather than a dot '.'
when the encoder generates a keyframe. Note that every 8 frames a 'K'
is output.

85
examples/gen_example_code.sh Executable file
View File

@ -0,0 +1,85 @@
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
# gen_example_code.sh
self=$0
die_usage() {
echo "Usage: $self <example.txt>"
exit 1
}
die() {
echo "$@"
exit 1
}
include_block() {
show_bar=$1
block_name=${line##*@}
indent=${line%%${block_name}}
indent=${#indent}
[ $indent -eq 1 ] && indent=0
local on_block
while IFS=$'\n' read -r t_line; do
case "$t_line" in
\~*\ ${block_name})
if [ "x$on_block" == "xyes" ]; then
return 0;
else
on_block=yes
fi
;;
@DEFAULT)
if [ "x$on_block" == "xyes" ]; then
include_block $show_bar < "${template%.c}.txt"
return 0
fi
;;
*)
if [ "x$on_block" == "xyes" ]; then
local rem
(( rem = 78 - indent ))
case "$block_name" in
\**) printf "%${indent}s * %s\n" "" "$t_line" ;;
*)
if [ "$show_bar" == "yes" ]; then
printf "%${indent}s%-${rem}s//\n" "" "$t_line"
else
printf "%${indent}s%s\n" "" "$t_line"
fi
;;
esac
fi
esac
done
return 1
}
txt=$1
[ -f "$txt" ] || die_usage
read -r template < "$txt"
case "$template" in
@TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
*) die "Failed to parse template name from '$template'" ;;
esac
while IFS=$'\n' read -r line; do
case "$line" in
@*) include_block yes < "$txt" \
|| include_block < "${template%.c}.txt" \
#|| echo "WARNING: failed to find text for block $block_name" >&2
;;
*) echo "$line" ;;
esac
done < "$template"

224
examples/gen_example_doxy.php Executable file
View File

@ -0,0 +1,224 @@
#!/usr/bin/env php
/*
* Copyright (c) 2010 The WebM project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
<?php
/* This script converts markdown to doxygen htmlonly syntax, nesting the
* content inside a \page. It expects input on stdin and outputs on stdout.
*
* Usage: gen_example_doxy.php <page_identifier> "<page description>"
*/
$geshi_path = dirname($argv[0])."/includes/geshi/geshi/"; // Language files
$tmp_token = '<!-- I wanna rock you, Chaka Khan -->';
// Include prerequisites or exit
if(!include_once('includes/PHP-Markdown-Extra-1.2.3/markdown.php'))
die("Cannot load Markdown transformer.\n");
if(!include_once('includes/PHP-SmartyPants-1.5.1e/smartypants.php'))
die("Cannot load SmartyPants transformer.\n");
if(!include_once('includes/geshi/geshi.php'))
die("Cannot load GeSHi transformer.\n");
// ASCIIMathPHP?
// HTML::Toc?
// Tidy?
// Prince?
/**
* Generate XHTML body
*
*/
$page_body = file_get_contents('php://stdin');
// Transform any MathML expressions in the body text
$regexp = '/\[\[(.*?)\]\]/'; // Double square bracket delimiters
$page_body = preg_replace_callback($regexp, 'ASCIIMathPHPCallback', $page_body);
// Fix ASCIIMathPHP's output
$page_body = fix_asciiMath($page_body);
// Wrap block-style <math> elements in <p>, since Markdown doesn't.
$page_body = preg_replace('/\n(<math.*<\/math>)\n/', '<p class="eq_para">$1</p>', $page_body);
// Transform the body text to HTML
$page_body = Markdown($page_body);
// Preprocess code blocks
// Decode XML entities. GeSHi doesn't anticipate that
// Markdown has already done this.
$regexp = '|<pre><code>(.*?)<\/code><\/pre>|si';
while (preg_match($regexp, $page_body, $matches) > 0)
{
// Replace 1st match with token
$page_body = preg_replace($regexp, $tmp_token, $page_body, 1);
$block_new = $matches[1];
// Un-encode ampersand entities
$block_new = decode_markdown($block_new);
// Replace token with revised string
$page_body = preg_replace("|$tmp_token|", '<div class="codeblock">'.$block_new.'</div>', $page_body);
}
// Run GeSHi over code blocks
$regexp = '|<div class="codeblock">(.*?)<\/div>|si';
$language = 'c';
while (preg_match($regexp, $page_body, $matches))
{
$geshi = new GeSHi($matches[1], $language);
$geshi->set_language_path($geshi_path);
$block_new = $geshi->parse_code();
// Strip annoying final newline
$block_new = preg_replace('|\n&nbsp;<\/pre>|', '</pre>' , $block_new);
// Remove style attribute (TODO: Research this in GeSHi)
$block_new = preg_replace('| style="font-family:monospace;"|', '' , $block_new);
$page_body = preg_replace($regexp, $block_new, $page_body, 1);
unset($geshi); // Clean up
}
unset($block_new); // Clean up
// Apply typographic flourishes
$page_body = SmartyPants($page_body);
/**
* Generate Doxygen Body
*
*/
$page_id=(isset($argv[1]))?$argv[1]:"";
$page_desc=(isset($argv[2]))?$argv[2]:"";
print "/*!\\page ".$page_id." ".$page_desc."\n\\htmlonly\n";
print $page_body;
print "\\endhtmlonly\n*/\n";
// ---------------------------------------------------------
/**
* decode_markdown()
*
* Markdown encodes '&', '<' and '>' in detected code
* blocks, as a convenience. This will restore the
* encoded entities to ordinary characters, since a
* downstream transformer (like GeSHi) may not
* anticipate this.
*
**********************************************************/
function decode_markdown($input)
{
$out = FALSE;
$entities = array ('|&amp;|'
,'|&lt;|'
,'|&gt;|'
);
$characters = array ('&'
,'<'
,'>'
);
$input = preg_replace($entities, $characters, $input);
$out = $input;
return $out;
}
/**
* ASCIIMathML parser
* http://tinyurl.com/ASCIIMathPHP
*
* @PARAM mtch_arr array - Array of ASCIIMath expressions
* as returned by preg_replace_callback([pattern]). First
* dimension is the full matched string (with delimiter);
* 2nd dimension is the undelimited contents (typically
* a capture group).
*
**********************************************************/
function ASCIIMathPHPCallback($mtch_arr)
{
$txt = trim($mtch_arr[1]);
include('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php');
require_once('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php');
static $asciimath;
if (!isset($asciimath)) $asciimath = new ASCIIMathPHP($symbol_arr);
$math_attr_arr = array('displaystyle' => 'true');
$asciimath->setExpr($txt);
$asciimath->genMathML($math_attr_arr);
return($asciimath->getMathML());
}
/**
* fix_asciiMath()
*
* ASCIIMath pretty-prints its output, with linefeeds
* and tabs. Causes unexpected behavior in some renderers.
* This flattens <math> blocks.
*
* @PARAM page_body str - The <body> element of an
* XHTML page to transform.
*
**********************************************************/
function fix_asciiMath($page_body)
{
$out = FALSE;
// Remove linefeeds and whitespace in <math> elements
$tags_bad = array('/(<math.*?>)\n*\s*/'
, '/(<mstyle.*?>)\n*\s*/'
, '/(<\/mstyle>)\n*\s*/'
, '/(<mrow.*?>)\n*\s*/'
, '/(<\/mrow>)\n*\s*/'
, '/(<mo.*?>)\n*\s*/'
, '/(<\/mo>)\n*\s*/'
, '/(<mi.*?>)\n*\s*/'
, '/(<\/mi>)\n*\s*/'
, '/(<mn.*?>)\n*\s*/'
, '/(<\/mn>)\n*\s*/'
, '/(<mtext.*?>)\n*\s*/'
, '/(<\/mtext>)\n*\s*/'
, '/(<msqrt.*?>)\n*\s*/'
, '/(<\/msqrt>)\n*\s*/'
, '/(<mfrac.*?>)\n*\s*/'
, '/(<\/mfrac>)\n*\s*/'
);
$tags_good = array( '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
, '$1'
);
$out = preg_replace($tags_bad, $tags_good, $page_body);
return $out;
}

84
examples/gen_example_text.sh Executable file
View File

@ -0,0 +1,84 @@
#!/bin/bash
##
## Copyright (c) 2010 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
# gen_example_text.sh
self=$0
die_usage() {
echo "Usage: $self <example.txt>"
exit 1
}
die() {
echo "$@"
exit 1
}
include_block() {
local on_block
while IFS=$'\n' read -r t_line; do
case "$t_line" in
\~*\ ${block_name})
if [ "x$on_block" == "xyes" ]; then
return 0;
else
on_block=yes
fi
;;
*)
if [ "x$on_block" == "xyes" ]; then
echo "$t_line"
fi
;;
esac
done
echo "WARNING: failed to find text for block $block_name" >&2
return 1
}
txt=$1
[ -f "$txt" ] || die_usage
read -r template < "$txt"
case "$template" in
@TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
*) die "Failed to parse template name from '$template'" ;;
esac
fence="~~~~~~~~~"
fence="${fence}${fence}"
fence="${fence}${fence}"
fence="${fence}${fence}"
while IFS=$'\n' read -r line; do
case "$line" in
@TEMPLATE*)
template=${template##@TEMPLATE }
template=${template%.c}.txt
;;
@DEFAULT)
include_block < "$template"
;;
~~~*)
block_name=${line##~* }
[ "$block_name" == "INTRODUCTION" ] || echo "$fence"
;;
*) echo "$line"
;;
esac
done < "$txt"
echo
echo "Putting It All Together"
echo "======================="
echo "${fence}"
${self%/*}/gen_example_code.sh "${txt}"
echo "${fence}"

View File

@ -0,0 +1,218 @@
<?php
$symbol_arr = array(
// Greek symbols
'alpha' => array( 'input'=>'alpha','tag'=>'mi', 'output'=>'&#' . hexdec('03B1') . ';'),
'beta' => array( 'input'=>'beta','tag'=>'mi', 'output'=>'&#' . hexdec('03B2') . ';'),
'chi' => array( 'input'=>'chi','tag'=>'mi', 'output'=>'&#' . hexdec('03C7') . ';'),
'delta' => array( 'input'=>'delta','tag'=>'mi', 'output'=>'&#' . hexdec('03B4') . ';'),
'Delta' => array( 'input'=>'Delta','tag'=>'mo', 'output'=>'&#' . hexdec('0394') . ';'),
'epsi' => array( 'input'=>'epsi','tag'=>'mi', 'output'=>'&#' . hexdec('03B5') . ';'),
'varepsilon' => array( 'input'=>'varepsilon','tag'=>'mi', 'output'=>'&#' . hexdec('025B') . ';'),
'eta' => array( 'input'=>'eta','tag'=>'mi', 'output'=>'&#' . hexdec('03B7') . ';'),
'gamma' => array( 'input'=>'gamma','tag'=>'mi', 'output'=>'&#' . hexdec('03B3') . ';'),
'Gamma' => array( 'input'=>'Gamma','tag'=>'mi', 'output'=>'&#' . hexdec('0393') . ';'),
'iota' => array( 'input'=>'iota','tag'=>'mi', 'output'=>'&#' . hexdec('03B9') . ';'),
'kappa' => array( 'input'=>'kappa','tag'=>'mi', 'output'=>'&#' . hexdec('03BA') . ';'),
'lambda' => array( 'input'=>'lambda','tag'=>'mi', 'output'=>'&#' . hexdec('03BB') . ';'),
'Lambda' => array( 'input'=>'Lambda','tag'=>'mo', 'output'=>'&#' . hexdec('039B') . ';'),
'mu' => array( 'input'=>'mu','tag'=>'mi', 'output'=>'&#' . hexdec('03BC') . ';'),
'nu' => array( 'input'=>'nu','tag'=>'mi', 'output'=>'&#' . hexdec('03BD') . ';'),
'omega' => array( 'input'=>'omega','tag'=>'mi', 'output'=>'&#' . hexdec('03C9') . ';'),
'Omega' => array( 'input'=>'Omega','tag'=>'mo', 'output'=>'&#' . hexdec('03A9') . ';'),
'phi' => array( 'input'=>'phi','tag'=>'mi', 'output'=>'&#' . hexdec('03C6') . ';'),
'varphi' => array( 'input'=>'varphi','tag'=>'mi', 'output'=>'&#' . hexdec('03D5') . ';'),
'Phi' => array( 'input'=>'Phi','tag'=>'mo', 'output'=>'&#' . hexdec('03A6') . ';'),
'pi' => array( 'input'=>'pi','tag'=>'mi', 'output'=>'&#' . hexdec('03C0') . ';'),
'Pi' => array( 'input'=>'Pi','tag'=>'mo', 'output'=>'&#' . hexdec('03A0') . ';'),
'psi' => array( 'input'=>'psi','tag'=>'mi', 'output'=>'&#' . hexdec('03C8') . ';'),
'rho' => array( 'input'=>'rho','tag'=>'mi', 'output'=>'&#' . hexdec('03C1') . ';'),
'sigma' => array( 'input'=>'sigma','tag'=>'mi', 'output'=>'&#' . hexdec('03C3') . ';'),
'Sigma' => array( 'input'=>'Sigma','tag'=>'mo', 'output'=>'&#' . hexdec('03A3') . ';'),
'tau' => array( 'input'=>'tau','tag'=>'mi', 'output'=>'&#' . hexdec('03C4') . ';'),
'theta' => array( 'input'=>'theta','tag'=>'mi', 'output'=>'&#' . hexdec('03B8') . ';'),
'vartheta' => array( 'input'=>'vartheta','tag'=>'mi', 'output'=>'&#' . hexdec('03D1') . ';'),
'Theta' => array( 'input'=>'Theta','tag'=>'mo', 'output'=>'&#' . hexdec('0398') . ';'),
'upsilon' => array( 'input'=>'upsilon','tag'=>'mi', 'output'=>'&#' . hexdec('03C5') . ';'),
'xi' => array( 'input'=>'xi','tag'=>'mi', 'output'=>'&#' . hexdec('03BE') . ';'),
'Xi' => array( 'input'=>'alpha','tag'=>'mo', 'output'=>'&#' . hexdec('039E') . ';'),
'zeta' => array( 'input'=>'zeta','tag'=>'mi', 'output'=>'&#' . hexdec('03B6') . ';'),
// Binary operation symbols
'*' => array( 'input'=>'*','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';'),
'**' => array( 'input'=>'**','tag'=>'mo', 'output'=>'&#' . hexdec('22C6') . ';'),
'//' => array( 'input'=>'//','tag'=>'mo', 'output'=>'/'),
'\\\\' => array( 'input'=>'\\\\','tag'=>'mo', 'output'=>'\\'),
'xx' => array( 'input'=>'xx','tag'=>'mo', 'output'=>'&#' . hexdec('00D7') . ';'),
'-:' => array( 'input'=>'-:','tag'=>'mo', 'output'=>'&#' . hexdec('00F7') . ';'),
'@' => array( 'input'=>'@','tag'=>'mo', 'output'=>'&#' . hexdec('2218') . ';'),
'o+' => array( 'input'=>'o+','tag'=>'mo', 'output'=>'&#' . hexdec('2295') . ';'),
'ox' => array( 'input'=>'ox','tag'=>'mo', 'output'=>'&#' . hexdec('2297') . ';'),
'sum' => array( 'input'=>'sum','tag'=>'mo', 'output'=>'&#' . hexdec('2211') . ';', 'underover'=>TRUE),
'prod' => array( 'input'=>'prod','tag'=>'mo', 'output'=>'&#' . hexdec('220F') . ';', 'underover'=>TRUE),
'^^' => array( 'input'=>'^^','tag'=>'mo', 'output'=>'&#' . hexdec('2227') . ';'),
'^^^' => array( 'input'=>'^^^','tag'=>'mo', 'output'=>'&#' . hexdec('22C0') . ';', 'underover'=>TRUE),
'vv' => array( 'input'=>'vv','tag'=>'mo', 'output'=>'&#' . hexdec('2228') . ';'),
'vvv' => array( 'input'=>'vvv','tag'=>'mo', 'output'=>'&#' . hexdec('22C1') . ';', 'underover'=>TRUE),
'nn' => array( 'input'=>'nn','tag'=>'mo', 'output'=>'&#' . hexdec('2229') . ';'),
'nnn' => array( 'input'=>'nnn','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';', 'underover'=>TRUE),
'uu' => array( 'input'=>'uu','tag'=>'mo', 'output'=>'&#' . hexdec('222A') . ';'),
'uuu' => array( 'input'=>'uuu','tag'=>'mo', 'output'=>'&#' . hexdec('22C3') . ';', 'underover'=>TRUE),
// Binary relation symbols
'!=' => array( 'input'=>'!=','tag'=>'mo', 'output'=>'&#' . hexdec('2260') . ';'),
':=' => array( 'input'=>':=','tag'=>'mo', 'output'=>':=' ), /* 2005-06-05 wes */
'<' => array( 'input'=>'<','tag'=>'mo', 'output'=>'&lt;'),
'lt' => array( 'input'=>'lt','tag'=>'mo', 'output'=>'&lt;'), /* 2005-06-05 wes */
'<=' => array( 'input'=>'<=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
'lt=' => array( 'input'=>'lt=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
'le' => array( 'input'=>'le','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'), /* 2005-06-05 wes */
'>' => array( 'input'=>'>','tag'=>'mo', 'output'=>'&gt;'),
'>=' => array( 'input'=>'>=','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
'qeq' => array( 'input'=>'geq','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
'-<' => array( 'input'=>'-<','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
'-lt' => array( 'input'=>'-lt','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
'>-' => array( 'input'=>'>-','tag'=>'mo', 'output'=>'&#' . hexdec('227B') . ';'),
'in' => array( 'input'=>'in','tag'=>'mo', 'output'=>'&#' . hexdec('2208') . ';'),
'!in' => array( 'input'=>'!in','tag'=>'mo', 'output'=>'&#' . hexdec('2209') . ';'),
'sub' => array( 'input'=>'sub','tag'=>'mo', 'output'=>'&#' . hexdec('2282') . ';'),
'sup' => array( 'input'=>'sup','tag'=>'mo', 'output'=>'&#' . hexdec('2283') . ';'),
'sube' => array( 'input'=>'sube','tag'=>'mo', 'output'=>'&#' . hexdec('2286') . ';'),
'supe' => array( 'input'=>'supe','tag'=>'mo', 'output'=>'&#' . hexdec('2287') . ';'),
'-=' => array( 'input'=>'-=','tag'=>'mo', 'output'=>'&#' . hexdec('2261') . ';'),
'~=' => array( 'input'=>'~=','tag'=>'mo', 'output'=>'&#' . hexdec('2245') . ';'),
'~~' => array( 'input'=>'~~','tag'=>'mo', 'output'=>'&#' . hexdec('2248') . ';'),
'prop' => array( 'input'=>'prop','tag'=>'mo', 'output'=>'&#' . hexdec('221D') . ';'),
// Logical symbols
'and' => array( 'input'=>'and','tag'=>'mtext', 'output'=>'and', 'space'=>'1ex'),
'or' => array( 'input'=>'or','tag'=>'mtext', 'output'=>'or', 'space'=>'1ex'),
'not' => array( 'input'=>'not','tag'=>'mo', 'output'=>'&#' . hexdec('00AC') . ';'),
'=>' => array( 'input'=>'=>','tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
'if' => array( 'input'=>'if','tag'=>'mo', 'output'=>'if', 'space'=>'1ex'),
'iff' => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
'<=>' => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'), /* 2005-06-07 wes */
'AA' => array( 'input'=>'AA','tag'=>'mo', 'output'=>'&#' . hexdec('2200') . ';'),
'EE' => array( 'input'=>'EE','tag'=>'mo', 'output'=>'&#' . hexdec('2203') . ';'),
'_|_' => array( 'input'=>'_|_','tag'=>'mo', 'output'=>'&#' . hexdec('22A5') . ';'),
'TT' => array( 'input'=>'TT','tag'=>'mo', 'output'=>'&#' . hexdec('22A4') . ';'),
'|-' => array( 'input'=>'|-','tag'=>'mo', 'output'=>'&#' . hexdec('22A2') . ';'),
'|=' => array( 'input'=>'|=','tag'=>'mo', 'output'=>'&#' . hexdec('22A8') . ';'),
// Miscellaneous symbols
'ang' => array('input'=>'ang','tag'=>'mo','output'=>'&#' . hexdec('2220') . ';'),
'deg' => array('input'=>'deg','tag'=>'mo','output'=>'&#' . hexdec('00B0') . ';'),
'int' => array( 'input'=>'int','tag'=>'mo', 'output'=>'&#' . hexdec('222B') . ';'),
'dx' => array( 'input'=>'dx','tag'=>'mi', 'output'=>'{:d x:}', 'definition'=>TRUE), /* 2005-06-11 wes */
'dy' => array( 'input'=>'dy','tag'=>'mi', 'output'=>'{:d y:}', 'definition'=>TRUE), /* 2005-06-11 wes */
'dz' => array( 'input'=>'dz','tag'=>'mi', 'output'=>'{:d z:}', 'definition'=>TRUE), /* 2005-06-11 wes */
'dt' => array( 'input'=>'dt','tag'=>'mi', 'output'=>'{:d t:}', 'definition'=>TRUE), /* 2005-06-11 wes */
'oint' => array( 'input'=>'oint','tag'=>'mo', 'output'=>'&#' . hexdec('222E') . ';'),
'del' => array( 'input'=>'del','tag'=>'mo', 'output'=>'&#' . hexdec('2202') . ';'),
'grad' => array( 'input'=>'grad','tag'=>'mo', 'output'=>'&#' . hexdec('2207') . ';'),
'+-' => array( 'input'=>'+-','tag'=>'mo', 'output'=>'&#' . hexdec('00B1') . ';'),
'O/' => array( 'input'=>'0/','tag'=>'mo', 'output'=>'&#' . hexdec('2205') . ';'),
'oo' => array( 'input'=>'oo','tag'=>'mo', 'output'=>'&#' . hexdec('221E') . ';'),
'aleph' => array( 'input'=>'aleph','tag'=>'mo', 'output'=>'&#' . hexdec('2135') . ';'),
'...' => array( 'input'=>'int','tag'=>'mo', 'output'=>'...'),
'~' => array( 'input'=>'!~','tag'=>'mo', 'output'=>'&#' . hexdec('0020') . ';'),
'\\ ' => array( 'input'=>'~','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';'),
'quad' => array( 'input'=>'quad','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
'qquad' => array( 'input'=>'qquad','tag'=>'mo', 'output'=> '&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
'cdots' => array( 'input'=>'cdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EF') . ';'),
'vdots' => array( 'input'=>'vdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EE') . ';'), /* 2005-06-11 wes */
'ddots' => array( 'input'=>'ddots','tag'=>'mo', 'output'=>'&#' . hexdec('22F1') . ';'), /* 2005-06-11 wes */
'diamond' => array( 'input'=>'diamond','tag'=>'mo', 'output'=>'&#' . hexdec('22C4') . ';'),
'square' => array( 'input'=>'square','tag'=>'mo', 'output'=>'&#' . hexdec('25A1') . ';'),
'|_' => array( 'input'=>'|_','tag'=>'mo', 'output'=>'&#' . hexdec('230A') . ';'),
'_|' => array( 'input'=>'_|','tag'=>'mo', 'output'=>'&#' . hexdec('230B') . ';'),
'|~' => array( 'input'=>'|~','tag'=>'mo', 'output'=>'&#' . hexdec('2308') . ';'),
'~|' => array( 'input'=>'~|','tag'=>'mo', 'output'=>'&#' . hexdec('2309') . ';'),
'CC' => array( 'input'=>'CC','tag'=>'mo', 'output'=>'&#' . hexdec('2102') . ';'),
'NN' => array( 'input'=>'NN','tag'=>'mo', 'output'=>'&#' . hexdec('2115') . ';'),
'QQ' => array( 'input'=>'QQ','tag'=>'mo', 'output'=>'&#' . hexdec('211A') . ';'),
'RR' => array( 'input'=>'RR','tag'=>'mo', 'output'=>'&#' . hexdec('211D') . ';'),
'ZZ' => array( 'input'=>'ZZ','tag'=>'mo', 'output'=>'&#' . hexdec('2124') . ';'),
// Standard functions
'lim' => array( 'input'=>'lim','tag'=>'mo', 'output'=>'lim', 'underover'=>TRUE),
'Lim' => array( 'input'=>'Lim','tag'=>'mo', 'output'=>'Lim', 'underover'=>TRUE), /* 2005-06-11 wes */
'sin' => array( 'input'=>'sin','tag'=>'mo', 'output'=>'sin', 'unary'=>TRUE, 'func'=>TRUE),
'cos' => array( 'input'=>'cos', 'tag'=>'mo', 'output'=>'cos', 'unary'=>TRUE, 'func'=>TRUE),
'tan' => array( 'input'=>'tan', 'tag'=>'mo', 'output'=>'tan', 'unary'=>TRUE, 'func'=>TRUE),
'arcsin' => array( 'input'=>'arcsin','tag'=>'mo', 'output'=>'arcsin', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
'arccos' => array( 'input'=>'arccos', 'tag'=>'mo', 'output'=>'arccos', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
'arctan' => array( 'input'=>'arctan', 'tag'=>'mo', 'output'=>'arctan', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
'sinh' => array( 'input'=>'sinh','tag'=>'mo', 'output'=>'sinh', 'unary'=>TRUE, 'func'=>TRUE),
'cosh' => array( 'input'=>'cosh', 'tag'=>'mo', 'output'=>'cosh', 'unary'=>TRUE, 'func'=>TRUE),
'tanh' => array( 'input'=>'tanh', 'tag'=>'mo', 'output'=>'tanh', 'unary'=>TRUE, 'func'=>TRUE),
'cot' => array( 'input'=>'cot','tag'=>'mo', 'output'=>'cot', 'unary'=>TRUE, 'func'=>TRUE),
'sec' => array( 'input'=>'sec', 'tag'=>'mo', 'output'=>'sec', 'unary'=>TRUE, 'func'=>TRUE),
'csc' => array( 'input'=>'csc', 'tag'=>'mo', 'output'=>'csc', 'unary'=>TRUE, 'func'=>TRUE),
'coth' => array( 'input'=>'coth','tag'=>'mo', 'output'=>'coth', 'unary'=>TRUE, 'func'=>TRUE),
'sech' => array( 'input'=>'sech', 'tag'=>'mo', 'output'=>'sech', 'unary'=>TRUE, 'func'=>TRUE),
'csch' => array( 'input'=>'csch', 'tag'=>'mo', 'output'=>'csch', 'unary'=>TRUE, 'func'=>TRUE),
'log' => array( 'input'=>'log', 'tag'=>'mo', 'output'=>'log', 'unary'=>TRUE, 'func'=>TRUE),
'ln' => array( 'input'=>'ln', 'tag'=>'mo', 'output'=>'ln', 'unary'=>TRUE, 'func'=>TRUE),
'det' => array( 'input'=>'det', 'tag'=>'mo', 'output'=>'det', 'unary'=>TRUE, 'func'=>TRUE),
'dim' => array( 'input'=>'dim', 'tag'=>'mo', 'output'=>'dim'),
'mod' => array( 'input'=>'mod', 'tag'=>'mo', 'output'=>'mod'),
'gcd' => array( 'input'=>'gcd', 'tag'=>'mo', 'output'=>'gcd', 'unary'=>TRUE, 'func'=>TRUE),
'lcm' => array( 'input'=>'lcm', 'tag'=>'mo', 'output'=>'lcm', 'unary'=>TRUE, 'func'=>TRUE),
'lub' => array( 'input'=>'lub', 'tag'=>'mo', 'output'=>'lub'), /* 2005-06-11 wes */
'glb' => array( 'input'=>'glb', 'tag'=>'mo', 'output'=>'glb'), /* 2005-06-11 wes */
'min' => array( 'input'=>'min', 'tag'=>'mo', 'output'=>'min', 'underover'=>TRUE), /* 2005-06-11 wes */
'max' => array( 'input'=>'max', 'tag'=>'mo', 'output'=>'max', 'underover'=>TRUE), /* 2005-06-11 wes */
'f' => array( 'input'=>'f','tag'=>'mi', 'output'=>'f', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
'g' => array( 'input'=>'g', 'tag'=>'mi', 'output'=>'g', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
// Arrows
'uarr' => array( 'input'=>'uarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2191') . ';'),
'darr' => array( 'input'=>'darr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2193') . ';'),
'rarr' => array( 'input'=>'rarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
'->' => array( 'input'=>'->', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
'|->' => array( 'input'=>'|->', 'tag'=>'mo', 'output'=>'&#' . hexdec('21A6') . ';'), /* 2005-06-11 wes */
'larr' => array( 'input'=>'larr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2190') . ';'),
'harr' => array( 'input'=>'harr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2194') . ';'),
'rArr' => array( 'input'=>'rArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
'lArr' => array( 'input'=>'lArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D0') . ';'),
'hArr' => array( 'input'=>'hArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
// Commands with argument
'sqrt' => array( 'input'=>'sqrt', 'tag'=>'msqrt', 'output'=>'sqrt', 'unary'=>TRUE ),
'root' => array( 'input'=>'root', 'tag'=>'mroot', 'output'=>'root', 'binary'=>TRUE ),
'frac' => array( 'input'=>'frac', 'tag'=>'mfrac', 'output'=>'/', 'binary'=>TRUE),
'/' => array( 'input'=>'/', 'tag'=>'mfrac', 'output'=>'/', 'infix'=>TRUE),
'_' => array( 'input'=>'_', 'tag'=>'msub', 'output'=>'_', 'infix'=>TRUE),
'^' => array( 'input'=>'^', 'tag'=>'msup', 'output'=>'^', 'infix'=>TRUE),
'hat' => array( 'input'=>'hat', 'tag'=>'mover', 'output'=>'&#' . hexdec('005E') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
'bar' => array( 'input'=>'bar', 'tag'=>'mover', 'output'=>'&#' . hexdec('00AF') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
'vec' => array( 'input'=>'vec', 'tag'=>'mover', 'output'=>'&#' . hexdec('2192') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
'dot' => array( 'input'=>'dot', 'tag'=>'mover', 'output'=>'.', 'unary'=>TRUE, 'acc'=>TRUE),
'ddot' => array( 'input'=>'ddot', 'tag'=>'mover', 'output'=>'..', 'unary'=>TRUE, 'acc'=>TRUE),
'ul' => array( 'input'=>'ul', 'tag'=>'munder', 'output'=>'&#' . hexdec('0332') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
'avec' => array( 'input'=>'avec', 'tag'=>'munder', 'output'=>'~', 'unary'=>TRUE, 'acc'=>TRUE),
'text' => array( 'input'=>'text', 'tag'=>'mtext', 'output'=>'text', 'unary'=>TRUE),
'mbox' => array( 'input'=>'mbox', 'tag'=>'mtext', 'output'=>'mbox', 'unary'=>TRUE),
'"' => array( 'input'=>'"', 'tag'=>'mtext','output'=>'mbox', 'unary'=>TRUE),
/* 2005-06-05 wes: added stackrel */
'stackrel' => array( 'input'=>'stackrel', 'tag'=>'mover', 'output'=>'stackrel', 'binary'=>TRUE),
// Grouping brackets
'(' => array( 'input'=>'(', 'tag'=>'mo', 'output'=>'(', 'left_bracket'=>TRUE),
')' => array( 'input'=>')', 'tag'=>'mo', 'output'=>')', 'right_bracket'=>TRUE),
'[' => array( 'input'=>'[', 'tag'=>'mo', 'output'=>'[', 'left_bracket'=>TRUE),
']' => array( 'input'=>']', 'tag'=>'mo', 'output'=>']', 'right_bracket'=>TRUE),
'{' => array( 'input'=>'{', 'tag'=>'mo', 'output'=>'{', 'left_bracket'=>TRUE),
'}' => array( 'input'=>'}', 'tag'=>'mo', 'output'=>'}', 'right_bracket'=>TRUE),
'(:' => array( 'input'=>'(:', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE),
':)' => array( 'input'=>':)', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE),
'{:' => array( 'input'=>'{:', 'tag'=>'mo', 'output'=>'{:', 'left_bracket'=>TRUE, 'invisible'=>TRUE),
':}' => array( 'input'=>':}', 'tag'=>'mo', 'output'=>':}', 'right_bracket'=>TRUE ,'invisible'=>TRUE),
'<<' => array( 'input'=>'<<', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE), // 2005-06-07 wes
'>>' => array( 'input'=>'>>', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE) // 2005-06-07 wes
);
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,86 @@
/* March 19, 2004 MathHTML (c) Peter Jipsen http://www.chapman.edu/~jipsen
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
(at http://www.gnu.org/copyleft/gpl.html) for more details.*/
function convertMath(node) {// for Gecko
if (node.nodeType==1) {
var newnode =
document.createElementNS("http://www.w3.org/1998/Math/MathML",
node.nodeName.toLowerCase());
for(var i=0; i < node.attributes.length; i++) {
if (node.attributes[i].nodeName == 'displaystyle') {
newnode.setAttribute(node.attributes[i].nodeName,node.attributes[i].nodeValue);
}
}
for (var i=0; i<node.childNodes.length; i++) {
var st = node.childNodes[i].nodeValue;
if (st==null || st.slice(0,1)!=" " && st.slice(0,1)!="\n")
newnode.appendChild(convertMath(node.childNodes[i]));
}
return newnode;
}
else return node;
}
function convert() {
if (document.createElementNS) {
var mmlnode = document.getElementsByTagName("span");
for (var i=0; i<mmlnode.length; i++) {
var tmp_node = mmlnode[i];
if (tmp_node.className == 'asciimath') {
tmp_node.replaceChild(convertMath(tmp_node.firstChild),tmp_node.firstChild);
/*
for (var j=0;j<tmp_node.childNodes.length;j++) {
if (tmp_node.childNodes[j].nodeType != 3) {
}
}
*/
}
}
} else {
var st,node,newnode;
var mmlnode = document.getElementsByTagName("math");
for (var i=0; i<mmlnode.length; i++) {
var str = "";
node = mmlnode[i];
while (node.nodeName!="/MATH" && node.nextSibling) {
st = node.nodeName.toLowerCase();
if (st=="#text") {
str += node.nodeValue;
} else {
str += (st.slice(0,1)=="/" ? "</m:"+st.slice(1) : "<m:"+st);
if (st.slice(0,1)!="/") {
for(var j=0; j < node.attributes.length; j++) {
if (node.attributes[j].nodeValue!="italic" &&
node.attributes[j].nodeValue!="" &&
node.attributes[j].nodeValue!="inherit" &&
node.attributes[j].nodeValue!=undefined) {
str += " "+node.attributes[j].nodeName+"="+
"\""+node.attributes[j].nodeValue+"\"";
}
}
}
str += ">";
}
node = node.nextSibling;
node.parentNode.removeChild(node.previousSibling);
}
if (str != '') {
str += "</m:math>";
newnode = document.createElement("span");
node.parentNode.replaceChild(newnode,node);
newnode.innerHTML = str;
}
}
}
}

View File

@ -0,0 +1 @@
* -crlf

View File

@ -0,0 +1,26 @@
Revision history for Perl extension HTML::Toc.
2001-09-03 Freddy Vulto <fvu@fvu.myweb.nl>
Release 0.91
- Tested on Cygwin.
- Used Unix file type for source files.
- Updated documentation.
- Prohibited call with undefined parameter to HTML::Parser->parse() from
HTML::_tokenTocEndParser->parse() which caused havoc with version 3.25
of HTML::Parser.
- Specified 'HTML::Parser' as module that needs to be available in order
to use HTML::Toc.
- Added protected method HTML::TocGenerator::_setActiveAnchorName().
This method replaces the incongruous access of
'HTML::TocUpdator::_doDeleteTokens' by HTML::TocGenerator.
HTML::TocUpdator now overrides '_setActiveAnchorName()' to allow
the ancestor call to HTML::TocGenerator only when '_doDeleteTokens'
equals false.
2001-08-09 Freddy Vulto <fvu@fvu.myweb.nl>
Release 0.90
- First release.

View File

@ -0,0 +1,26 @@
Changes
Toc.pod
Toc.pm
TocGenerator.pm
TocInsertor.pm
TocUpdator.pm
Makefile.PL
MANIFEST
t/extend.t
t/format.t
t/generate.t
t/insert.t
t/manualTest.t
t/options.t
t/podExamples.t
t/propagate.t
t/siteMap.t
t/update.t
t/ManualTest/manualTest1.htm
t/SiteMap/index.htm
t/SiteMap/SubDir1/index.htm
t/SiteMap/SubDir1/SubSubDir1/index.htm
t/SiteMap/SubDir2/index.htm
t/SiteMap/SubDir2/SubSubDir1/index.htm
t/SiteMap/SubDir2/SubSubDir2/index.htm
t/SiteMap/SubDir3/index.htm

View File

@ -0,0 +1,8 @@
use ExtUtils::MakeMaker;
WriteMakefile(
'NAME' => 'HTML::Toc',
'VERSION_FROM' => 'Toc.pm',
'PREREQ_PM' => {'HTML::Parser' => 0},
'MAN3PODS' => {},
);

View File

@ -0,0 +1,549 @@
#=== HTML::Toc ================================================================
# function: HTML Table of Contents
package HTML::Toc;
use strict;
BEGIN {
use vars qw($VERSION);
$VERSION = '0.91';
}
use constant FILE_FILTER => '.*';
use constant GROUP_ID_H => 'h';
use constant LEVEL_1 => 1;
use constant NUMBERING_STYLE_DECIMAL => 'decimal';
# Templates
# Anchor templates
use constant TEMPLATE_ANCHOR_NAME => '$groupId."-".$node';
use constant TEMPLATE_ANCHOR_HREF_BEGIN =>
'"<a href=#$anchorName>"';
use constant TEMPLATE_ANCHOR_HREF_BEGIN_FILE =>
'"<a href=$file#$anchorName>"';
use constant TEMPLATE_ANCHOR_HREF_END => '"</a>"';
use constant TEMPLATE_ANCHOR_NAME_BEGIN =>
'"<a name=$anchorName>"';
use constant TEMPLATE_ANCHOR_NAME_END => '"</a>"';
use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN =>
'<!-- #BeginTocAnchorNameBegin -->';
use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN =>
'<!-- #EndTocAnchorNameBegin -->';
use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END =>
'<!-- #BeginTocAnchorNameEnd -->';
use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_END =>
'<!-- #EndTocAnchorNameEnd -->';
use constant TOKEN_UPDATE_BEGIN_NUMBER =>
'<!-- #BeginTocNumber -->';
use constant TOKEN_UPDATE_END_NUMBER =>
'<!-- #EndTocNumber -->';
use constant TOKEN_UPDATE_BEGIN_TOC =>
'<!-- #BeginToc -->';
use constant TOKEN_UPDATE_END_TOC =>
'<!-- #EndToc -->';
use constant TEMPLATE_TOKEN_NUMBER => '"$node &nbsp;"';
# Level templates
use constant TEMPLATE_LEVEL => '"<li>$text\n"';
use constant TEMPLATE_LEVEL_BEGIN => '"<ul>\n"';
use constant TEMPLATE_LEVEL_END => '"</ul>\n"';
END {}
#--- HTML::Toc::new() ---------------------------------------------------------
# function: Constructor
sub new {
# Get arguments
my ($aType) = @_;
# Local variables
my $self;
$self = bless({}, $aType);
# Default to empty 'options' array
$self->{options} = {};
# Empty toc
$self->{_toc} = "";
# Hash reference to array for each groupId, each array element
# referring to the group of the level indicated by the array index.
# For example, with the default 'tokenGroups', '_levelGroups' would
# look like:
#
# {'h'} => [\$group1, \$group2, \$group3, \$group4, \$group5, \$group6];
#
$self->{_levelGroups} = undef;
# Set default options
$self->_setDefaults();
return $self;
} # new()
#--- HTML::Toc::_compareLevels() ----------------------------------------------
# function: Compare levels.
# args: - $aLevel: pointer to level
# - $aGroupLevel
# - $aPreviousLevel
# - $aPreviousGroupLevel
# returns: 0 if new level equals previous level, 1 if new level exceeds
# previous level, -1 if new level is smaller then previous level.
sub _compareLevels {
# Get arguments
my (
$self, $aLevel, $aPreviousLevel, $aGroupLevel, $aPreviousGroupLevel
) = @_;
# Local variables
my ($result);
# Levels equals?
if (
($aLevel == $aPreviousLevel) &&
($aGroupLevel == $aPreviousGroupLevel)
) {
# Yes, levels are equals;
# Indicate so
$result = 0;
}
else {
# No, levels differ;
# Bias to new level being smaller than previous level;
$result = -1;
# Must groups not be nested and do group levels differ?
if (
($self->{options}{'doNestGroup'} == 0) &&
($aGroupLevel != $aPreviousGroupLevel)
) {
# Yes, groups must be kept apart and the group levels differ;
# Level is greater than previous level?
if (
($aLevel > $aPreviousLevel)
) {
# Yes, level is greater than previous level;
# Indicate so
$result = 1;
}
}
else {
# No, group must be nested;
# Level is greater than previous level?
if (
($aLevel > $aPreviousLevel) ||
($aGroupLevel > $aPreviousGroupLevel)
) {
# Yes, level is greater than previous level;
# Indicate so
$result = 1;
}
}
}
# Return value
return $result;
} # _compareLevels()
#--- HTML::TocGenerator::_formatLevelIndent() ---------------------------------
# function: Format indent.
# args: - $aText: text to indent
# - $aLevel: Level.
# - $aGroupLevel: Group level.
# - $aAdd
# - $aGlobalLevel
sub _formatLevelIndent {
# Get arguments
my ($self, $aText, $aAdd, $aGlobalLevel) = @_;
# Local variables
my ($levelIndent, $indent, $nrOfIndents);
# Alias indentation option
$levelIndent = $self->{options}{'levelIndent'}; #=~ s/[0-9]+/&/;
# Calculate number of indents
$nrOfIndents = ($aGlobalLevel + $aAdd) * $levelIndent;
# Assemble indents
$indent = pack("A$nrOfIndents");
# Return value
return $indent . $aText;
} # _formatLevelIndent()
#--- HTML::Toc::_formatToc() --------------------------------------------------
# function: Format ToC.
# args: - aPreviousLevel
# - aPreviousGroupLevel
# - aToc: ToC to format.
# - aHeaderLines
# note: Recursive function this is.
sub _formatToc {
# Get arguments
my (
$self, $aPreviousLevel, $aPreviousGroupLevel, $aToc, $aHeaderLines,
$aGlobalLevel
) = @_;
# Local variables
my ($level, $groupLevel, $line, $groupId, $text, $compareStatus);
my ($anchorName, $globalLevel, $node, $sequenceNr);
LOOP: {
# Lines need processing?
while (scalar(@$aHeaderLines) > 0) {
# Yes, lines need processing;
# Get line
$line = shift @$aHeaderLines;
# Determine levels
($level, $groupLevel, $groupId, $node, $sequenceNr,
$anchorName, $text) = split(
/ /, $line, 7
);
# Must level and group be processed?
if (
($level =~ m/$self->{options}{'levelToToc'}/) &&
($groupId =~ m/$self->{options}{'groupToToc'}/)
) {
# Yes, level must be processed;
# Compare levels
$compareStatus = $self->_compareLevels(
$level, $aPreviousLevel, $groupLevel, $aPreviousGroupLevel
);
COMPARE_LEVELS: {
# Equals?
if ($compareStatus == 0) {
# Yes, levels are equal;
# Format level
$$aToc .= $self->_formatLevelIndent(
ref($self->{_templateLevel}) eq "CODE" ?
&{$self->{_templateLevel}}(
$level, $groupId, $node, $sequenceNr, $text
) :
eval($self->{_templateLevel}),
0, $aGlobalLevel
);
}
# Greater?
if ($compareStatus > 0) {
# Yes, new level is greater than previous level;
# Must level be single-stepped?
if (
$self->{options}{'doSingleStepLevel'} &&
($aPreviousLevel) &&
($level > $aPreviousLevel)
) {
# Yes, level must be single-stepped;
# Make sure, new level is increased one step only
$level = $aPreviousLevel + 1;
}
# Increase global level
$aGlobalLevel++;
# Format begin of level
$$aToc .= $self->_formatLevelIndent(
eval($self->{_templateLevelBegin}), -1, $aGlobalLevel
);
# Process line again
unshift @$aHeaderLines, $line;
# Assemble TOC (recursive) for next level
$self->_formatToc(
$level, $groupLevel, $aToc, $aHeaderLines, $aGlobalLevel
);
# Format end of level
$$aToc .= $self->_formatLevelIndent(
eval($self->{_templateLevelEnd}), -1, $aGlobalLevel
);
# Decrease global level
$aGlobalLevel--;
# Exit loop
last COMPARE_LEVELS;
}
# Smaller?
if ($compareStatus < 0) {
# Yes, new level is smaller than previous level;
# Process line again
unshift @$aHeaderLines, $line;
# End loop
last LOOP;
}
}
}
}
}
} # _formatToc()
#--- HTML::Toc::_parseTokenGroups() -------------------------------------------
# function: Parse token groups
sub _parseTokenGroups {
# Get arguments
my ($self) = @_;
# Local variables
my ($group, $levelGroups, $numberingStyle);
# Clear any previous 'levelGroups'
$self->{_levelGroups} = undef;
# Determine default 'numberingStyle'
$numberingStyle = defined($self->{options}{'numberingStyle'}) ?
$self->{options}{'numberingStyle'} : NUMBERING_STYLE_DECIMAL;
# Loop through groups
foreach $group (@{$self->{options}{'tokenToToc'}}) {
# 'groupId' is specified?
if (! defined($group->{'groupId'})) {
# No, 'groupId' isn't specified;
# Set default groupId
$group->{'groupId'} = GROUP_ID_H;
}
# 'level' is specified?
if (! defined($group->{'level'})) {
# No, 'level' isn't specified;
# Set default level
$group->{'level'} = LEVEL_1;
}
# 'numberingStyle' is specified?
if (! defined($group->{'numberingStyle'})) {
# No, 'numberingStyle' isn't specified;
# Set default numberingStyle
$group->{'numberingStyle'} = $numberingStyle;
}
# Add group to '_levelGroups' variabele
$self->{_levelGroups}{$group->{'groupId'}}[$group->{'level'} - 1] =
$group;
}
} # _parseTokenGroups()
#--- HTML::Toc::_setDefaults() ------------------------------------------------
# function: Set default options.
sub _setDefaults {
# Get arguments
my ($self) = @_;
# Set default options
$self->setOptions(
{
'attributeToExcludeToken' => '-',
'attributeToTocToken' => '@',
'insertionPoint' => 'after <body>',
'levelToToc' => '.*',
'groupToToc' => '.*',
'doNumberToken' => 0,
'doLinkToFile' => 0,
'doLinkToToken' => 1,
'doLinkToId' => 0,
'doSingleStepLevel' => 1,
'linkUri' => '',
'levelIndent' => 3,
'doNestGroup' => 0,
'doUseExistingAnchors' => 1,
'doUseExistingIds' => 1,
'tokenToToc' => [
{
'level' => 1,
'tokenBegin' => '<h1>'
}, {
'level' => 2,
'tokenBegin' => '<h2>'
}, {
'level' => 3,
'tokenBegin' => '<h3>'
}, {
'level' => 4,
'tokenBegin' => '<h4>'
}, {
'level' => 5,
'tokenBegin' => '<h5>'
}, {
'level' => 6,
'tokenBegin' => '<h6>'
}
],
'header' =>
"\n<!-- Table of Contents generated by Perl - HTML::Toc -->\n",
'footer' =>
"\n<!-- End of generated Table of Contents -->\n",
}
);
} # _setDefaults()
#--- HTML::Toc::clear() -------------------------------------------------------
# function: Clear ToC.
sub clear {
# Get arguments
my ($self) = @_;
# Clear ToC
$self->{_toc} = "";
$self->{toc} = "";
$self->{groupIdLevels} = undef;
$self->{levels} = undef;
} # clear()
#--- HTML::Toc::format() ------------------------------------------------------
# function: Format ToC.
# returns: Formatted ToC.
sub format {
# Get arguments
my ($self) = @_;
# Local variables;
my $toc = "";
my @tocLines = split(/\r\n|\n/, $self->{_toc});
# Format table of contents
$self->_formatToc("0", "0", \$toc, \@tocLines, 0);
# Remove last newline
$toc =~ s/\n$//m;
# Add header & footer
$toc = $self->{options}{'header'} . $toc . $self->{options}{'footer'};
# Return value
return $toc;
} # format()
#--- HTML::Toc::parseOptions() ------------------------------------------------
# function: Parse options.
sub parseOptions {
# Get arguments
my ($self) = @_;
# Alias options
my $options = $self->{options};
# Parse token groups
$self->_parseTokenGroups();
# Link ToC to tokens?
if ($self->{options}{'doLinkToToken'}) {
# Yes, link ToC to tokens;
# Determine anchor href template begin
$self->{_templateAnchorHrefBegin} =
defined($options->{'templateAnchorHrefBegin'}) ?
$options->{'templateAnchorHrefBegin'} :
$options->{'doLinkToFile'} ?
TEMPLATE_ANCHOR_HREF_BEGIN_FILE : TEMPLATE_ANCHOR_HREF_BEGIN;
# Determine anchor href template end
$self->{_templateAnchorHrefEnd} =
defined($options->{'templateAnchorHrefEnd'}) ?
$options->{'templateAnchorHrefEnd'} :
TEMPLATE_ANCHOR_HREF_END;
# Determine anchor name template
$self->{_templateAnchorName} =
defined($options->{'templateAnchorName'}) ?
$options->{'templateAnchorName'} :
TEMPLATE_ANCHOR_NAME;
# Determine anchor name template begin
$self->{_templateAnchorNameBegin} =
defined($options->{'templateAnchorNameBegin'}) ?
$options->{'templateAnchorNameBegin'} :
TEMPLATE_ANCHOR_NAME_BEGIN;
# Determine anchor name template end
$self->{_templateAnchorNameEnd} =
defined($options->{'templateAnchorNameEnd'}) ?
$options->{'templateAnchorNameEnd'} :
TEMPLATE_ANCHOR_NAME_END;
}
# Determine token number template
$self->{_templateTokenNumber} =
defined($options->{'templateTokenNumber'}) ?
$options->{'templateTokenNumber'} :
TEMPLATE_TOKEN_NUMBER;
# Determine level template
$self->{_templateLevel} =
defined($options->{'templateLevel'}) ?
$options->{'templateLevel'} :
TEMPLATE_LEVEL;
# Determine level begin template
$self->{_templateLevelBegin} =
defined($options->{'templateLevelBegin'}) ?
$options->{'templateLevelBegin'} :
TEMPLATE_LEVEL_BEGIN;
# Determine level end template
$self->{_templateLevelEnd} =
defined($options->{'templateLevelEnd'}) ?
$options->{'templateLevelEnd'} :
TEMPLATE_LEVEL_END;
# Determine 'anchor name begin' begin update token
$self->{_tokenUpdateBeginOfAnchorNameBegin} =
defined($options->{'tokenUpdateBeginOfAnchorNameBegin'}) ?
$options->{'tokenUpdateBeginOfAnchorNameBegin'} :
TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN;
# Determine 'anchor name begin' end update token
$self->{_tokenUpdateEndOfAnchorNameBegin} =
defined($options->{'tokenUpdateEndOfAnchorNameBegin'}) ?
$options->{'tokenUpdateEndOfAnchorNameBegin'} :
TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN;
# Determine 'anchor name end' begin update token
$self->{_tokenUpdateBeginOfAnchorNameEnd} =
defined($options->{'tokenUpdateBeginOfAnchorNameEnd'}) ?
$options->{'tokenUpdateBeginOfAnchorNameEnd'} :
TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END;
# Determine 'anchor name end' end update token
$self->{_tokenUpdateEndOfAnchorNameEnd} =
defined($options->{'tokenUpdateEndOfAnchorNameEnd'}) ?
$options->{'tokenUpdateEndOfAnchorNameEnd'} :
TOKEN_UPDATE_END_OF_ANCHOR_NAME_END;
# Determine number begin update token
$self->{_tokenUpdateBeginNumber} =
defined($options->{'tokenUpdateBeginNumber'}) ?
$options->{'tokenUpdateBeginNumber'} :
TOKEN_UPDATE_BEGIN_NUMBER;
# Determine number end update token
$self->{_tokenUpdateEndNumber} =
defined($options->{'tokenUpdateEndNumber'}) ?
$options->{'tokenUpdateEndNumber'} :
TOKEN_UPDATE_END_NUMBER;
# Determine toc begin update token
$self->{_tokenUpdateBeginToc} =
defined($options->{'tokenUpdateBeginToc'}) ?
$options->{'tokenUpdateBeginToc'} :
TOKEN_UPDATE_BEGIN_TOC;
# Determine toc end update token
$self->{_tokenUpdateEndToc} =
defined($options->{'tokenUpdateEndToc'}) ?
$options->{'tokenUpdateEndToc'} :
TOKEN_UPDATE_END_TOC;
} # parseOptions()
#--- HTML::Toc::setOptions() --------------------------------------------------
# function: Set options.
# args: - aOptions: Reference to hash containing options.
sub setOptions {
# Get arguments
my ($self, $aOptions) = @_;
# Add options
%{$self->{options}} = (%{$self->{options}}, %$aOptions);
} # setOptions()
1;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,693 @@
#==== HTML::TocUpdator ========================================================
# function: Update 'HTML::Toc' table of contents.
# note: - 'TUT' is an abbreviation of 'Toc Update Token'.
package HTML::TocUpdator;
use strict;
use HTML::TocInsertor;
BEGIN {
use vars qw(@ISA $VERSION);
$VERSION = '0.91';
@ISA = qw(HTML::TocInsertor);
}
use constant TUT_TOKENTYPE_START => 0;
use constant TUT_TOKENTYPE_END => 1;
use constant TUT_TOKENTYPE_TEXT => 2;
use constant TUT_TOKENTYPE_COMMENT => 3;
use constant MODE_DO_NOTHING => 0; # 0b00
use constant MODE_DO_INSERT => 1; # 0b01
use constant MODE_DO_UPDATE => 3; # 0b11
END {}
#--- HTML::TocUpdator::new() --------------------------------------------------
# function: Constructor.
sub new {
# Get arguments
my ($aType) = @_;
my $self = $aType->SUPER::new;
# Bias to not update ToC
$self->{htu__Mode} = MODE_DO_NOTHING;
# Bias to not delete tokens
$self->{_doDeleteTokens} = 0;
# Reset batch variables
#$self->_resetBatchVariables;
$self->{options} = {};
# TODO: Initialize output
return $self;
} # new()
#--- HTML::TocUpdator::_deinitializeUpdatorBatch() --------------------------
# function: Deinitialize updator batch.
# args: - $aTocs: Reference to array of tocs.
sub _deinitializeUpdatorBatch {
# Get arguments
my ($self, $aTocs) = @_;
# Indicate end of ToC updating
$self->{htu__Mode} = MODE_DO_NOTHING;
# Deinitialize insertor batch
$self->_deinitializeInsertorBatch();
} # _deinitializeUpdatorBatch()
#--- HTML::TokenUpdator::_doesHashEqualHash() ---------------------------------
# function: Determines whether hash1 equals hash2.
# args: - $aHash1
# - $aHash2
# returns: True (1) if hash1 equals hash2, 0 if not. For example, with the
# following hashes:
#
# %hash1 = { %hash2 = {
# 'class' => 'header', 'class' => 'header',
# 'id' => 'intro1' 'id' => 'intro2'
# } }
#
# the routine will return 0, cause the hash fields 'id' differ.
# note: Class function.
sub _doesHashEqualHash {
# Get arguments
my ($aHash1, $aHash2) = @_;
# Local variables
my ($key1, $value1, $key2, $value2, $result);
# Bias to success
$result = 1;
# Loop through hash1 while values available
HASH1: while (($key1, $value1) = each %$aHash1) {
# Yes, values are available;
# Value1 differs from value2?
if ($value1 ne $aHash2->{$key1}) {
# Yes, hashes differ;
# Indicate condition fails
$result = 0;
# Reset 'each' iterator which we're going to break
keys %$aHash2;
# Break loop
last HASH1;
}
}
# Return value
return $result;
} # _doesHashEqualHash()
#--- HTML::TokenUpdator::_doesTagExistInArray() -------------------------------
# function: Check whether tag & attributes matches any of the tags & attributes
# in the specified array. The array must consist of elements with
# format:
#
# [$tag, \%attributes]
#
# args: - $aTag: tag to search for
# - $aAttributes: tag attributes to search for
# - $aArray: Array to search in.
# returns: 1 if tag does exist in array, 0 if not.
# note: Class function.
sub _doesTagExistInArray {
# Get arguments
my ($aTag, $aAttributes, $aArray) = @_;
# Local variables
my ($tag, $result);
# Bias to non-existing tag
$result = 0;
# Loop through existing tags
TAG: foreach $tag (@{$aArray}) {
if (defined(@{$tag}[0])) {
# Does tag equals any existing tag?
if ($aTag eq @{$tag}[0]) {
# Yes, tag equals existing tag;
# Do hashes equal?
if (HTML::TocUpdator::_doesHashEqualHash(
$aAttributes, @{$tag}[1]
)) {
# Yes, hashes are the same;
# Indicate tag exists in array
$result = 1;
# Break loop
last TAG;
}
}
}
}
# Return value
return $result;
} # _doesTagExistInArray()
#--- HTML::TocUpdator::_initializeUpdatorBatch() ----------------------------
# function: Initialize insertor batch.
# args: - $aMode: Mode. Can be either MODE_DO_INSERT or MODE_DO_UPDATE
# - $aTocs: Reference to array of tocs.
# - $aOptions: optional options
# note: Updating actually means: deleting the old ToC and inserting a new
# ToC. That's why we're calling 'insertor' methods here.
sub _initializeUpdatorBatch {
# Get arguments
my ($self, $aMode, $aTocs, $aOptions) = @_;
# Initialize insertor batch
$self->_initializeInsertorBatch($aTocs, $aOptions);
# Parse ToC update templates
$self->_parseTocUpdateTokens();
# Indicate start of ToC updating
$self->{htu__Mode} = $aMode;
} # _initializeUpdatorBatch()
#--- HTML::TocUpdator::_parseTocUpdateTokens() --------------------------------
# function: Parse ToC insertion point specifier.
sub _parseTocUpdateTokens {
# Get arguments
my ($self) = @_;
# Local variables
my ($toc, $tokenType, $tokenPreposition, $token);
my ($tocInsertionPoint, $tocInsertionPointTokenAttributes);
# Create parser for update begin tokens
my $tokenUpdateBeginParser = HTML::_TokenUpdateParser->new(
$self->{_tokensUpdateBegin}
);
# Create parser for update end tokens
my $tokenUpdateEndParser = HTML::_TokenUpdateParser->new(
$self->{_tokensUpdateEnd}
);
# Loop through ToCs
foreach $toc (@{$self->{_tocs}}) {
# Parse update tokens
$tokenUpdateBeginParser->parse(
$toc->{_tokenUpdateBeginOfAnchorNameBegin}
);
$tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginOfAnchorNameEnd});
$tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginNumber});
$tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginToc});
$tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameBegin});
$tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameEnd});
$tokenUpdateEndParser->parse($toc->{_tokenUpdateEndNumber});
$tokenUpdateEndParser->parse($toc->{_tokenUpdateEndToc});
}
} # _parseTocUpdateTokens()
#--- HTML::TocUpdator::_resetBatchVariables() ---------------------------------
# function: Reset batch variables
sub _resetBatchVariables {
# Get arguments
my ($self) = @_;
# Call ancestor
$self->SUPER::_resetBatchVariables();
# Arrays containing start, end, comment & text tokens which indicate
# the begin of ToC tokens. The tokens are stored in keys of hashes to
# avoid storing duplicates as an array would.
$self->{_tokensUpdateBegin} = [
[], # ['<start tag>', <attributes>]
{}, # {'<end tag>' => ''}
{}, # {'<text>' => ''}
{} # {'<comment>' => ''}
];
# Arrays containing start, end, comment & text tokens which indicate
# the end of ToC tokens. The tokens are stored in keys of hashes to
# avoid storing duplicates as an array would.
$self->{_tokensUpdateEnd} = [
[], # ['<start tag>', <attributes>]
{}, # {'<end tag>' => ''}
{}, # {'<text>' => ''}
{} # {'<comment>' => ''}
];
} # _resetBatchVariables()
#--- HTML::TocUpdator::_setActiveAnchorName() ---------------------------------
# function: Set active anchor name.
# args: - aAnchorName: Name of anchor name to set active.
sub _setActiveAnchorName {
# Get arguments
my ($self, $aAnchorName) = @_;
# Are tokens being deleted?
if (! $self->{_doDeleteTokens}) {
# No, tokens aren't being deleted;
# Call ancestor to set anchor name
$self->SUPER::_setActiveAnchorName($aAnchorName);
}
} # _setActiveAnchorName()
#--- HTML::TocUpdator::_update() ----------------------------------------------
# function: Update ToC in string.
# args: - $aMode: Mode. Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
# - $aToc: (reference to array of) ToC object to update
# - $aString: string to update ToC of
# - $aOptions: optional updator options
# note: Used internally.
sub _update {
# Get arguments
my ($self, $aMode, $aToc, $aString, $aOptions) = @_;
# Initialize TocUpdator batch
$self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
# Start updating ToC by starting ToC insertion
$self->_insert($aString);
# Deinitialize TocUpdator batch
$self->_deinitializeUpdatorBatch();
} # update()
#--- HTML::TocUpdator::_updateFile() ------------------------------------------
# function: Update ToCs in file.
# args: - $aMode: Mode. Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
# - $aToc: (reference to array of) ToC object to update
# - $aFile: (reference to array of) file to parse for updating.
# - $aOptions: optional updator options
# note: Used internally.
sub _updateFile {
# Get arguments
my ($self, $aMode, $aToc, $aFile, $aOptions) = @_;
# Initialize TocUpdator batch
$self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
# Start updating ToC by starting ToC insertion
$self->_insertIntoFile($aFile);
# Deinitialize TocUpdator batch
$self->_deinitializeUpdatorBatch();
} # _updateFile()
#--- HTML::TocUpdator::_writeOrBufferOutput() ---------------------------------
# function: Write processed HTML to output device(s).
# args: - aOutput: scalar to write
sub _writeOrBufferOutput {
# Get arguments
my ($self, $aOutput) = @_;
# Delete output?
if (! $self->{_doDeleteTokens}) {
# No, don't delete output;
# Call ancestor
$self->SUPER::_writeOrBufferOutput($aOutput);
}
} # _writeOrBufferOutput()
#--- HTML::TocUpdator::anchorNameBegin() --------------------------------------
# function: Process 'anchor name begin' generated by HTML::Toc.
# args: - $aAnchorName: Anchor name begin tag to output.
# - $aToc: Reference to ToC to which anchorname belongs.
sub anchorNameBegin {
# Get arguments
my ($self, $aAnchorNameBegin, $aToc) = @_;
# Call ancestor
$self->SUPER::anchorNameBegin($aAnchorNameBegin);
# Must ToC be inserted or updated?
if ($self->{htu__Mode} != MODE_DO_NOTHING) {
# Yes, ToC must be inserted or updated;
# Surround anchor name with update tags
$self->{_outputPrefix} =
$aToc->{_tokenUpdateBeginOfAnchorNameBegin} .
$self->{_outputPrefix} .
$aToc->{_tokenUpdateEndOfAnchorNameBegin};
}
} # anchorNameBegin()
#--- HTML::TocUpdator::anchorNameEnd() ----------------------------------------
# function: Process 'anchor name end' generated by HTML::Toc.
# args: - $aAnchorNameEnd: Anchor name end tag to output.
# - $aToc: Reference to ToC to which anchorname belongs.
sub anchorNameEnd {
# Get arguments
my ($self, $aAnchorNameEnd, $aToc) = @_;
# Call ancestor
$self->SUPER::anchorNameEnd($aAnchorNameEnd);
# Must ToC be inserted or updated?
if ($self->{htu__Mode} != MODE_DO_NOTHING) {
# Yes, ToC must be inserted or updated;
# Surround anchor name with update tags
$self->{_outputSuffix} =
$aToc->{_tokenUpdateBeginOfAnchorNameEnd} .
$self->{_outputSuffix} .
$aToc->{_tokenUpdateEndOfAnchorNameEnd};
}
} # anchorNameEnd()
#--- HTML::TocUpdator::comment() ----------------------------------------------
# function: Process comment.
# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
sub comment {
# Get arguments
my ($self, $aComment) = @_;
# Must ToC be updated?
if ($self->{htu__Mode} == MODE_DO_UPDATE) {
# Yes, ToC must be updated;
# Updator is currently deleting tokens?
if ($self->{_doDeleteTokens}) {
# Yes, tokens must be deleted;
# Call ancestor
$self->SUPER::comment($aComment);
# Look for update end token
# Does comment matches update end token?
if (defined(
$self->{_tokensUpdateEnd}[TUT_TOKENTYPE_COMMENT]{$aComment}
)) {
# Yes, comment matches update end token;
# Indicate to stop deleting tokens
$self->{_doDeleteTokens} = 0;
}
}
else {
# No, tokens mustn't be deleted;
# Look for update begin token
# Does comment matches update begin token?
if (defined(
$self->{_tokensUpdateBegin}[TUT_TOKENTYPE_COMMENT]{$aComment}
)) {
# Yes, comment matches update begin token;
# Indicate to start deleting tokens
$self->{_doDeleteTokens} = 1;
}
# Call ancestor
$self->SUPER::comment($aComment);
}
}
else {
# No, ToC mustn't be updated;
# Call ancestor
$self->SUPER::comment($aComment);
}
} # comment()
#--- HTML::TocUpdator::end() --------------------------------------------------
# function: This function is called every time a closing tag is encountered.
# args: - $aTag: tag name (in lower case).
# - $aOrigText: tag name including brackets.
sub end {
# Get arguments
my ($self, $aTag, $aOrigText) = @_;
# Call ancestor
$self->SUPER::end($aTag, $aOrigText);
# Must ToC be updated?
if ($self->{htu__Mode} == MODE_DO_UPDATE) {
# Yes, ToC must be updated;
# Updator is currently deleting tokens?
if ($self->{_doDeleteTokens}) {
# Yes, tokens must be deleted;
# Does end tag matches update end token?
if (defined(
$self->{_tokensUpdateEnd}[TUT_TOKENTYPE_END]{$aTag}
)) {
# Yes, end tag matches update end token;
# Indicate to stop deleting tokens
$self->{_doDeleteTokens} = 0;
}
}
}
} # end()
#--- HTML::TocUpdator::insert() -----------------------------------------------
# function: Insert ToC in string.
# args: - $aToc: (reference to array of) ToC object to update
# - $aString: string to insert ToC in.
# - $aOptions: optional updator options
sub insert {
# Get arguments
my ($self, $aToc, $aString, $aOptions) = @_;
# Do start insert
$self->_update(MODE_DO_INSERT, $aToc, $aString, $aOptions);
} # insert()
#--- HTML::TocUpdator::insertIntoFile() --------------------------------------
# function: Insert ToC in file.
# args: - $aToc: (reference to array of) ToC object to update
# - $aFile: File to insert ToC in.
# - $aOptions: optional updator options
sub insertIntoFile {
# Get arguments
my ($self, $aToc, $aFile, $aOptions) = @_;
# Do start insert
$self->_updateFile(MODE_DO_INSERT, $aToc, $aFile, $aOptions);
} # insertIntoFile()
#--- HTML::TocUpdator::number() -----------------------------------------------
# function: Process heading number generated by HTML::Toc.
# args: - $aNumber
# - $aToc: Reference to ToC to which anchorname belongs.
sub number {
# Get arguments
my ($self, $aNumber, $aToc) = @_;
# Call ancestor
$self->SUPER::number($aNumber);
# Must ToC be inserted or updated?
if ($self->{htu__Mode} != MODE_DO_NOTHING) {
# Yes, ToC must be inserted or updated;
# Surround number with update tags
$self->{_outputSuffix} =
$aToc->{_tokenUpdateBeginNumber} .
$self->{_outputSuffix} .
$aToc->{_tokenUpdateEndNumber};
}
} # number()
#--- HTML::TocUpdator::start() ------------------------------------------------
# function: This function is called every time an opening tag is encountered.
# args: - $aTag: tag name (in lower case).
# - $aAttr: reference to hash containing all tag attributes (in lower
# case).
# - $aAttrSeq: reference to array containing all tag attributes (in
# lower case) in the original order
# - $aOrigText: the original HTML text
sub start {
# Get arguments
my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
# Must ToC be updated?
if ($self->{htu__Mode} == MODE_DO_UPDATE) {
# Yes, ToC must be updated;
# Does start tag matches token update begin tag?
if (HTML::TocUpdator::_doesTagExistInArray(
$aTag, $aAttr, $self->{_tokensUpdateBegin}[TUT_TOKENTYPE_START]
)) {
# Yes, start tag matches token update tag;
# Indicate to delete tokens
$self->{_doDeleteTokens} = 1;
}
}
# Let ancestor process the start tag
$self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText);
} # start()
#--- HTML::TocUpdator::toc() --------------------------------------------------
# function: Toc processing method. Add toc reference to scenario.
# args: - $aScenario: Scenario to add ToC reference to.
# - $aToc: Reference to ToC to insert.
# note: The ToC hasn't been build yet; only a reference to the ToC to be
# build is inserted.
sub toc {
# Get arguments
my ($self, $aScenario, $aToc) = @_;
# Surround toc with update tokens
# Add update begin token
push(@$aScenario, \$aToc->{_tokenUpdateBeginToc});
# Call ancestor
$self->SUPER::toc($aScenario, $aToc);
# Add update end token
push(@$aScenario, \$aToc->{_tokenUpdateEndToc});
} # toc()
#--- HTML::TocUpdator::_processTocText() --------------------------------------
# function: Toc text processing function.
# args: - $aText: Text to add to ToC.
# - $aToc: ToC to add text to.
sub _processTocText {
# Get arguments
my ($self, $aText, $aToc) = @_;
# Delete output?
if (! $self->{_doDeleteTokens}) {
# No, don't delete output;
# Call ancestor
$self->SUPER::_processTocText($aText, $aToc);
}
} # _processTocText()
#--- HTML::TocUpdator::update() -----------------------------------------------
# function: Update ToC in string.
# args: - $aToc: (reference to array of) ToC object to update
# - $aString: string to update ToC of
# - $aOptions: optional updator options
sub update {
# Get arguments
my ($self, $aToc, $aString, $aOptions) = @_;
# Do start update
$self->_update(MODE_DO_UPDATE, $aToc, $aString, $aOptions);
} # update()
#--- HTML::TocUpdator::updateFile() -------------------------------------------
# function: Update ToC of file.
# args: - $aToc: (reference to array of) ToC object to update
# - $aFile: (reference to array of) file to parse for updating.
# - $aOptions: optional updator options
sub updateFile {
# Get arguments
my ($self, $aToc, $aFile, $aOptions) = @_;
# Do start update
$self->_updateFile(MODE_DO_UPDATE, $aToc, $aFile, $aOptions);
} # update()
#=== HTML::_TokenUpdateParser =================================================
# function: Parse 'update tokens'. 'Update tokens' mark HTML code which is
# inserted by 'HTML::TocInsertor'.
# note: Used internally.
package HTML::_TokenUpdateParser;
BEGIN {
use vars qw(@ISA);
@ISA = qw(HTML::Parser);
}
END {}
#--- HTML::_TokenUpdateParser::new() ------------------------------------------
# function: Constructor
sub new {
# Get arguments
my ($aType, $aTokenArray) = @_;
# Create instance
my $self = $aType->SUPER::new;
# Reference token array
$self->{tokens} = $aTokenArray;
# Return instance
return $self;
} # new()
#--- HTML::_TokenUpdateParser::comment() --------------------------------------
# function: Process comment.
# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
sub comment {
# Get arguments
my ($self, $aComment) = @_;
# Add token to array of update tokens
$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_COMMENT]{$aComment} = '';
} # comment()
#--- HTML::_TokenUpdateParser::end() ------------------------------------------
# function: This function is called every time a closing tag is encountered
# by HTML::Parser.
# args: - $aTag: tag name (in lower case).
sub end {
# Get arguments
my ($self, $aTag, $aOrigText) = @_;
# Add token to array of update tokens
$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_END]{$aTag} = '';
} # end()
#--- HTML::_TokenUpdateParser::parse() ----------------------------------------
# function: Parse token.
# args: - $aToken: 'update token' to parse
sub parse {
# Get arguments
my ($self, $aString) = @_;
# Call ancestor
$self->SUPER::parse($aString);
} # parse()
#--- HTML::_TokenUpdateParser::start() ----------------------------------------
# function: This function is called every time an opening tag is encountered.
# args: - $aTag: tag name (in lower case).
# - $aAttr: reference to hash containing all tag attributes (in lower
# case).
# - $aAttrSeq: reference to array containing all tag attributes (in
# lower case) in the original order
# - $aOrigText: the original HTML text
sub start {
# Get arguments
my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
# Does token exist in array?
if (! HTML::TocUpdator::_doesTagExistInArray(
$aTag, $aAttr, $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]
)) {
# No, token doesn't exist in array;
# Add token to array of update tokens
push(
@{$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]},
[$aTag, $aAttr]
);
}
} # start()
#--- HTML::_TokenUpdateParser::text() -----------------------------------------
# function: This function is called every time plain text is encountered.
# args: - @_: array containing data.
sub text {
# Get arguments
my ($self, $aText) = @_;
# Add token to array of update tokens
$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_TEXT]{$aText} = '';
} # text()
1;

View File

@ -0,0 +1,92 @@
<html>
<head>
<title>Manual</title>
<style type="text/css">
ul.toc_appendix1 {
list-style-type: none;
margin-left: 0;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h2 {
list-style-type: none;
}
ul.toc_h3 {
list-style-type: none;
}
ul.toc_part1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_prelude1 {
list-style: none;
}
p.captionFigure {
font-style: italic;
font-weight: bold;
}
p.captionTable {
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<h1 class=prelude>Preface</h1>
Better C than never.
<h1 class=hidden>Table of Contents</h1>
<!-- Table of Contents -->
<h1 class=prelude>Table of Figures</h1>
<!-- Table of Figures -->
<h1 class=prelude>Table of Tables</h1>
<!-- Table of Tables -->
<h1 class=prelude>Introduction</h1>
Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
<p class=captionTable>Compile Steps</p>
<ul><pre>
Parser
Compiler
Linker
</pre></ul>
<h1 class=part>Disks</h1>
<h1>Compiler Disk v1</h1>
<img src=img.gif alt="Contents Compiler Disk v1">
<p class=captionFigure>Contents Compiler Disk v1</p>
<h2>System</h2>
<h2>Standard Library</h2>
<h1>Compiler Disk v2</h1>
<img src=img.gif alt="Contents Compiler Disk v2">
<p class=captionFigure>Contents Compiler Disk v2</p>
<h2>System</h2>
<h3>parser.com</h3>
<h3>compiler.com</h3>
<h3>linker.com</h3>
<h2>Standard Library</h2>
<h1>Library System Disk</h1>
<h1 class=part>Personal</h1>
<h1>Tips & Tricks</h1>
<h1 class=part>Appendixes</h1>
<h1 class=appendix>Functions Standard Library v1</h1>
<h1 class=appendix>Functions Standard Library v2</h1>
<h1 class=appendix>Functions Graphic Library</h1>
<h1 class=prelude>Bibliography</h1>
</body>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>SubSub1</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>Sub1</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>SubSub1</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>SubSub2</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>Sub2</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>Sub3</title>
</head>
</html>

View File

@ -0,0 +1,5 @@
<html>
<head>
<title>Main</title>
</head>
</html>

View File

@ -0,0 +1,87 @@
#--- generate.t ---------------------------------------------------------------
# function: Test ToC generation.
use strict;
use Test;
BEGIN { plan tests => 4; }
use HTML::Toc;
use HTML::TocGenerator;
my ($filename);
my $toc = HTML::Toc->new;
my $tocGenerator = HTML::TocGenerator->new;
$toc->setOptions({
'doLinkToToken' => 0,
'levelIndent' => 0,
'header' => '',
'footer' => '',
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT';
<h1>Header</h1>
EOT
close(FILE);
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. extend ----------------------------------------------------------------
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
# Extend ToC
$tocGenerator->extend($toc, "<h1>Header</h1>");
# Test ToC
ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
#--- 2. extendFromFile --------------------------------------------------------
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Extend ToC
$tocGenerator->extendFromFile($toc, $filename);
# Test ToC
ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
#--- 3. extendFromFiles -------------------------------------------------------
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Extend ToC
$tocGenerator->extendFromFile($toc, [$filename, $filename]);
# Test ToC
ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n<li>Header\n</ul>");
#--- 4. linkTocToToken --------------------------------------------------------
$toc->setOptions({
'doLinkToToken' => 1,
});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
# Extend ToC
$tocGenerator->extend($toc, "<h1>Header</h1>");
# Test ToC
ok($toc->format() . "\n", <<'EOT');
<ul>
<li><a href=#h-1>Header</a>
<li><a href=#h-2>Header</a>
</ul>
EOT

View File

@ -0,0 +1,157 @@
#--- format.t -----------------------------------------------------------------
# function: Test ToC formatting.
use strict;
use Test;
BEGIN { plan tests => 6; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
my ($output, $content, $filename);
my $toc = HTML::Toc->new;
my $tocGenerator = HTML::TocGenerator->new;
my $tocInsertor = HTML::TocInsertor->new;
$toc->setOptions({
'doLinkToToken' => 0,
'levelIndent' => 0,
'insertionPoint' => 'before <h1>',
'header' => '',
'footer' => '',
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<h1>Header</h1>
EOT
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. templateLevelBegin ----------------------------------------------------
$toc->setOptions({
'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"'
});
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok($output, "<ul class=toc_h1>\n<li>Header\n</ul><h1>Header</h1>");
$toc->setOptions({'templateLevelBegin' => undef});
#--- 2. levelToToc -----------------------------------------------------------
$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
$toc->setOptions({'levelToToc' => '1'});
ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
$toc->setOptions({'levelToToc' => '.*'});
#--- 3. groupToToc -----------------------------------------------------------
$toc->setOptions({
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1 class=-foo>'
}, {
'groupId' => 'foo',
'level' => 1,
'tokenBegin' => '<h1 class=foo>'
}]
});
$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h1 class=foo>Foo</h1>");
$toc->setOptions({'groupToToc' => 'foo'});
ok($toc->format(), "<ul>\n<li>Foo\n</ul>");
$toc->setOptions({'groupToToc' => '.*'});
#--- 4. header & footer -------------------------------------------------------
$toc->setOptions({
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1>'
}],
'header' => '<!-- TocHeader -->',
'footer' => '<!-- TocFooter -->',
});
$tocInsertor->insert($toc, "<h1>Header1</h1>", {'output' => \$output});
ok("$output\n", <<EOT);
<!-- TocHeader --><ul>
<li>Header1
</ul><!-- TocFooter --><h1>Header1</h1>
EOT
# Test 'doSingleStepLevel' => 1
TestSingleStepLevel1();
# Test 'doSingleStepLevel' => 0
TestSingleStepLevel0();
#--- 5. TestSingleStepLevel1 --------------------------------------------------
sub TestSingleStepLevel1 {
my $toc = new HTML::Toc;
my $tocGenerator = new HTML::TocGenerator;
# Generate ToC
$tocGenerator->generate($toc, <<EOT);
<h1>Header 1</h1>
<h3>Header 3</h3>
EOT
# Compare output
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Header 1</a>
<ul>
<ul>
<li><a href=#h-1.0.1>Header 3</a>
</ul>
</ul>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestSingleStepLevel1()
#--- 6. TestSingleStepLevel0 --------------------------------------------------
sub TestSingleStepLevel0 {
my $toc = new HTML::Toc;
my $tocGenerator = new HTML::TocGenerator;
# Set ToC options
$toc->setOptions({'doSingleStepLevel' => 0});
# Generate ToC
$tocGenerator->generate($toc, <<EOT);
<h1>Header 1</h1>
<h3>Header 3</h3>
EOT
# Compare output
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Header 1</a>
<ul>
<li><a href=#h-1.0.1>Header 3</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestSingleStepLevel0()

View File

@ -0,0 +1,200 @@
#--- generate.t ---------------------------------------------------------------
# function: Test ToC generation.
use strict;
use Test;
BEGIN { plan tests => 13; }
use HTML::Toc;
use HTML::TocGenerator;
my ($filename);
my $toc = HTML::Toc->new;
my $tocGenerator = HTML::TocGenerator->new;
$toc->setOptions({
'doLinkToToken' => 0,
'levelIndent' => 0,
'header' => '',
'footer' => '',
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT';
<h1>Header</h1>
EOT
close(FILE);
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. generate --------------------------------------------------------------
$tocGenerator->generate($toc, "<h1>Header</h1>");
ok($toc->format(), "<ul>\n<li>Header\n</ul>");
#--- 2. generateFromFile ------------------------------------------------------
$tocGenerator->generateFromFile($toc, $filename);
ok($toc->format(), "<ul>\n<li>Header\n</ul>");
#--- 3. generateFromFiles -----------------------------------------------------
$tocGenerator->generateFromFile($toc, [$filename, $filename]);
ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
#--- 4. doLinkToToken -----------------------------------------------------
$toc->setOptions({'doLinkToToken' => 1});
$tocGenerator->generateFromFile($toc, $filename, {'globalGroups' => 1});
ok($toc->format(), "<ul>\n<li><a href=#h-1>Header</a>\n</ul>");
#--- 5. doLinkToFile -------------------------------------------------------
$toc->setOptions({'doLinkToFile' => 1});
$tocGenerator->generateFromFile($toc, $filename);
ok($toc->format(), "<ul>\n<li><a href=$filename#h-1>Header</a>\n</ul>");
#--- 6. templateAnchorHrefBegin -----------------------------------------------
# Set options
$toc->setOptions({'templateAnchorHrefBegin' => '"test-$file"'});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), "<ul>\n<li>test-".$filename."Header</a>\n</ul>");
# Reset options
$toc->setOptions({'templateAnchorHrefBegin' => undef});
#--- 7. templateAnchorHrefBegin function --------------------------------------
sub AssembleAnchorHrefBegin {
# Get arguments
my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
# Return value
return $aFile . $aGroupId . $aLevel . $aNode;
} # AssembleAnchorHrefBegin()
# Set options
$toc->setOptions({'templateAnchorHrefBegin' => \&AssembleAnchorHrefBegin});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), "<ul>\n<li>".$filename."h11Header</a>\n</ul>");
# Reset options
$toc->setOptions({'templateAnchorHrefBegin' => undef});
#--- 8. levelToToc no levels available ---------------------------------------
$toc->setOptions({'levelToToc' => '2'});
$tocGenerator->generate($toc, "<h1>Header</h1>");
ok($toc->format(), "");
#--- 9. levelToToc level 1 ---------------------------------------------------
# Set options
$toc->setOptions({
'levelToToc' => '1',
'doLinkToToken' => 0,
});
$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
#--- 10. levelToToc level 2 --------------------------------------------------
# Set options
$toc->setOptions({
'levelToToc' => '2',
'doLinkToToken' => 0,
});
$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
ok($toc->format(), "<ul>\n<li>Header2\n</ul>");
# Restore options
$toc->setOptions({
'levelToToc' => '.*',
});
#--- 11. tokenToToc empty array ----------------------------------------------
# Set options
$toc->setOptions({'tokenToToc' => []});
$tocGenerator->generate($toc, "<h1>Header</h1>");
ok($toc->format(), "");
#--- 12. groups nested --------------------------------------------------------
$toc->setOptions({
'doNestGroup' => 1,
'tokenToToc' => [
{
'level' => 1,
'tokenBegin' => '<h1 class=-appendix>'
}, {
'groupId' => 'appendix',
'level' => 1,
'tokenBegin' => '<h1 class=appendix>'
}
]
});
$tocGenerator->generate(
$toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
);
ok($toc->format() . "\n", <<'EOT');
<ul>
<li>Header1
<ul>
<li>Appendix
</ul>
</ul>
EOT
#--- 13. groups not nested ----------------------------------------------------
$toc->setOptions({
'doNestGroup' => 0,
'tokenToToc' => [
{
'level' => 1,
'tokenBegin' => '<h1 class=-appendix>'
}, {
'groupId' => 'appendix',
'level' => 1,
'tokenBegin' => '<h1 class=appendix>'
}
]
});
$tocGenerator->generate(
$toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
);
ok($toc->format() . "\n", <<'EOT');
<ul>
<li>Header1
</ul>
<ul>
<li>Appendix
</ul>
EOT

View File

@ -0,0 +1,336 @@
#--- insert.t -----------------------------------------------------------------
# function: Test ToC insertion.
use strict;
use Test;
BEGIN { plan tests => 10; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
my ($output, $content, $filename);
my $toc = HTML::Toc->new;
my $tocGenerator = HTML::TocGenerator->new;
my $tocInsertor = HTML::TocInsertor->new;
$toc->setOptions({
'doLinkToToken' => 0,
'levelIndent' => 0,
'header' => "",
'footer' => "",
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<h1>Header</h1>
EOT
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. insert before start ---------------------------------------------------
$toc->setOptions({'insertionPoint' => 'before <h1>'});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
$tocInsertor->insert($toc, "<h1>Header</h1>", {
'output' => \$output,
'doGenerateToc' => 0
});
# Test ToC
ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
#--- 2. insert after start ----------------------------------------------------
$toc->setOptions({'insertionPoint' => 'after <h1>'});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
$tocInsertor->insert($toc, "<h1>Header</h1>", {
'output' => \$output,
'doGenerateToc' => 0
});
# Test ToC
ok($output, "<h1><ul>\n<li>Header\n</ul>Header</h1>");
#--- 3. insert before end -----------------------------------------------------
$toc->setOptions({'insertionPoint' => 'before </h1>'});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
$tocInsertor->insert($toc, "<h1>Header</h1>", {
'output' => \$output,
'doGenerateToc' => 0
});
# Test ToC
ok($output, "<h1>Header<ul>\n<li>Header\n</ul></h1>");
#--- 4. insert after end ------------------------------------------------------
$toc->setOptions({'insertionPoint' => 'after </h1>'});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
$tocInsertor->insert($toc, "<h1>Header</h1>", {
'output' => \$output,
'doGenerateToc' => 0
});
# Test ToC
ok($output, "<h1>Header</h1><ul>\n<li>Header\n</ul>");
#--- 5. outputFile ------------------------------------------------------------
$toc->setOptions({'insertionPoint' => 'before <h1>'});
# Generate ToC
$tocGenerator->generate($toc, "<h1>Header</h1>");
# Insert ToC, output to file
$tocInsertor->insert($toc, "<h1>Header</h1>", {
'outputFile' => $filename,
'doGenerateToc' => 0
});
# Read outputfile
open(FILE, "<$filename") || die "Can't open $filename: $!";
$content = join('', <FILE>);
close(FILE);
# Test ToC
ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
#--- 6. empty toc -------------------------------------------------------------
$tocGenerator->generate($toc, "");
$tocInsertor->insert($toc, "", {
'output' => \$output,
'doGenerateToc' => 0
});
ok($output, "");
#--- TestAfterDeclaration() ---------------------------------------------------
# function: Test putting HTML comment after declaration.
sub TestAfterDeclaration {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'insertionPoint' => "after <!ToC>",
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<!ToC><body>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<!ToC>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Appendix</a>
<ul>
<li><a href=#h-1.1>Appendix Paragraph</a>
</ul>
<li><a href=#h-2>Appendix</a>
<ul>
<li><a href=#h-2.1>Appendix Paragraph</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<body>
<a name=h-1><h1>Appendix</h1></a>
<a name=h-1.1><h2>Appendix Paragraph</h2></a>
<a name=h-2><h1>Appendix</h1></a>
<a name=h-2.1><h2>Appendix Paragraph</h2></a>
</body>
EOT
} # TestAfterDeclaration()
#--- TestNumberingStyle() -----------------------------------------------------
# function: Test numberingstyle.
sub TestNumberingStyle {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'numberingStyle' => 'lower-alpha',
'doNumberToken' => 1,
'tokenToToc' => [{
'tokenBegin' => '<h1>',
}, {
'tokenBegin' => '<h2>',
'level' => 2,
'numberingStyle' => 'upper-alpha'
}, {
'tokenBegin' => '<h3>',
'level' => 3,
'numberingStyle' => 'decimal'
}]
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<body>
<h1>Chapter</h1>
<h2>Paragraph</h2>
<h3>Paragraph</h3>
<h3>Paragraph</h3>
<h3>Paragraph</h3>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-a>Chapter</a>
<ul>
<li><a href=#h-a.A>Paragraph</a>
<ul>
<li><a href=#h-a.A.1>Paragraph</a>
<li><a href=#h-a.A.2>Paragraph</a>
<li><a href=#h-a.A.3>Paragraph</a>
</ul>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<a name=h-a><h1>a &nbsp;Chapter</h1></a>
<a name=h-a.A><h2>a.A &nbsp;Paragraph</h2></a>
<a name=h-a.A.1><h3>a.A.1 &nbsp;Paragraph</h3></a>
<a name=h-a.A.2><h3>a.A.2 &nbsp;Paragraph</h3></a>
<a name=h-a.A.3><h3>a.A.3 &nbsp;Paragraph</h3></a>
</body>
EOT
} # TestNumberingStyle()
#--- TestReplaceComment() -----------------------------------------------------
# function: Test replacing HTML comment with ToC.
sub TestReplaceComment {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'insertionPoint' => "replace <!-- ToC -->"
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<!-- ToC -->
<body>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Appendix</a>
<ul>
<li><a href=#h-1.1>Appendix Paragraph</a>
</ul>
<li><a href=#h-2>Appendix</a>
<ul>
<li><a href=#h-2.1>Appendix Paragraph</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<body>
<a name=h-1><h1>Appendix</h1></a>
<a name=h-1.1><h2>Appendix Paragraph</h2></a>
<a name=h-2><h1>Appendix</h1></a>
<a name=h-2.1><h2>Appendix Paragraph</h2></a>
</body>
EOT
} # TestReplaceComment()
#--- TestReplaceText() -----------------------------------------------------
# function: Test replacing HTML comment with ToC.
sub TestReplaceText {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'insertionPoint' => "replace ToC will be placed here[,]"
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
The ToC will be placed here, overnight.
<body>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Appendix</a>
<ul>
<li><a href=#h-1.1>Appendix Paragraph</a>
</ul>
<li><a href=#h-2>Appendix</a>
<ul>
<li><a href=#h-2.1>Appendix Paragraph</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<body>
<a name=h-1><h1>Appendix</h1></a>
<a name=h-1.1><h2>Appendix Paragraph</h2></a>
<a name=h-2><h1>Appendix</h1></a>
<a name=h-2.1><h2>Appendix Paragraph</h2></a>
</body>
EOT
} # TestReplaceText()
# 7. Test 'numberingStyle'
TestNumberingStyle();
# 8. Test replace comment
TestReplaceComment();
# 9. Test after declaration
TestAfterDeclaration();
# 10. Test replace text
TestReplaceText();

View File

@ -0,0 +1,768 @@
#--- manual.t -----------------------------------------------------------------
# function: Test HTML::ToC generating a manual.
use strict;
use Test;
BEGIN { plan tests => 3; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
use HTML::TocUpdator;
#--- AssembleTocLine() --------------------------------------------------------
# function: Assemble ToC line.
sub AssembleTocLine {
# Get arguments
my ($aLevel, $aGroupId, $aNode, $aSequenceNr, $aText) = @_;
# Local variables
my ($result);
# Assemble ToC line
SWITCH: {
if ($aGroupId eq "prelude") {
$result = "<li>$aText\n";
last SWITCH;
}
if ($aGroupId eq "part") {
$result = "<li>Part $aNode &nbsp;$aText\n";
last SWITCH;
}
if ($aGroupId eq "h") {
$result = "<li>$aSequenceNr. &nbsp;$aText\n";
last SWITCH;
}
else {
$result = "<li>$aNode &nbsp;$aText\n";
last SWITCH;
}
}
# Return value
return $result;
} # AssembleTocLine()
#--- AssembleTokenNumber() ----------------------------------------------------
# function: Assemble token number.
sub AssembleTokenNumber {
# Get arguments
my ($aNode, $aGroupId, $aFile, $aGroupLevel, $aLevel, $aToc) = @_;
# Local variables
my ($result);
# Assemble token number
SWITCH: {
if ($aGroupId eq "part") {
$result = "Part $aNode &nbsp;";
last SWITCH;
}
else {
$result = "$aNode &nbsp;";
last SWITCH;
}
}
# Return value
return $result;
} # AssembleTokenNumber()
#--- TestInsertManualToc ------------------------------------------------------
# function: Test inserting ToC into manual.
sub TestInsertManualToc {
my $output;
# Create objects
my $toc = new HTML::Toc;
my $tocOfFigures = new HTML::Toc;
my $tocOfTables = new HTML::Toc;
my $tocInsertor = new HTML::TocInsertor;
# Set ToC options
$toc->setOptions({
'doNestGroup' => 1,
'doNumberToken' => 1,
'insertionPoint' => "replace <!-- Table of Contents -->",
'templateLevel' => \&AssembleTocLine,
'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
'templateLevelEnd' => '"</ul>\n"',
'templateTokenNumber' => \&AssembleTokenNumber,
'tokenToToc' => [{
'groupId' => 'part',
'doNumberToken' => 1,
'level' => 1,
'tokenBegin' => '<h1 class=part>',
}, {
'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
}, {
'tokenBegin' => '<h2>',
'level' => 2
}, {
'tokenBegin' => '<h3>',
'level' => 3
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h1 class=appendix>',
'numberingStyle' => 'upper-alpha',
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h2 class=appendix>',
'level' => 2
}, {
'groupId' => 'prelude',
'tokenBegin' => '<h1 class=prelude>',
'level' => 1,
'doNumberToken' => 0,
}],
});
$tocOfFigures->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "replace <!-- Table of Figures -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Figure $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Figure',
'tokenBegin' => '<p class=captionFigure>'
}]
});
$tocOfTables->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "replace <!-- Table of Tables -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Table $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Table',
'tokenBegin' => '<p class=captionTable>'
}]
});
# Insert ToC
$tocInsertor->insertIntoFile(
[$toc, $tocOfFigures, $tocOfTables],
't/ManualTest/manualTest1.htm', {
'doUseGroupsGlobal' => 1,
'output' => \$output,
'outputFile' => 't/ManualTest/manualTest2.htm'
}
);
ok($output, <<EOT);
<html>
<head>
<title>Manual</title>
<style type="text/css">
ul.toc_appendix1 {
list-style-type: none;
margin-left: 0;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h2 {
list-style-type: none;
}
ul.toc_h3 {
list-style-type: none;
}
ul.toc_part1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_prelude1 {
list-style: none;
}
p.captionFigure {
font-style: italic;
font-weight: bold;
}
p.captionTable {
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<a name=prelude-1><h1 class=prelude>Preface</h1></a>
Better C than never.
<h1 class=hidden>Table of Contents</h1>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul class=toc_prelude1>
<li><a href=#prelude-1>Preface</a>
<li><a href=#prelude-2>Table of Figures</a>
<li><a href=#prelude-3>Table of Tables</a>
<li><a href=#prelude-4>Introduction</a>
<ul class=toc_part1>
<li>Part 1 &nbsp;<a href=#part-1>Disks</a>
<ul class=toc_h1>
<li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-1.1>System</a>
<li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
</ul>
<li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-2.1>System</a>
<ul class=toc_h3>
<li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
<li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
<li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
</ul>
<li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
</ul>
<li>3. &nbsp;<a href=#h-3>Library System Disk</a>
</ul>
<li>Part 2 &nbsp;<a href=#part-2>Personal</a>
<ul class=toc_h1>
<li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
</ul>
<li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
<ul class=toc_appendix1>
<li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
<li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
<li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
</ul>
</ul>
<li><a href=#prelude-5>Bibliography</a>
</ul>
<!-- End of generated Table of Contents -->
<a name=prelude-2><h1 class=prelude>Table of Figures</h1></a>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Figure-1>Contents Compiler Disk v1</a>
<li><a href=#Figure-2>Contents Compiler Disk v2</a>
</ol>
<!-- End of generated Table of Contents -->
<a name=prelude-3><h1 class=prelude>Table of Tables</h1></a>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Table-1>Compile Steps</a>
</ol>
<!-- End of generated Table of Contents -->
<a name=prelude-4><h1 class=prelude>Introduction</h1></a>
Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
<a name=Table-1><p class=captionTable>Table 1: &nbsp;Compile Steps</p></a>
<ul><pre>
Parser
Compiler
Linker
</pre></ul>
<a name=part-1><h1 class=part>Part 1 &nbsp;Disks</h1></a>
<a name=h-1><h1>1 &nbsp;Compiler Disk v1</h1></a>
<img src=img.gif alt="Contents Compiler Disk v1">
<a name=Figure-1><p class=captionFigure>Figure 1: &nbsp;Contents Compiler Disk v1</p></a>
<a name=h-1.1><h2>1.1 &nbsp;System</h2></a>
<a name=h-1.2><h2>1.2 &nbsp;Standard Library</h2></a>
<a name=h-2><h1>2 &nbsp;Compiler Disk v2</h1></a>
<img src=img.gif alt="Contents Compiler Disk v2">
<a name=Figure-2><p class=captionFigure>Figure 2: &nbsp;Contents Compiler Disk v2</p></a>
<a name=h-2.1><h2>2.1 &nbsp;System</h2></a>
<a name=h-2.1.1><h3>2.1.1 &nbsp;parser.com</h3></a>
<a name=h-2.1.2><h3>2.1.2 &nbsp;compiler.com</h3></a>
<a name=h-2.1.3><h3>2.1.3 &nbsp;linker.com</h3></a>
<a name=h-2.2><h2>2.2 &nbsp;Standard Library</h2></a>
<a name=h-3><h1>3 &nbsp;Library System Disk</h1></a>
<a name=part-2><h1 class=part>Part 2 &nbsp;Personal</h1></a>
<a name=h-4><h1>4 &nbsp;Tips & Tricks</h1></a>
<a name=part-3><h1 class=part>Part 3 &nbsp;Appendixes</h1></a>
<a name=appendix-A><h1 class=appendix>A &nbsp;Functions Standard Library v1</h1></a>
<a name=appendix-B><h1 class=appendix>B &nbsp;Functions Standard Library v2</h1></a>
<a name=appendix-C><h1 class=appendix>C &nbsp;Functions Graphic Library</h1></a>
<a name=prelude-5><h1 class=prelude>Bibliography</h1></a>
</body>
</html>
EOT
} # TestInsertManualToc()
#--- TestInsertManualForUpdating() --------------------------------------------
# function: Test inserting ToC into manual.
sub TestInsertManualForUpdating {
my $output;
# Create objects
my $toc = new HTML::Toc;
my $tocOfFigures = new HTML::Toc;
my $tocOfTables = new HTML::Toc;
my $tocUpdator = new HTML::TocUpdator;
# Set ToC options
$toc->setOptions({
'doNestGroup' => 1,
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Contents -->",
'templateLevel' => \&AssembleTocLine,
'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
'templateLevelEnd' => '"</ul>\n"',
'templateTokenNumber' => \&AssembleTokenNumber,
'tokenToToc' => [{
'groupId' => 'part',
'doNumberToken' => 1,
'level' => 1,
'tokenBegin' => '<h1 class=part>',
}, {
'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
}, {
'tokenBegin' => '<h2>',
'level' => 2
}, {
'tokenBegin' => '<h3>',
'level' => 3
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h1 class=appendix>',
'numberingStyle' => 'upper-alpha',
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h2 class=appendix>',
'level' => 2
}, {
'groupId' => 'prelude',
'tokenBegin' => '<h1 class=prelude>',
'level' => 1,
'doNumberToken' => 0,
}],
});
$tocOfFigures->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Figures -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Figure $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Figure',
'tokenBegin' => '<p class=captionFigure>'
}]
});
$tocOfTables->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Tables -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Table $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Table',
'tokenBegin' => '<p class=captionTable>'
}]
});
# Insert ToC
$tocUpdator->updateFile(
[$toc, $tocOfFigures, $tocOfTables],
't/ManualTest/manualTest1.htm', {
'doUseGroupsGlobal' => 1,
'output' => \$output,
'outputFile' => 't/ManualTest/manualTest3.htm'
}
);
ok($output, <<EOT);
<html>
<head>
<title>Manual</title>
<style type="text/css">
ul.toc_appendix1 {
list-style-type: none;
margin-left: 0;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h2 {
list-style-type: none;
}
ul.toc_h3 {
list-style-type: none;
}
ul.toc_part1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_prelude1 {
list-style: none;
}
p.captionFigure {
font-style: italic;
font-weight: bold;
}
p.captionTable {
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
Better C than never.
<h1 class=hidden>Table of Contents</h1>
<!-- Table of Contents --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul class=toc_prelude1>
<li><a href=#prelude-1>Preface</a>
<li><a href=#prelude-2>Table of Figures</a>
<li><a href=#prelude-3>Table of Tables</a>
<li><a href=#prelude-4>Introduction</a>
<ul class=toc_part1>
<li>Part 1 &nbsp;<a href=#part-1>Disks</a>
<ul class=toc_h1>
<li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-1.1>System</a>
<li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
</ul>
<li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-2.1>System</a>
<ul class=toc_h3>
<li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
<li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
<li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
</ul>
<li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
</ul>
<li>3. &nbsp;<a href=#h-3>Library System Disk</a>
</ul>
<li>Part 2 &nbsp;<a href=#part-2>Personal</a>
<ul class=toc_h1>
<li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
</ul>
<li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
<ul class=toc_appendix1>
<li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
<li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
<li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
</ul>
</ul>
<li><a href=#prelude-5>Bibliography</a>
</ul>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- Table of Figures --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Figure-1>Contents Compiler Disk v1</a>
<li><a href=#Figure-2>Contents Compiler Disk v2</a>
</ol>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- Table of Tables --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Table-1>Compile Steps</a>
</ol>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<ul><pre>
Parser
Compiler
Linker
</pre></ul>
<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<img src=img.gif alt="Contents Compiler Disk v1">
<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<img src=img.gif alt="Contents Compiler Disk v2">
<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
</body>
</html>
EOT
} # TestInsertManualForUpdating()
#--- TestUpdateManual() -------------------------------------------------------
# function: Test inserting ToC into manual.
sub TestUpdateManual {
my $output;
# Create objects
my $toc = new HTML::Toc;
my $tocOfFigures = new HTML::Toc;
my $tocOfTables = new HTML::Toc;
my $tocUpdator = new HTML::TocUpdator;
# Set ToC options
$toc->setOptions({
'doNestGroup' => 1,
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Contents -->",
'templateLevel' => \&AssembleTocLine,
'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
'templateLevelEnd' => '"</ul>\n"',
'templateTokenNumber' => \&AssembleTokenNumber,
'tokenToToc' => [{
'groupId' => 'part',
'doNumberToken' => 1,
'level' => 1,
'tokenBegin' => '<h1 class=part>',
}, {
'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
}, {
'tokenBegin' => '<h2>',
'level' => 2
}, {
'tokenBegin' => '<h3>',
'level' => 3
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h1 class=appendix>',
'numberingStyle' => 'upper-alpha',
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h2 class=appendix>',
'level' => 2
}, {
'groupId' => 'prelude',
'tokenBegin' => '<h1 class=prelude>',
'level' => 1,
'doNumberToken' => 0,
}],
});
$tocOfFigures->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Figures -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Figure $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Figure',
'tokenBegin' => '<p class=captionFigure>'
}]
});
$tocOfTables->setOptions({
'doNumberToken' => 1,
'insertionPoint' => "after <!-- Table of Tables -->",
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
'templateTokenNumber' => '"Table $node: &nbsp;"',
'tokenToToc' => [{
'groupId' => 'Table',
'tokenBegin' => '<p class=captionTable>'
}]
});
# Insert ToC
$tocUpdator->updateFile(
[$toc, $tocOfFigures, $tocOfTables],
't/ManualTest/manualTest3.htm', {
'doUseGroupsGlobal' => 1,
'output' => \$output,
'outputFile' => 't/ManualTest/manualTest4.htm'
}
);
ok($output, <<EOT);
<html>
<head>
<title>Manual</title>
<style type="text/css">
ul.toc_appendix1 {
list-style-type: none;
margin-left: 0;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_h2 {
list-style-type: none;
}
ul.toc_h3 {
list-style-type: none;
}
ul.toc_part1 {
list-style-type: none;
margin-left: 1;
margin-top: 1em;
margin-bottom: 1em;
}
ul.toc_prelude1 {
list-style: none;
}
p.captionFigure {
font-style: italic;
font-weight: bold;
}
p.captionTable {
font-style: italic;
font-weight: bold;
}
</style>
</head>
<body>
<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
Better C than never.
<h1 class=hidden>Table of Contents</h1>
<!-- Table of Contents --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul class=toc_prelude1>
<li><a href=#prelude-1>Preface</a>
<li><a href=#prelude-2>Table of Figures</a>
<li><a href=#prelude-3>Table of Tables</a>
<li><a href=#prelude-4>Introduction</a>
<ul class=toc_part1>
<li>Part 1 &nbsp;<a href=#part-1>Disks</a>
<ul class=toc_h1>
<li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-1.1>System</a>
<li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
</ul>
<li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
<ul class=toc_h2>
<li>1. &nbsp;<a href=#h-2.1>System</a>
<ul class=toc_h3>
<li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
<li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
<li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
</ul>
<li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
</ul>
<li>3. &nbsp;<a href=#h-3>Library System Disk</a>
</ul>
<li>Part 2 &nbsp;<a href=#part-2>Personal</a>
<ul class=toc_h1>
<li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
</ul>
<li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
<ul class=toc_appendix1>
<li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
<li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
<li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
</ul>
</ul>
<li><a href=#prelude-5>Bibliography</a>
</ul>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- Table of Figures --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Figure-1>Contents Compiler Disk v1</a>
<li><a href=#Figure-2>Contents Compiler Disk v2</a>
</ol>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- Table of Tables --><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#Table-1>Compile Steps</a>
</ol>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<ul><pre>
Parser
Compiler
Linker
</pre></ul>
<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<img src=img.gif alt="Contents Compiler Disk v1">
<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<img src=img.gif alt="Contents Compiler Disk v2">
<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
</body>
</html>
EOT
} # TestUpdateManual()
# Test inserting ToC into manual
TestInsertManualToc();
# Test inserting ToC with update tokens into manual
TestInsertManualForUpdating();
# Test updating ToC
TestUpdateManual();

View File

@ -0,0 +1,194 @@
#--- options.t ----------------------------------------------------------------
# function: Test HTML::ToC. In particular test the available options.
use strict;
use Test;
BEGIN { plan tests => 5; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
use HTML::TocUpdator;
my ($filename);
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- TestAttributeToExcludeToken() --------------------------------------------
# function: Test 'HTML::Toc' option 'attributeToExcludeToken'
sub TestAttributeToExcludeToken {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<h1>Chapter 1</h1>
<h1 class=appendix>Appendix</h1>
</body>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
$toc->setOptions({
'attributeToExcludeToken' => 'foo',
'tokenToToc' => [{
'tokenBegin' => '<h1 class=foodix>'
}]
});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Chapter 1</a>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestAttributeToExcludeToken()
#--- TestAttributeToTocToken() ------------------------------------------------
# function: Test 'HTML::Toc' option 'attributeToTocToken'
sub TestAttributeToTocToken {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<img src=test.gif alt=Picture>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
$toc->setOptions({
'attributeToTocToken' => 'foo',
'tokenToToc' => [{
'groupId' => 'image',
'tokenBegin' => '<img alt=foo>'
}],
});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#image-1>Picture</a>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestAttributeToTocToken()
#--- TestNumberingStyleDecimal ------------------------------------------------
# function: Test 'decimal' numbering style.
sub TestNumberingStyleDecimal {
# Local variables
my $output;
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
$toc->setOptions({
'doNumberToken' => 1,
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1>',
'numberingStyle' => 'decimal'
}],
});
# Generate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok("$output\n", <<EOT);
<a name=h-1><h1>1 &nbsp;Header</h1></a>
EOT
} # TestNumberingStyleDecimal()
#--- TestNumberingStyleLowerAlpha ---------------------------------------------
# function: Test 'lower-alpha' numbering style.
sub TestNumberingStyleLowerAlpha {
# Local variables
my $output;
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
$toc->setOptions({
'doNumberToken' => 1,
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1>',
'numberingStyle' => 'lower-alpha'
}],
});
# Generate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok("$output\n", <<EOT);
<a name=h-a><h1>a &nbsp;Header</h1></a>
EOT
} # TestNumberingStyleLowerAlpha()
#--- TestNumberingStyleUpperAlpha ---------------------------------------------
# function: Test 'upper-alpha' numbering style.
sub TestNumberingStyleUpperAlpha {
# Local variables
my $output;
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
$toc->setOptions({
'doNumberToken' => 1,
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1>',
'numberingStyle' => 'upper-alpha'
}],
});
# Generate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok("$output\n", <<EOT);
<a name=h-A><h1>A &nbsp;Header</h1></a>
EOT
} # TestNumberingStyleUpperAlpha()
# Test 'attributeToTocToken'
TestAttributeToTocToken();
# Test 'attributeToExcludeToken'
TestAttributeToExcludeToken();
# Test 'numberingStyleDecimal'
TestNumberingStyleDecimal();
# Test 'numberingStyleLowerAlpha'
TestNumberingStyleLowerAlpha();
# Test 'numberingStyleUpperAlpha'
TestNumberingStyleUpperAlpha();

View File

@ -0,0 +1,709 @@
#--- podExamples.t ------------------------------------------------------------
# function: Test HTML::ToC. In particular test the examples as described in
# the POD documentation.
use strict;
use Test;
BEGIN { plan tests => 13; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
use HTML::TocUpdator;
my ($filename, $filename2);
BEGIN {
# Create test file
$filename = "tmp.htm";
die "$filename is already there" if -e $filename;
# Create test file 2
$filename2 = "tmp2.htm";
die "$filename2 is already there" if -e $filename2;
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
# Remove test file 2
unlink($filename2) or warn "Can't unlink $filename2: $!";
}
#--- TestExtendFromFile() --------------------------------------------------
# function: Test 'HTML::TocGenerator->extendFromFile()
sub TestExtendFromFile {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<h1>Chapter of document 1</h1>
</body>
EOT
# Assemble test file 2
open(FILE, ">$filename2") || die "Can't create $filename2: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body>
<h1>Chapter of document 2</h1>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Set ToC options
$toc->setOptions({'doLinkToFile' => 1});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
$tocGenerator->extendFromFile($toc, $filename2);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=tmp.htm#h-1>Chapter of document 1</a>
<li><a href=tmp2.htm#h-2>Chapter of document 2</a>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestExtendFromFile()
#--- TestGenerateFromFiles() --------------------------------------------------
# function: Test 'HTML::TocGenerator->generateFromFile()
sub TestGenerateFromFiles {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<h1>Chapter of document 1</h1>
</body>
EOT
# Assemble test file 2
open(FILE, ">$filename2") || die "Can't create $filename2: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body>
<h1>Chapter of document 2</h1>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Set ToC options
$toc->setOptions({'doLinkToFile' => 1});
# Generate ToC
$tocGenerator->generateFromFile($toc, [$filename, $filename2]);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=tmp.htm#h-1>Chapter of document 1</a>
<li><a href=tmp2.htm#h-2>Chapter of document 2</a>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestGenerateFromFiles()
#--- TestGenerateFromFiles() --------------------------------------------------
# function: Test 'HTML::TocGenerator->generateFromFile() using multiple files.
sub TestGenerateFromFile {
# Assemble test file 1
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body>
<h1>Chapter</h1>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Chapter</a>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestGenerateFromFile()
#--- TestInsertIntoFile() -----------------------------------------------------
# function: Test 'HTML::TocInsertor->insertIntoFile()
sub TestInsertIntoFile {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body>
<h1>Chapter</h1>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Generate ToC
$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
# Test ToC
ok($output, <<EOT);
<html>
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Chapter</a>
</ul>
<!-- End of generated Table of Contents -->
<a name=h-1><h1>Chapter</h1></a>
</body>
</html>
EOT
} # TestInsertIntoFile()
#--- TestInsertIntoFileUsingTocUpdator() --------------------------------------
# function: Test 'HTML::TocUpdator->insertIntoFile()
sub TestInsertIntoFileUsingTocUpdator {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body>
<h1>
Chapter
</h1>
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocUpdator = HTML::TocUpdator->new();
my $output;
# Generate ToC
$tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
# Test ToC
ok($output, <<EOT);
<html>
<body><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1> Chapter </a>
</ul>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
Chapter
</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
</body>
</html>
EOT
} # TestInsertIntoFileUsingTocUpdator()
#--- TestGlobalGroups0() ------------------------------------------------------
# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
sub TestGlobalGroups0 {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<h1>Chapter</h1>
<h2>Paragraph</h2>
EOT
# Create objects
my $toc1 = HTML::Toc->new();
my $toc2 = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Set options
$toc1->setOptions({
'header' => '',
'footer' => '',
'tokenToToc' => [{'tokenBegin' => '<h1>'}]
});
$toc2->setOptions({
'header' => '',
'footer' => '',
'tokenToToc' => [{'tokenBegin' => '<h2>'}]
});
# Generate ToC
$tocGenerator->generateFromFile([$toc1, $toc2], $filename);
# Test ToC
ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
<ul>
<li><a href=#h-1>Chapter</a>
</ul><ul>
<li><a href=#h-1>Paragraph</a>
</ul>
EOT
} # TestGlobalGroups0()
#--- TestGlobalGroups1() ------------------------------------------------------
# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
sub TestGlobalGroups1 {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT';
<h1>Chapter</h1>
<h2>Paragraph</h2>
EOT
close(FILE);
# Create objects
my $toc1 = HTML::Toc->new();
my $toc2 = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Set options
$toc1->setOptions({
'header' => '',
'footer' => '',
'tokenToToc' => [{'tokenBegin' => '<h1>'}]
});
$toc2->setOptions({
'header' => '',
'footer' => '',
'tokenToToc' => [{'tokenBegin' => '<h2>'}]
});
# Generate ToC
$tocGenerator->generateFromFile(
[$toc1, $toc2], $filename, {'doUseGroupsGlobal' => 1}
);
# Test ToC
ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
<ul>
<li><a href=#h-1>Chapter</a>
</ul><ul>
<li><a href=#h-2>Paragraph</a>
</ul>
EOT
} # TestGlobalGroups1()
#--- TestMultipleGroupsAppendix() ---------------------------------------------
# function: Test multiple ToCs
sub TestMultipleGroupsAppendix() {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'tokenToToc' => [{
'tokenBegin' => '<h1 class=-appendix>'
}, {
'tokenBegin' => '<h2 class=-appendix>',
'level' => 2
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h1 class=appendix>',
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h2 class=appendix>',
'level' => 2
}],
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<body>
<h1>Chapter</h1>
<h2>Paragraph</h2>
<h3>Subparagraph</h3>
<h1>Chapter</h1>
<h1 class=appendix>Appendix Chapter</h1>
<h2 class=appendix>Appendix Paragraph</h2>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Chapter</a>
<ul>
<li><a href=#h-1.1>Paragraph</a>
</ul>
<li><a href=#h-2>Chapter</a>
</ul>
<ul>
<li><a href=#appendix-1>Appendix Chapter</a>
<ul>
<li><a href=#appendix-1.1>Appendix Paragraph</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<a name=h-1><h1>Chapter</h1></a>
<a name=h-1.1><h2>Paragraph</h2></a>
<h3>Subparagraph</h3>
<a name=h-2><h1>Chapter</h1></a>
<a name=appendix-1><h1 class=appendix>Appendix Chapter</h1></a>
<a name=appendix-1.1><h2 class=appendix>Appendix Paragraph</h2></a>
</body>
EOT
} # TestMultipleGroupsAppendix()
#--- TestMultipleGroupsPart() -------------------------------------------------
# function: Test multiple ToCs
sub TestMultipleGroupsPart() {
# Create objects
my $toc = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc->setOptions({
'tokenToToc' => [{
'tokenBegin' => '<h1 class=-part>'
}, {
'tokenBegin' => '<h2 class=-part>',
'level' => 2,
}, {
'groupId' => 'part',
'tokenBegin' => '<h1 class=part>',
'level' => 1,
'doNumberToken' => 1,
'numberingStyle' => 'upper-alpha'
}]
});
# Generate ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<body>
<h1 class=part>First Part</h1>
<h1>Chapter</h1>
<h2>Paragraph</h2>
<h1 class=part>Second Part</h1>
<h1>Chapter</h1>
<h2>Paragraph</h2>
</body>
EOT
# Test ToC
ok($output, <<EOT);
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#part-A>First Part</a>
</ul>
<ul>
<li><a href=#h-1>Chapter</a>
<ul>
<li><a href=#h-1.1>Paragraph</a>
</ul>
</ul>
<ul>
<li><a href=#part-B>Second Part</a>
</ul>
<ul>
<li><a href=#h-2>Chapter</a>
<ul>
<li><a href=#h-2.1>Paragraph</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<a name=part-A><h1 class=part>A &nbsp;First Part</h1></a>
<a name=h-1><h1>Chapter</h1></a>
<a name=h-1.1><h2>Paragraph</h2></a>
<a name=part-B><h1 class=part>B &nbsp;Second Part</h1></a>
<a name=h-2><h1>Chapter</h1></a>
<a name=h-2.1><h2>Paragraph</h2></a>
</body>
EOT
} # TestMultipleGroupsPart()
#--- TestMultipleTocs() -------------------------------------------------------
# function: Test multiple ToCs
sub TestMultipleTocs() {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<h1>Header One</h1>
<img src=test1.gif alt="First picture">
<h2>Paragraph One</h2>
<img src=test2.gif alt="Second picture">
</body>
EOT
# Create objects
my $toc1 = HTML::Toc->new();
my $toc2 = HTML::Toc->new();
my $tocInsertor = HTML::TocInsertor->new();
my $output;
# Set ToC options
$toc2->setOptions({
'tokenToToc' => [{
'groupId' => 'image',
'tokenBegin' => '<img alt=@>'
}],
});
# Generate ToC
$tocInsertor->insertIntoFile(
[$toc1, $toc2], $filename, {'output' => \$output}
);
# Test ToC
ok($output, <<EOT);
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1>Header One</a>
<ul>
<li><a href=#h-1.1>Paragraph One</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#image-1>First picture</a>
<li><a href=#image-2>Second picture</a>
</ul>
<!-- End of generated Table of Contents -->
<a name=h-1><h1>Header One</h1></a>
<a name=image-1><img src=test1.gif alt="First picture"></a>
<a name=h-1.1><h2>Paragraph One</h2></a>
<a name=image-2><img src=test2.gif alt="Second picture"></a>
</body>
EOT
} # TestMultipleTocs()
#--- TestSpecifyNumberedList() ------------------------------------------------
# function: Test specifying numbered list.
sub TestSpecifyNumberedList {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<body>
<h1>Chapter</h1>
<h2>Paragraph</h2>
</body>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
# Set ToC options
$toc->setOptions({
'templateLevelBegin' => '"<ol>\n"',
'templateLevelEnd' => '"</ol>\n"',
});
# Generate ToC
$tocGenerator->generateFromFile($toc, $filename);
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol>
<li><a href=#h-1>Chapter</a>
<ol>
<li><a href=#h-1.1>Paragraph</a>
</ol>
</ol>
<!-- End of generated Table of Contents -->
EOT
} # TestSpecifyNumberedList()
#--- TestUpdateFile() ---------------------------------------------------------
# function: Test 'HTML::TocUpdator->updateFile()'
sub TestUpdateFile {
# Assemble test file
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<html>
<body><!-- #BeginToc -->
foo
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
Chapter
</h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
</body>
</html>
EOT
# Create objects
my $toc = HTML::Toc->new();
my $tocUpdator = HTML::TocUpdator->new();
my $output;
# Generate ToC
$tocUpdator->updateFile($toc, $filename, {'output' => \$output});
# Test ToC
ok($output, <<EOT);
<html>
<body><!-- #BeginToc -->
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=#h-1> Chapter </a>
</ul>
<!-- End of generated Table of Contents -->
<!-- #EndToc -->
<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
Chapter
</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
</body>
</html>
EOT
} # TestUpdateFile()
#--- TestUsingCSS() -----------------------------------------------------------
# function: Test multiple ToCs
sub TestUsingCSS() {
# Create objects
my $toc = new HTML::Toc;
my $tocInsertor = new HTML::TocInsertor;
my $output;
$toc->setOptions({
'templateLevelBegin' => '"<ol class=toc_$groupId$level>\n"',
'templateLevelEnd' => '"</ol>\n"',
'doNumberToken' => 1,
'tokenToToc' => [{
'groupId' => 'appendix',
'tokenBegin' => '<h1>',
'numberingStyle' => 'upper-alpha'
}, {
'groupId' => 'appendix',
'tokenBegin' => '<h2>',
'level' => 2,
}]
});
$tocInsertor->insert($toc, <<EOT);
<html>
<head>
<style type="text/css">
ol.toc_appendix1 { list-style-type: upper-alpha }
</style>
</head>
<body>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
</body>
</html>
EOT
# Insert ToC
$tocInsertor->insert($toc, <<EOT, {'output' => \$output});
<html>
<head>
<style type="text/css">
ol.toc_appendix1 { list-style-type: upper-alpha }
</style>
</head>
<body>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
<h1>Appendix</h1>
<h2>Appendix Paragraph</h2>
</body>
</html>
EOT
# Test ToC
ok($output, <<EOT);
<html>
<head>
<style type="text/css">
ol.toc_appendix1 { list-style-type: upper-alpha }
</style>
</head>
<body>
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ol class=toc_appendix1>
<li><a href=#appendix-A>Appendix</a>
<ol class=toc_appendix2>
<li><a href=#appendix-A.1>Appendix Paragraph</a>
</ol>
<li><a href=#appendix-B>Appendix</a>
<ol class=toc_appendix2>
<li><a href=#appendix-B.1>Appendix Paragraph</a>
</ol>
</ol>
<!-- End of generated Table of Contents -->
<a name=appendix-A><h1>A &nbsp;Appendix</h1></a>
<a name=appendix-A.1><h2>A.1 &nbsp;Appendix Paragraph</h2></a>
<a name=appendix-B><h1>B &nbsp;Appendix</h1></a>
<a name=appendix-B.1><h2>B.1 &nbsp;Appendix Paragraph</h2></a>
</body>
</html>
EOT
} # TestUsingCSS()
# Test 'extendFromFile()'
TestExtendFromFile();
# Test 'generateFromFile()'
TestGenerateFromFile();
# Test 'generateFromFiles()'
TestGenerateFromFiles();
# Test 'doUseGroupsGlobal = 0'
TestGlobalGroups0();
# Test 'doUseGroupsGlobal = 1'
TestGlobalGroups1();
# Test 'tocInsertor->insertIntoFile'
TestInsertIntoFile();
# Test 'tocUpdator->insertIntoFile'
TestInsertIntoFileUsingTocUpdator();
# Test additional 'appendix' group
TestMultipleGroupsAppendix();
# Test additional 'part' group
TestMultipleGroupsPart();
# Test multiple ToCs
TestMultipleTocs();
# Test specifying numbered list
TestSpecifyNumberedList();
# Test 'updateFile()'
TestUpdateFile();
# Test using CSS
TestUsingCSS();

View File

@ -0,0 +1,176 @@
#--- propagate.t --------------------------------------------------------------
# function: Test ToC propagation.
use strict;
use Test;
BEGIN { plan tests => 10; }
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
my ($output, $content, $filename);
my $toc = HTML::Toc->new;
my $tocGenerator = HTML::TocGenerator->new;
my $tocInsertor = HTML::TocInsertor->new;
$toc->setOptions({
'doLinkToToken' => 0,
'levelIndent' => 0,
'insertionPoint' => 'before <h1>',
'header' => '',
'footer' => '',
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<h1>Header</h1>
EOT
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. propagate -------------------------------------------------------------
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
#--- 2. propagateFile ---------------------------------------------------------
$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>\n");
#--- 3. doLinkToToken -----------------------------------------------------
$toc->setOptions({'doLinkToToken' => 1});
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok("$output\n", <<'EOT');
<ul>
<li><a href=#h-1>Header</a>
</ul><a name=h-1><h1>Header</h1></a>
EOT
#--- 4. templateAnchorHrefBegin -----------------------------------------------
$toc->setOptions(
{'templateAnchorHrefBegin' => '"<$node${file}test${groupId}>"'}
);
$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
ok($output, "<ul>\n<li><1${filename}testh>Header</a>\n</ul><a name=h-1><h1>Header</h1></a>\n");
$toc->setOptions({'templateAnchorHrefBegin' => undef});
#--- 5. templateAnchorNameBegin -----------------------------------------------
$toc->setOptions({
'templateAnchorName' => '"$node$groupId"',
'templateAnchorNameBegin' => '"<$anchorName>"'
});
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok($output, "<ul>\n<li><a href=#1h>Header</a>\n</ul><1h><h1>Header</h1></a>");
$toc->setOptions({'templateAnchorName' => undef});
#--- 6. templateAnchorName function -------------------------------------------
sub AssembleAnchorName {
# Get arguments
my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
# Return value
return $aFile . $aGroupId . $aLevel . $aNode;
} # AssembleAnchorName()
# Set options
$toc->setOptions({'templateAnchorNameBegin' => \&AssembleAnchorName});
# Propagate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok($output, "<ul>\n<li><a href=#h-1>Header</a>\n</ul>h11<h1>Header</h1></a>");
# Restore options
$toc->setOptions({'templateAnchorNameBegin' => undef});
#--- 7. doNumberToken --------------------------------------------------------
# Set options
$toc->setOptions({'doNumberToken' => 1});
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok("$output\n", <<'EOT');
<ul>
<li><a href=#h-1>Header</a>
</ul><a name=h-1><h1>1 &nbsp;Header</h1></a>
EOT
# Reset options
$toc->setOptions({
'templateTokenNumber' => undef,
'doNumberToken' => 0
});
#--- 8. templateTokenNumber ---------------------------------------------------
# Set options
$toc->setOptions({
'templateTokenNumber' => '"-$node-"',
'doNumberToken' => 1
});
# Propagate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok("$output\n", <<'EOT');
<ul>
<li><a href=#h-1>Header</a>
</ul><a name=h-1><h1>-1-Header</h1></a>
EOT
# Reset options
$toc->setOptions({
'doNumberToken' => 0,
'templateTokenNumber' => undef
});
#--- 9. numberingStyle --------------------------------------------------------
# Set options
$toc->setOptions({
'doNumberToken' => 1,
'tokenToToc' => [{
'level' => 1,
'tokenBegin' => '<h1>',
'numberingStyle' => 'lower-alpha'
}]
});
# Propagate ToC
$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
# Test ToC
ok("$output\n", <<'EOT');
<ul>
<li><a href=#h-a>Header</a>
</ul><a name=h-a><h1>a &nbsp;Header</h1></a>
EOT
# Reset options
$toc->setOptions({
'doNumberToken' => 0,
'tokenToToc' => undef,
});
#--- 10. declaration pass through ---------------------------------------------
$tocInsertor->insert($toc, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>', {'output' => \$output});
# Test ToC
ok($output, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>');

View File

@ -0,0 +1,97 @@
#--- manual.t -----------------------------------------------------------------
# function: Test HTML::ToC generating a manual.
use strict;
use Test;
BEGIN { plan tests => 1; }
use Data::Dumper;
use File::Find;
use HTML::Toc;
use HTML::TocGenerator;
use HTML::TocInsertor;
use HTML::TocUpdator;
# Create objects
my $toc = HTML::Toc->new();
my $tocGenerator = HTML::TocGenerator->new();
my @fileList;
#--- TestSiteMap() ------------------------------------------------------------
# function: Test specifying numbered list.
sub TestSiteMap {
# Set ToC options
$toc->setOptions({
'doLinkToFile' => 1,
'templateAnchorName' => '""',
'templateAnchorHref' => '"<a href=$file"."#".$groupId.$level.">"',
'doLinkTocToToken' => 1,
'tokenToToc' => [{
'groupId' => 'dir',
'level' => 1,
'tokenBegin' => '<title>',
'tokenEnd' => '</title>',
'fileSpec' => '\./[^/]+$'
}, {
'groupId' => 'dir',
'level' => 2,
'tokenBegin' => '<title>',
'tokenEnd' => '</title>',
'fileSpec' => '\./[^/]+?/[^/]+$'
}, {
'groupId' => 'dir',
'level' => 3,
'tokenBegin' => '<title>',
'tokenEnd' => '</title>',
'fileSpec' => '\./[^/]+?/[^/]+?/[^/]+$'
}]
});
# Change current directory
chdir("t/SiteMap");
# Find files, filling 'fileList'
find({wanted => \&WantedSiteMap, no_chdir => 1}, '.');
# Generate ToC of case-insensitively sorted file list
$tocGenerator->extendFromFile(
$toc, [sort {uc($a) cmp uc($b)} @fileList]
);
# Restore current directory
chdir("../..");
# Test ToC
ok($toc->format(), <<EOT);
<!-- Table of Contents generated by Perl - HTML::Toc -->
<ul>
<li><a href=./index.htm#>Main</a>
<ul>
<li><a href=./SubDir1/index.htm#>Sub1</a>
<ul>
<li><a href=./SubDir1/SubSubDir1/index.htm#>SubSub1</a>
</ul>
<li><a href=./SubDir2/index.htm#>Sub2</a>
<ul>
<li><a href=./SubDir2/SubSubDir1/index.htm#>SubSub1</a>
<li><a href=./SubDir2/SubSubDir2/index.htm#>SubSub2</a>
</ul>
<li><a href=./SubDir3/index.htm#>Sub3</a>
</ul>
</ul>
<!-- End of generated Table of Contents -->
EOT
} # TestSiteMap()
#--- WantedSiteMap() ----------------------------------------------------------
# function: 'Wanted' function, used by File::Find of 'TestSiteMap()'.
sub WantedSiteMap {
# Add file to 'fileList' if extension matches '.htm'
push (@fileList, $File::Find::name) if (m/\.htm$/);
} # WantedSiteMap()
# Test site map
TestSiteMap();

View File

@ -0,0 +1,114 @@
#--- update.t -----------------------------------------------------------------
# function: Test ToC updating.
use strict;
use Test;
BEGIN { plan tests => 6; }
use HTML::Toc;
use HTML::TocUpdator;
my ($output, $output2, $content, $filename);
my $toc = HTML::Toc->new;
my $tocUpdator = HTML::TocUpdator->new;
$toc->setOptions({
'doLinkToToken' => 1,
'doNumberToken' => 1,
'levelIndent' => 0,
'insertionPoint' => 'before <h1>',
'header' => '',
'footer' => '',
});
BEGIN {
# Create test file
$filename = "file$$.htm";
die "$filename is already there" if -e $filename;
open(FILE, ">$filename") || die "Can't create $filename: $!";
print FILE <<'EOT'; close(FILE);
<h1>Header</h1>
EOT
}
END {
# Remove test file
unlink($filename) or warn "Can't unlink $filename: $!";
}
#--- 1. update ----------------------------------------------------------------
$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
ok("$output\n", <<'EOT');
<!-- #BeginToc --><ul>
<li><a href=#h-1>Header</a>
</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
EOT
#--- 2. updateFile ------------------------------------------------------------
$tocUpdator->updateFile($toc, $filename, {'output' => \$output});
open(FILE, ">a.out1") || die "Can't create a.out1: $!";
print FILE $output; close(FILE);
$output2 = <<'EOT';
<!-- #BeginToc --><ul>
<li><a href=#h-1>Header</a>
</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
EOT
open(FILE, ">a.out2") || die "Can't create a.out2: $!";
print FILE $output2; close(FILE);
ok($output, $output2);
#--- 3. insert ----------------------------------------------------------------
$tocUpdator->insert($toc, "<h1>Header</h1>", {'output' => \$output});
ok("$output\n", <<'EOT');
<!-- #BeginToc --><ul>
<li><a href=#h-1>Header</a>
</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
EOT
#--- 4. insertIntoFile --------------------------------------------------------
$tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
ok($output, <<'EOT');
<!-- #BeginToc --><ul>
<li><a href=#h-1>Header</a>
</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
EOT
#--- 5. update twice ----------------------------------------------------------
$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
$tocUpdator->update($toc, $output, {'output' => \$output2});
ok("$output\n", <<'EOT');
<!-- #BeginToc --><ul>
<li><a href=#h-1>Header</a>
</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
EOT
#--- 6. tokens update begin & end ---------------------------------------------
$toc->setOptions({
'tokenUpdateBeginOfAnchorNameBegin' => '<tocAnchorNameBegin>',
'tokenUpdateEndOfAnchorNameBegin' => '</tocAnchorNameBegin>',
'tokenUpdateBeginOfAnchorNameEnd' => '<tocAnchorNameEnd>',
'tokenUpdateEndOfAnchorNameEnd' => '</tocAnchorNameEnd>',
'tokenUpdateBeginNumber' => '<tocNumber>',
'tokenUpdateEndNumber' => '</tocNumber>',
'tokenUpdateBeginToc' => '<toc>',
'tokenUpdateEndToc', => '</toc>'
});
$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
ok("$output\n", <<'EOT');
<toc><ul>
<li><a href=#h-1>Header</a>
</ul></toc><tocAnchorNameBegin><a name=h-1></tocAnchorNameBegin><h1><tocNumber>1 &nbsp;</tocNumber>Header</h1><tocAnchorNameEnd></a></tocAnchorNameEnd>
EOT

View File

@ -0,0 +1,36 @@
PHP Markdown & Extra
Copyright (c) 2004-2008 Michel Fortin
<http://www.michelf.com/>
All rights reserved.
Based on Markdown
Copyright (c) 2003-2006 John Gruber
<http://daringfireball.net/>
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 "Markdown" 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.

View File

@ -0,0 +1,731 @@
PHP Markdown Extra
==================
Version 1.2.3 - Wed 31 Dec 2008
by Michel Fortin
<http://www.michelf.com/>
based on Markdown by John Gruber
<http://daringfireball.net/>
Introduction
------------
This is a special version of PHP Markdown with extra features. See
<http://www.michelf.com/projects/php-markdown/extra/> for details.
Markdown is a text-to-HTML conversion tool for web writers. Markdown
allows you to write using an easy-to-read, easy-to-write plain text
format, then convert it to structurally valid XHTML (or HTML).
"Markdown" is two things: a plain text markup syntax, and a software
tool, written in Perl, that converts the plain text markup to HTML.
PHP Markdown is a port to PHP of the original Markdown program by
John Gruber.
PHP Markdown can work as a plug-in for WordPress and bBlog, as a
modifier for the Smarty templating engine, or as a remplacement for
textile formatting in any software that support textile.
Full documentation of Markdown's syntax is available on John's
Markdown page: <http://daringfireball.net/projects/markdown/>
Installation and Requirement
----------------------------
PHP Markdown requires PHP version 4.0.5 or later.
### WordPress ###
PHP Markdown works with [WordPress][wp], version 1.2 or later.
[wp]: http://wordpress.org/
1. To use PHP Markdown with WordPress, place the "makrdown.php" file
in the "plugins" folder. This folder is located inside
"wp-content" at the root of your site:
(site home)/wp-content/plugins/
2. Activate the plugin with the administrative interface of
WordPress. In the "Plugins" section you will now find Markdown.
To activate the plugin, click on the "Activate" button on the
same line than Markdown. Your entries will now be formatted by
PHP Markdown.
3. To post Markdown content, you'll first have to disable the
"visual" editor in the User section of WordPress.
You can configure PHP Markdown to not apply to the comments on your
WordPress weblog. See the "Configuration" section below.
It is not possible at this time to apply a different set of
filters to different entries. All your entries will be formated by
PHP Markdown. This is a limitation of WordPress. If your old entries
are written in HTML (as opposed to another formatting syntax, like
Textile), they'll probably stay fine after installing Markdown.
### bBlog ###
PHP Markdown also works with [bBlog][bb].
[bb]: http://www.bblog.com/
To use PHP Markdown with bBlog, rename "markdown.php" to
"modifier.markdown.php" and place the file in the "bBlog_plugins"
folder. This folder is located inside the "bblog" directory of
your site, like this:
(site home)/bblog/bBlog_plugins/modifier.markdown.php
Select "Markdown" as the "Entry Modifier" when you post a new
entry. This setting will only apply to the entry you are editing.
### Replacing Textile in TextPattern ###
[TextPattern][tp] use [Textile][tx] to format your text. You can
replace Textile by Markdown in TextPattern without having to change
any code by using the *Texitle Compatibility Mode*. This may work
with other software that expect Textile too.
[tx]: http://www.textism.com/tools/textile/
[tp]: http://www.textpattern.com/
1. Rename the "markdown.php" file to "classTextile.php". This will
make PHP Markdown behave as if it was the actual Textile parser.
2. Replace the "classTextile.php" file TextPattern installed in your
web directory. It can be found in the "lib" directory:
(site home)/textpattern/lib/
Contrary to Textile, Markdown does not convert quotes to curly ones
and does not convert multiple hyphens (`--` and `---`) into en- and
em-dashes. If you use PHP Markdown in Textile Compatibility Mode, you
can solve this problem by installing the "smartypants.php" file from
[PHP SmartyPants][psp] beside the "classTextile.php" file. The Textile
Compatibility Mode function will use SmartyPants automatically without
further modification.
[psp]: http://www.michelf.com/projects/php-smartypants/
### In Your Own Programs ###
You can use PHP Markdown easily in your current PHP program. Simply
include the file and then call the Markdown function on the text you
want to convert:
include_once "markdown.php";
$my_html = Markdown($my_text);
If you wish to use PHP Markdown with another text filter function
built to parse HTML, you should filter the text *after* the Markdown
function call. This is an example with [PHP SmartyPants][psp]:
$my_html = SmartyPants(Markdown($my_text));
### With Smarty ###
If your program use the [Smarty][sm] template engine, PHP Markdown
can now be used as a modifier for your templates. Rename "markdown.php"
to "modifier.markdown.php" and put it in your smarty plugins folder.
[sm]: http://smarty.php.net/
If you are using MovableType 3.1 or later, the Smarty plugin folder is
located at `(MT CGI root)/php/extlib/smarty/plugins`. This will allow
Markdown to work on dynamic pages.
### Updating Markdown in Other Programs ###
Many web applications now ship with PHP Markdown, or have plugins to
perform the conversion to HTML. You can update PHP Markdown -- or
replace it with PHP Markdown Extra -- in many of these programs by
swapping the old "markdown.php" file for the new one.
Here is a short non-exhaustive list of some programs and where they
hide the "markdown.php" file.
| Program | Path to Markdown
| ------- | ----------------
| [Pivot][] | `(site home)/pivot/includes/markdown/`
If you're unsure if you can do this with your application, ask the
developer, or wait for the developer to update his application or
plugin with the new version of PHP Markdown.
[Pivot]: http://pivotlog.net/
Configuration
-------------
By default, PHP Markdown produces XHTML output for tags with empty
elements. E.g.:
<br />
Markdown can be configured to produce HTML-style tags; e.g.:
<br>
To do this, you must edit the "MARKDOWN_EMPTY_ELEMENT_SUFFIX"
definition below the "Global default settings" header at the start of
the "markdown.php" file.
### WordPress-Specific Settings ###
By default, the Markdown plugin applies to both posts and comments on
your WordPress weblog. To deactivate one or the other, edit the
`MARKDOWN_WP_POSTS` or `MARKDOWN_WP_COMMENTS` definitions under the
"WordPress settings" header at the start of the "markdown.php" file.
Bugs
----
To file bug reports please send email to:
<michel.fortin@michelf.com>
Please include with your report: (1) the example input; (2) the output you
expected; (3) the output PHP Markdown actually produced.
Version History
---------------
Extra 1.2.3 (31 Dec 2008):
* In WordPress pages featuring more than one post, footnote id prefixes are
now automatically applied with the current post ID to avoid clashes
between footnotes belonging to different posts.
* Fix for a bug introduced in Extra 1.2 where block-level HTML tags where
not detected correctly, thus the addition of erroneous `<p>` tags and
interpretation of their content as Markdown-formatted instead of
HTML-formatted.
Extra 1.2.2 (21 Jun 2008):
* Fixed a problem where abbreviation definitions, footnote
definitions and link references were stripped inside
fenced code blocks.
* Fixed a bug where characters such as `"` in abbreviation
definitions weren't properly encoded to HTML entities.
* Fixed a bug where double quotes `"` were not correctly encoded
as HTML entities when used inside a footnote reference id.
1.0.1m (21 Jun 2008):
* Lists can now have empty items.
* Rewrote the emphasis and strong emphasis parser to fix some issues
with odly placed and overlong markers.
Extra 1.2.1 (27 May 2008):
* Fixed a problem where Markdown headers and horizontal rules were
transformed into their HTML equivalent inside fenced code blocks.
Extra 1.2 (11 May 2008):
* Added fenced code block syntax which don't require indentation
and can start and end with blank lines. A fenced code block
starts with a line of consecutive tilde (~) and ends on the
next line with the same number of consecutive tilde. Here's an
example:
~~~~~~~~~~~~
Hello World!
~~~~~~~~~~~~
* Rewrote parts of the HTML block parser to better accomodate
fenced code blocks.
* Footnotes may now be referenced from within another footnote.
* Added programatically-settable parser property `predef_attr` for
predefined attribute definitions.
* Fixed an issue where an indented code block preceded by a blank
line containing some other whitespace would confuse the HTML
block parser into creating an HTML block when it should have
been code.
1.0.1l (11 May 2008):
* Now removing the UTF-8 BOM at the start of a document, if present.
* Now accepting capitalized URI schemes (such as HTTP:) in automatic
links, such as `<HTTP://EXAMPLE.COM/>`.
* Fixed a problem where `<hr@example.com>` was seen as a horizontal
rule instead of an automatic link.
* Fixed an issue where some characters in Markdown-generated HTML
attributes weren't properly escaped with entities.
* Fix for code blocks as first element of a list item. Previously,
this didn't create any code block for item 2:
* Item 1 (regular paragraph)
* Item 2 (code block)
* A code block starting on the second line of a document wasn't seen
as a code block. This has been fixed.
* Added programatically-settable parser properties `predef_urls` and
`predef_titles` for predefined URLs and titles for reference-style
links. To use this, your PHP code must call the parser this way:
$parser = new Markdwon_Parser;
$parser->predef_urls = array('linkref' => 'http://example.com');
$html = $parser->transform($text);
You can then use the URL as a normal link reference:
[my link][linkref]
[my link][linkRef]
Reference names in the parser properties *must* be lowercase.
Reference names in the Markdown source may have any case.
* Added `setup` and `teardown` methods which can be used by subclassers
as hook points to arrange the state of some parser variables before and
after parsing.
Extra 1.1.7 (26 Sep 2007):
1.0.1k (26 Sep 2007):
* Fixed a problem introduced in 1.0.1i where three or more identical
uppercase letters, as well as a few other symbols, would trigger
a horizontal line.
Extra 1.1.6 (4 Sep 2007):
1.0.1j (4 Sep 2007):
* Fixed a problem introduced in 1.0.1i where the closing `code` and
`pre` tags at the end of a code block were appearing in the wrong
order.
* Overriding configuration settings by defining constants from an
external before markdown.php is included is now possible without
producing a PHP warning.
Extra 1.1.5 (31 Aug 2007):
1.0.1i (31 Aug 2007):
* Fixed a problem where an escaped backslash before a code span
would prevent the code span from being created. This should now
work as expected:
Litteral backslash: \\`code span`
* Overall speed improvements, especially with long documents.
Extra 1.1.4 (3 Aug 2007):
1.0.1h (3 Aug 2007):
* Added two properties (`no_markup` and `no_entities`) to the parser
allowing HTML tags and entities to be disabled.
* Fix for a problem introduced in 1.0.1g where posting comments in
WordPress would trigger PHP warnings and cause some markup to be
incorrectly filtered by the kses filter in WordPress.
Extra 1.1.3 (3 Jul 2007):
* Fixed a performance problem when parsing some invalid HTML as an HTML
block which was resulting in too much recusion and a segmentation fault
for long documents.
* The markdown="" attribute now accepts unquoted values.
* Fixed an issue where underscore-emphasis didn't work when applied on the
first or the last word of an element having the markdown="1" or
markdown="span" attribute set unless there was some surrounding whitespace.
This didn't work:
<p markdown="1">_Hello_ _world_</p>
Now it does produce emphasis as expected.
* Fixed an issue preventing footnotes from working when the parser's
footnote id prefix variable (fn_id_prefix) is not empty.
* Fixed a performance problem where the regular expression for strong
emphasis introduced in version 1.1 could sometime be long to process,
give slightly wrong results, and in some circumstances could remove
entirely the content for a whole paragraph.
* Fixed an issue were abbreviations tags could be incorrectly added
inside URLs and title of links.
* Placing footnote markers inside a link, resulting in two nested links, is
no longer allowed.
1.0.1g (3 Jul 2007):
* Fix for PHP 5 compiled without the mbstring module. Previous fix to
calculate the length of UTF-8 strings in `detab` when `mb_strlen` is
not available was only working with PHP 4.
* Fixed a problem with WordPress 2.x where full-content posts in RSS feeds
were not processed correctly by Markdown.
* Now supports URLs containing literal parentheses for inline links
and images, such as:
[WIMP](http://en.wikipedia.org/wiki/WIMP_(computing))
Such parentheses may be arbitrarily nested, but must be
balanced. Unbalenced parentheses are allowed however when the URL
when escaped or when the URL is enclosed in angle brakets `<>`.
* Fixed a performance problem where the regular expression for strong
emphasis introduced in version 1.0.1d could sometime be long to process,
give slightly wrong results, and in some circumstances could remove
entirely the content for a whole paragraph.
* Some change in version 1.0.1d made possible the incorrect nesting of
anchors within each other. This is now fixed.
* Fixed a rare issue where certain MD5 hashes in the content could
be changed to their corresponding text. For instance, this:
The MD5 value for "+" is "26b17225b626fb9238849fd60eabdf60".
was incorrectly changed to this in previous versions of PHP Markdown:
<p>The MD5 value for "+" is "+".</p>
* Now convert escaped characters to their numeric character
references equivalent.
This fix an integration issue with SmartyPants and backslash escapes.
Since Markdown and SmartyPants have some escapable characters in common,
it was sometime necessary to escape them twice. Previously, two
backslashes were sometime required to prevent Markdown from "eating" the
backslash before SmartyPants sees it:
Here are two hyphens: \\--
Now, only one backslash will do:
Here are two hyphens: \--
Extra 1.1.2 (7 Feb 2007)
* Fixed an issue where headers preceded too closely by a paragraph
(with no blank line separating them) where put inside the paragraph.
* Added the missing TextileRestricted method that was added to regular
PHP Markdown since 1.0.1d but which I forgot to add to Extra.
1.0.1f (7 Feb 2007):
* Fixed an issue with WordPress where manually-entered excerpts, but
not the auto-generated ones, would contain nested paragraphs.
* Fixed an issue introduced in 1.0.1d where headers and blockquotes
preceded too closely by a paragraph (not separated by a blank line)
where incorrectly put inside the paragraph.
* Fixed an issue introduced in 1.0.1d in the tokenizeHTML method where
two consecutive code spans would be merged into one when together they
form a valid tag in a multiline paragraph.
* Fixed an long-prevailing issue where blank lines in code blocks would
be doubled when the code block is in a list item.
This was due to the list processing functions relying on artificially
doubled blank lines to correctly determine when list items should
contain block-level content. The list item processing model was thus
changed to avoid the need for double blank lines.
* Fixed an issue with `<% asp-style %>` instructions used as inline
content where the opening `<` was encoded as `&lt;`.
* Fixed a parse error occuring when PHP is configured to accept
ASP-style delimiters as boundaries for PHP scripts.
* Fixed a bug introduced in 1.0.1d where underscores in automatic links
got swapped with emphasis tags.
Extra 1.1.1 (28 Dec 2006)
* Fixed a problem where whitespace at the end of the line of an atx-style
header would cause tailing `#` to appear as part of the header's content.
This was caused by a small error in the regex that handles the definition
for the id attribute in PHP Markdown Extra.
* Fixed a problem where empty abbreviations definitions would eat the
following line as its definition.
* Fixed an issue with calling the Markdown parser repetitivly with text
containing footnotes. The footnote hashes were not reinitialized properly.
1.0.1e (28 Dec 2006)
* Added support for internationalized domain names for email addresses in
automatic link. Improved the speed at which email addresses are converted
to entities. Thanks to Milian Wolff for his optimisations.
* Made deterministic the conversion to entities of email addresses in
automatic links. This means that a given email address will always be
encoded the same way.
* PHP Markdown will now use its own function to calculate the length of an
UTF-8 string in `detab` when `mb_strlen` is not available instead of
giving a fatal error.
Extra 1.1 (1 Dec 2006)
* Added a syntax for footnotes.
* Added an experimental syntax to define abbreviations.
1.0.1d (1 Dec 2006)
* Fixed a bug where inline images always had an empty title attribute. The
title attribute is now present only when explicitly defined.
* Link references definitions can now have an empty title, previously if the
title was defined but left empty the link definition was ignored. This can
be useful if you want an empty title attribute in images to hide the
tooltip in Internet Explorer.
* Made `detab` aware of UTF-8 characters. UTF-8 multi-byte sequences are now
correctly mapped to one character instead of the number of bytes.
* Fixed a small bug with WordPress where WordPress' default filter `wpautop`
was not properly deactivated on comment text, resulting in hard line breaks
where Markdown do not prescribes them.
* Added a `TextileRestrited` method to the textile compatibility mode. There
is no restriction however, as Markdown does not have a restricted mode at
this point. This should make PHP Markdown work again in the latest
versions of TextPattern.
* Converted PHP Markdown to a object-oriented design.
* Changed span and block gamut methods so that they loop over a
customizable list of methods. This makes subclassing the parser a more
interesting option for creating syntax extensions.
* Also added a "document" gamut loop which can be used to hook document-level
methods (like for striping link definitions).
* Changed all methods which were inserting HTML code so that they now return
a hashed representation of the code. New methods `hashSpan` and `hashBlock`
are used to hash respectivly span- and block-level generated content. This
has a couple of significant effects:
1. It prevents invalid nesting of Markdown-generated elements which
could occur occuring with constructs like `*something [link*][1]`.
2. It prevents problems occuring with deeply nested lists on which
paragraphs were ill-formed.
3. It removes the need to call `hashHTMLBlocks` twice during the the
block gamut.
Hashes are turned back to HTML prior output.
* Made the block-level HTML parser smarter using a specially-crafted regular
expression capable of handling nested tags.
* Solved backtick issues in tag attributes by rewriting the HTML tokenizer to
be aware of code spans. All these lines should work correctly now:
<span attr='`ticks`'>bar</span>
<span attr='``double ticks``'>bar</span>
`<test a="` content of attribute `">`
* Changed the parsing of HTML comments to match simply from `<!--` to `-->`
instead using of the more complicated SGML-style rule with paired `--`.
This is how most browsers parse comments and how XML defines them too.
* `<address>` has been added to the list of block-level elements and is now
treated as an HTML block instead of being wrapped within paragraph tags.
* Now only trim trailing newlines from code blocks, instead of trimming
all trailing whitespace characters.
* Fixed bug where this:
[text](http://m.com "title" )
wasn't working as expected, because the parser wasn't allowing for spaces
before the closing paren.
* Filthy hack to support markdown='1' in div tags.
* _DoAutoLinks() now supports the 'dict://' URL scheme.
* PHP- and ASP-style processor instructions are now protected as
raw HTML blocks.
<? ... ?>
<% ... %>
* Fix for escaped backticks still triggering code spans:
There are two raw backticks here: \` and here: \`, not a code span
Extra 1.0 - 5 September 2005
* Added support for setting the id attributes for headers like this:
Header 1 {#header1}
========
## Header 2 ## {#header2}
This only work only for headers for now.
* Tables will now work correctly as the first element of a definition
list. For example, this input:
Term
: Header | Header
------- | -------
Cell | Cell
used to produce no definition list and a table where the first
header was named ": Header". This is now fixed.
* Fix for a problem where a paragraph following a table was not
placed between `<p>` tags.
Extra 1.0b4 - 1 August 2005
* Fixed some issues where whitespace around HTML blocks were trigging
empty paragraph tags.
* Fixed an HTML block parsing issue that would cause a block element
following a code span or block with unmatched opening bracket to be
placed inside a paragraph.
* Removed some PHP notices that could appear when parsing definition
lists and tables with PHP notice reporting flag set.
Extra 1.0b3 - 29 July 2005
* Definition lists now require a blank line before each term. Solves
an ambiguity where the last line of lazy-indented definitions could
be mistaken by PHP Markdown as a new term in the list.
* Definition lists now support multiple terms per definition.
* Some special tags were replaced in the output by their md5 hash
key. Things such as this now work as expected:
## Header <?php echo $number ?> ##
Extra 1.0b2 - 26 July 2005
* Definition lists can now take two or more definitions for one term.
This should have been the case before, but a bug prevented this
from working right.
* Fixed a problem where single column table with a pipe only at the
end where not parsed as table. Here is such a table:
| header
| ------
| cell
* Fixed problems with empty cells in the first column of a table with
no leading pipe, like this one:
header | header
------ | ------
| cell
* Code spans containing pipes did not within a table. This is now
fixed by parsing code spans before splitting rows into cells.
* Added the pipe character to the backlash escape character lists.
Extra 1.0b1 (25 Jun 2005)
* First public release of PHP Markdown Extra.
Copyright and License
---------------------
Copyright (c) 2004-2005 Michel Fortin
<http://www.michelf.com/>
All rights reserved.
Based on Markdown
Copyright (c) 2003-2005 John Gruber
<http://daringfireball.net/>
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 "Markdown" 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.

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,394 @@
PHP SmartyPants
===============
Version 1.5.1e - Fri 9 Dec 2005
by Michel Fortin
<http://www.michelf.com/>
based on work by John Gruber
<http://daringfireball.net/>
Introduction
------------
PHP SmartyPants is a port to PHP of the original SmartyPants written
in Perl by John Gruber.
PHP SmartyPants is a free web publishing plug-in for WordPress and
Smarty template engine that easily translates plain ASCII punctuation
characters into "smart" typographic punctuation HTML entities.
SmartyPants can also be invoked as a standalone PHP function.
SmartyPants can perform the following transformations:
* Straight quotes (`"` and `'`) into "curly" quote HTML entities
* Backtick-style quotes (` ``like this'' `) into "curly" quote HTML
entities
* Dashes (`--` and `---`) into en- and em-dash entities
* Three consecutive dots (`...`) into an ellipsis entity
This means you can write, edit, and save using plain old ASCII straight
quotes, plain dashes, and plain dots, but your published posts (and
final HTML output) will appear with smart quotes, em-dashes, and proper
ellipses.
SmartyPants does not modify characters within `<pre>`, `<code>`,
`<kbd>`, or `<script>` tag blocks. Typically, these tags are used to
display text where smart quotes and other "smart punctuation" would not
be appropriate, such as source code or example markup.
### Backslash Escapes ###
If you need to use literal straight quotes (or plain hyphens and
periods), SmartyPants accepts the following backslash escape sequences
to force non-smart punctuation. It does so by transforming the escape
sequence into a decimal-encoded HTML entity:
Escape Value Character
------ ----- ---------
\\ &#92; \
\" &#34; "
\' &#39; '
\. &#46; .
\- &#45; -
\` &#96; `
This is useful, for example, when you want to use straight quotes as
foot and inch marks:
6\'2\" tall
translates into:
6&#39;2&#34; tall
in SmartyPants's HTML output. Which, when rendered by a web browser,
looks like:
6'2" tall
Installation and Requirement
----------------------------
PHP SmartyPants require PHP version 4.0.5 or later.
### WordPress ###
WordPress already include a filter called "Texturize" with the same
goal as SmartyPants. You could still find some usefulness to
PHP SmartyPants if you are not happy enough with the standard algorithm.
PHP SmartyPants works with [WordPress][wp], version 1.2 or later.
[wp]: http://wordpress.org/
1. To use PHP SmartyPants with WordPress, place the "smartypants.php"
file in the "plugins" folder. This folder is hidden inside
"wp-content" at the root of your site:
(site home)/wp-content/plugins/smartypants.php
2. Activate the plugin with the administrative interface of WordPress.
In the "Plugins" section you will now find SmartyPants. To activate
the plugin, click on the "Activate" button on the same line than
SmartyPants. Your entries will now be filtered by PHP SmartyPants.
Note: It is not possible at this time to apply a different set of
filters to different entries. All your entries will be filtered by
PHP SmartyPants if the plugin is active. This is currently a limitation
of WordPress.
### Blosxom ###
SmartyPants works with Blosxom version 2.0 or later.
1. Rename the "SmartyPants.pl" plug-in to "SmartyPants" (case is
important). Movable Type requires plug-ins to have a ".pl"
extension; Blosxom forbids it (at least as of this writing).
2. Copy the "SmartyPants" plug-in file to your Blosxom plug-ins folder.
If you're not sure where your Blosxom plug-ins folder is, see the
Blosxom documentation for information.
3. That's it. The entries in your weblog should now automatically have
SmartyPants's default transformations applied.
4. If you wish to configure SmartyPants's behavior, open the
"SmartyPants" plug-in, and edit the value of the `$smartypants_attr`
configuration variable, located near the top of the script. The
default value is 1; see "Options", below, for the full list of
supported values.
### In your programs ###
You can use PHP SmartyPants easily in your current PHP program. Simply
include the file and then call the `SmartyPants` function on the text
you want to convert:
include_once "smartypants.php";
$my_text = SmartyPants($my_text);
### With Smarty ###
If your program use the [Smarty][sm] template engine, PHP SmartyPants
can now be used as a modifier for your templates. Rename
"smartypants.php" to "modifier.smartypants.php" and put it in your
smarty plugins folder.
[sm]: http://smarty.php.net/
Options and Configuration
-------------------------
Settings are specified by editing the value of the `$smartypants_attr`
variable in the "smartypants.php" file. For users of the Smarty template
engine, the "smartypants" modifier also takes an optional attribute where
you can specify configuration options, like this:
`{$var|smartypants:1}` (where "1" is the configuration option).
Numeric values are the easiest way to configure SmartyPants's behavior:
"0"
Suppress all transformations. (Do nothing.)
"1"
Performs default SmartyPants transformations: quotes (including
backticks-style), em-dashes, and ellipses. `--` (dash dash) is
used to signify an em-dash; there is no support for en-dashes.
"2"
Same as smarty_pants="1", except that it uses the old-school
typewriter shorthand for dashes: `--` (dash dash) for en-dashes,
`---` (dash dash dash) for em-dashes.
"3"
Same as smarty_pants="2", but inverts the shorthand for dashes: `--`
(dash dash) for em-dashes, and `---` (dash dash dash) for en-dashes.
"-1"
Stupefy mode. Reverses the SmartyPants transformation process,
turning the HTML entities produced by SmartyPants into their ASCII
equivalents. E.g. `&#8220;` is turned into a simple double-quote
(`"`), `&#8212;` is turned into two dashes, etc. This is useful if you
wish to suppress smart punctuation in specific pages, such as
RSS feeds.
The following single-character attribute values can be combined to
toggle individual transformations from within the smarty_pants
attribute. For example, to educate normal quotes and em-dashes, but not
ellipses or backticks-style quotes:
$smartypants_attr = "qd";
Or inside a Smarty template:
{$var|smartypants:"qd"}
"q"
Educates normal quote characters: (`"`) and (`'`).
"b"
Educates ` ``backticks'' ` double quotes.
"B"
Educates backticks-style double quotes and ` `single' ` quotes.
"d"
Educates em-dashes.
"D"
Educates em-dashes and en-dashes, using old-school typewriter
shorthand: (dash dash) for en-dashes, (dash dash dash) for
em-dashes.
"i"
Educates em-dashes and en-dashes, using inverted old-school
typewriter shorthand: (dash dash) for em-dashes, (dash dash dash)
for en-dashes.
"e"
Educates ellipses.
"w"
Translates any instance of `&quot;` into a normal double-quote
character. This should be of no interest to most people, but of
particular interest to anyone who writes their posts using
Dreamweaver, as Dreamweaver inexplicably uses this entity to
represent a literal double-quote character. SmartyPants only
educates normal quotes, not entities (because ordinarily, entities
are used for the explicit purpose of representing the specific
character they represent). The "w" option must be used in
conjunction with one (or both) of the other quote options ("q" or
"b"). Thus, if you wish to apply all SmartyPants transformations
(quotes, en- and em-dashes, and ellipses) and also translate
`&quot;` entities into regular quotes so SmartyPants can educate
them, you should pass the following to the smarty_pants attribute:
$smartypants_attr = "qDew";
Inside a Smarty template, this will be:
{$var|smartypants:"qDew"}
Caveats
-------
### Why You Might Not Want to Use Smart Quotes in Your Weblog ###
For one thing, you might not care.
Most normal, mentally stable individuals do not take notice of proper
typographic punctuation. Many design and typography nerds, however,
break out in a nasty rash when they encounter, say, a restaurant sign
that uses a straight apostrophe to spell "Joe's".
If you're the sort of person who just doesn't care, you might well want
to continue not caring. Using straight quotes -- and sticking to the
7-bit ASCII character set in general -- is certainly a simpler way to
live.
Even if you *do* care about accurate typography, you still might want to
think twice before educating the quote characters in your weblog. One
side effect of publishing curly quote HTML entities is that it makes
your weblog a bit harder for others to quote from using copy-and-paste.
What happens is that when someone copies text from your blog, the copied
text contains the 8-bit curly quote characters (as well as the 8-bit
characters for em-dashes and ellipses, if you use these options). These
characters are not standard across different text encoding methods,
which is why they need to be encoded as HTML entities.
People copying text from your weblog, however, may not notice that
you're using curly quotes, and they'll go ahead and paste the unencoded
8-bit characters copied from their browser into an email message or
their own weblog. When pasted as raw "smart quotes", these characters
are likely to get mangled beyond recognition.
That said, my own opinion is that any decent text editor or email client
makes it easy to stupefy smart quote characters into their 7-bit
equivalents, and I don't consider it my problem if you're using an
indecent text editor or email client.
### Algorithmic Shortcomings ###
One situation in which quotes will get curled the wrong way is when
apostrophes are used at the start of leading contractions. For example:
'Twas the night before Christmas.
In the case above, SmartyPants will turn the apostrophe into an opening
single-quote, when in fact it should be a closing one. I don't think
this problem can be solved in the general case -- every word processor
I've tried gets this wrong as well. In such cases, it's best to use the
proper HTML entity for closing single-quotes (`&#8217;` or `&rsquo;`) by
hand.
Bugs
----
To file bug reports or feature requests (other than topics listed in the
Caveats section above) please send email to:
<michel.fortin@michelf.com>
If the bug involves quotes being curled the wrong way, please send
example text to illustrate.
Version History
---------------
1.5.1e (9 Dec 2005)
* Corrected a bug that prevented special characters from being
escaped.
1.5.1d (6 Jun 2005)
* Correct a small bug in `_TokenizeHTML` where a Doctype declaration
was not seen as HTML, making curly quotes inside it.
1.5.1c (13 Dec 2004)
* Changed a regular expression in `_TokenizeHTML` that could lead
to a segmentation fault with PHP 4.3.8 on Linux.
1.5.1b (6 Sep 2004)
* Corrected a problem with quotes immediately following a dash
with no space between: `Text--"quoted text"--text.`
* PHP SmartyPants can now be used as a modifier by the Smarty
template engine. Rename the file to "modifier.smartypants.php"
and put it in your smarty plugins folder.
* Replaced a lot of spaces characters by tabs, saving about 4 KB.
1.5.1a (30 Jun 2004)
* PHP Markdown and PHP Smartypants now share the same `_TokenizeHTML`
function when loaded simultanously.
* Changed the internals of `_TokenizeHTML` to lower the PHP version
requirement to PHP 4.0.5.
1.5.1 (6 Jun 2004)
* Initial release of PHP SmartyPants, based on version 1.5.1 of the
original SmartyPants written in Perl.
Copyright and License
---------------------
Copyright (c) 2005 Michel Fortin
<http://www.michelf.com/>
All rights reserved.
Copyright (c) 2003-2004 John Gruber
<http://daringfireball.net/>
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 "SmartyPants" 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.

View File

@ -0,0 +1,860 @@
<?php
#
# SmartyPants - Smart punctuation for web sites
#
# by John Gruber
# <http://daringfireball.net>
#
# PHP port by Michel Fortin
# <http://www.michelf.com/>
#
# Copyright (c) 2003-2004 John Gruber
# Copyright (c) 2004-2005 Michel Fortin
#
global $SmartyPantsPHPVersion, $SmartyPantsSyntaxVersion,
$smartypants_attr, $sp_tags_to_skip;
$SmartyPantsPHPVersion = '1.5.1e'; # Fru 9 Dec 2005
$SmartyPantsSyntaxVersion = '1.5.1'; # Fri 12 Mar 2004
# Configurable variables:
$smartypants_attr = "1"; # Change this to configure.
# 1 => "--" for em-dashes; no en-dash support
# 2 => "---" for em-dashes; "--" for en-dashes
# 3 => "--" for em-dashes; "---" for en-dashes
# See docs for more configuration options.
# Globals:
$sp_tags_to_skip = '<(/?)(?:pre|code|kbd|script|math)[\s>]';
# -- WordPress plugin interface -----------------------------------------------
/*
Plugin Name: SmartyPants
Plugin URI: http://www.michelf.com/projects/php-smartypants/
Description: SmartyPants is a web publishing utility that translates plain ASCII punctuation characters into &#8220;smart&#8221; typographic punctuation HTML entities. This plugin <strong>replace the default WordPress Texturize algorithm</strong> for the content and the title of your posts, the comments body and author name, and everywhere else Texturize normally apply. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>.
Version: 1.5.1e
Author: Michel Fortin
Author URI: http://www.michelf.com/
*/
if (isset($wp_version)) {
# Remove default Texturize filter that would conflict with SmartyPants.
remove_filter('category_description', 'wptexturize');
remove_filter('list_cats', 'wptexturize');
remove_filter('comment_author', 'wptexturize');
remove_filter('comment_text', 'wptexturize');
remove_filter('single_post_title', 'wptexturize');
remove_filter('the_title', 'wptexturize');
remove_filter('the_content', 'wptexturize');
remove_filter('the_excerpt', 'wptexturize');
# Add SmartyPants filter with priority 10 (same as Texturize).
add_filter('category_description', 'SmartyPants', 10);
add_filter('list_cats', 'SmartyPants', 10);
add_filter('comment_author', 'SmartyPants', 10);
add_filter('comment_text', 'SmartyPants', 10);
add_filter('single_post_title', 'SmartyPants', 10);
add_filter('the_title', 'SmartyPants', 10);
add_filter('the_content', 'SmartyPants', 10);
add_filter('the_excerpt', 'SmartyPants', 10);
}
# -- Smarty Modifier Interface ------------------------------------------------
function smarty_modifier_smartypants($text, $attr = NULL) {
return SmartyPants($text, $attr);
}
function SmartyPants($text, $attr = NULL, $ctx = NULL) {
global $smartypants_attr, $sp_tags_to_skip;
# Paramaters:
$text; # text to be parsed
$attr; # value of the smart_quotes="" attribute
$ctx; # MT context object (unused)
if ($attr == NULL) $attr = $smartypants_attr;
# Options to specify which transformations to make:
$do_stupefy = FALSE;
$convert_quot = 0; # should we translate &quot; entities into normal quotes?
# Parse attributes:
# 0 : do nothing
# 1 : set all
# 2 : set all, using old school en- and em- dash shortcuts
# 3 : set all, using inverted old school en and em- dash shortcuts
#
# q : quotes
# b : backtick quotes (``double'' only)
# B : backtick quotes (``double'' and `single')
# d : dashes
# D : old school dashes
# i : inverted old school dashes
# e : ellipses
# w : convert &quot; entities to " for Dreamweaver users
if ($attr == "0") {
# Do nothing.
return $text;
}
else if ($attr == "1") {
# Do everything, turn all options on.
$do_quotes = 1;
$do_backticks = 1;
$do_dashes = 1;
$do_ellipses = 1;
}
else if ($attr == "2") {
# Do everything, turn all options on, use old school dash shorthand.
$do_quotes = 1;
$do_backticks = 1;
$do_dashes = 2;
$do_ellipses = 1;
}
else if ($attr == "3") {
# Do everything, turn all options on, use inverted old school dash shorthand.
$do_quotes = 1;
$do_backticks = 1;
$do_dashes = 3;
$do_ellipses = 1;
}
else if ($attr == "-1") {
# Special "stupefy" mode.
$do_stupefy = 1;
}
else {
$chars = preg_split('//', $attr);
foreach ($chars as $c){
if ($c == "q") { $do_quotes = 1; }
else if ($c == "b") { $do_backticks = 1; }
else if ($c == "B") { $do_backticks = 2; }
else if ($c == "d") { $do_dashes = 1; }
else if ($c == "D") { $do_dashes = 2; }
else if ($c == "i") { $do_dashes = 3; }
else if ($c == "e") { $do_ellipses = 1; }
else if ($c == "w") { $convert_quot = 1; }
else {
# Unknown attribute option, ignore.
}
}
}
$tokens = _TokenizeHTML($text);
$result = '';
$in_pre = 0; # Keep track of when we're inside <pre> or <code> tags.
$prev_token_last_char = ""; # This is a cheat, used to get some context
# for one-character tokens that consist of
# just a quote char. What we do is remember
# the last character of the previous text
# token, to use as context to curl single-
# character quote tokens correctly.
foreach ($tokens as $cur_token) {
if ($cur_token[0] == "tag") {
# Don't mess with quotes inside tags.
$result .= $cur_token[1];
if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
}
} else {
$t = $cur_token[1];
$last_char = substr($t, -1); # Remember last char of this token before processing.
if (! $in_pre) {
$t = ProcessEscapes($t);
if ($convert_quot) {
$t = preg_replace('/&quot;/', '"', $t);
}
if ($do_dashes) {
if ($do_dashes == 1) $t = EducateDashes($t);
if ($do_dashes == 2) $t = EducateDashesOldSchool($t);
if ($do_dashes == 3) $t = EducateDashesOldSchoolInverted($t);
}
if ($do_ellipses) $t = EducateEllipses($t);
# Note: backticks need to be processed before quotes.
if ($do_backticks) {
$t = EducateBackticks($t);
if ($do_backticks == 2) $t = EducateSingleBackticks($t);
}
if ($do_quotes) {
if ($t == "'") {
# Special case: single-character ' token
if (preg_match('/\S/', $prev_token_last_char)) {
$t = "&#8217;";
}
else {
$t = "&#8216;";
}
}
else if ($t == '"') {
# Special case: single-character " token
if (preg_match('/\S/', $prev_token_last_char)) {
$t = "&#8221;";
}
else {
$t = "&#8220;";
}
}
else {
# Normal case:
$t = EducateQuotes($t);
}
}
if ($do_stupefy) $t = StupefyEntities($t);
}
$prev_token_last_char = $last_char;
$result .= $t;
}
}
return $result;
}
function SmartQuotes($text, $attr = NULL, $ctx = NULL) {
global $smartypants_attr, $sp_tags_to_skip;
# Paramaters:
$text; # text to be parsed
$attr; # value of the smart_quotes="" attribute
$ctx; # MT context object (unused)
if ($attr == NULL) $attr = $smartypants_attr;
$do_backticks; # should we educate ``backticks'' -style quotes?
if ($attr == 0) {
# do nothing;
return $text;
}
else if ($attr == 2) {
# smarten ``backticks'' -style quotes
$do_backticks = 1;
}
else {
$do_backticks = 0;
}
# Special case to handle quotes at the very end of $text when preceded by
# an HTML tag. Add a space to give the quote education algorithm a bit of
# context, so that it can guess correctly that it's a closing quote:
$add_extra_space = 0;
if (preg_match("/>['\"]\\z/", $text)) {
$add_extra_space = 1; # Remember, so we can trim the extra space later.
$text .= " ";
}
$tokens = _TokenizeHTML($text);
$result = '';
$in_pre = 0; # Keep track of when we're inside <pre> or <code> tags
$prev_token_last_char = ""; # This is a cheat, used to get some context
# for one-character tokens that consist of
# just a quote char. What we do is remember
# the last character of the previous text
# token, to use as context to curl single-
# character quote tokens correctly.
foreach ($tokens as $cur_token) {
if ($cur_token[0] == "tag") {
# Don't mess with quotes inside tags
$result .= $cur_token[1];
if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
}
} else {
$t = $cur_token[1];
$last_char = substr($t, -1); # Remember last char of this token before processing.
if (! $in_pre) {
$t = ProcessEscapes($t);
if ($do_backticks) {
$t = EducateBackticks($t);
}
if ($t == "'") {
# Special case: single-character ' token
if (preg_match('/\S/', $prev_token_last_char)) {
$t = "&#8217;";
}
else {
$t = "&#8216;";
}
}
else if ($t == '"') {
# Special case: single-character " token
if (preg_match('/\S/', $prev_token_last_char)) {
$t = "&#8221;";
}
else {
$t = "&#8220;";
}
}
else {
# Normal case:
$t = EducateQuotes($t);
}
}
$prev_token_last_char = $last_char;
$result .= $t;
}
}
if ($add_extra_space) {
preg_replace('/ \z/', '', $result); # Trim trailing space if we added one earlier.
}
return $result;
}
function SmartDashes($text, $attr = NULL, $ctx = NULL) {
global $smartypants_attr, $sp_tags_to_skip;
# Paramaters:
$text; # text to be parsed
$attr; # value of the smart_dashes="" attribute
$ctx; # MT context object (unused)
if ($attr == NULL) $attr = $smartypants_attr;
# reference to the subroutine to use for dash education, default to EducateDashes:
$dash_sub_ref = 'EducateDashes';
if ($attr == 0) {
# do nothing;
return $text;
}
else if ($attr == 2) {
# use old smart dash shortcuts, "--" for en, "---" for em
$dash_sub_ref = 'EducateDashesOldSchool';
}
else if ($attr == 3) {
# inverse of 2, "--" for em, "---" for en
$dash_sub_ref = 'EducateDashesOldSchoolInverted';
}
$tokens;
$tokens = _TokenizeHTML($text);
$result = '';
$in_pre = 0; # Keep track of when we're inside <pre> or <code> tags
foreach ($tokens as $cur_token) {
if ($cur_token[0] == "tag") {
# Don't mess with quotes inside tags
$result .= $cur_token[1];
if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
}
} else {
$t = $cur_token[1];
if (! $in_pre) {
$t = ProcessEscapes($t);
$t = $dash_sub_ref($t);
}
$result .= $t;
}
}
return $result;
}
function SmartEllipses($text, $attr = NULL, $ctx = NULL) {
# Paramaters:
$text; # text to be parsed
$attr; # value of the smart_ellipses="" attribute
$ctx; # MT context object (unused)
if ($attr == NULL) $attr = $smartypants_attr;
if ($attr == 0) {
# do nothing;
return $text;
}
$tokens;
$tokens = _TokenizeHTML($text);
$result = '';
$in_pre = 0; # Keep track of when we're inside <pre> or <code> tags
foreach ($tokens as $cur_token) {
if ($cur_token[0] == "tag") {
# Don't mess with quotes inside tags
$result .= $cur_token[1];
if (preg_match("@$sp_tags_to_skip@", $cur_token[1], $matches)) {
$in_pre = isset($matches[1]) && $matches[1] == '/' ? 0 : 1;
}
} else {
$t = $cur_token[1];
if (! $in_pre) {
$t = ProcessEscapes($t);
$t = EducateEllipses($t);
}
$result .= $t;
}
}
return $result;
}
function EducateQuotes($_) {
#
# Parameter: String.
#
# Returns: The string, with "educated" curly quote HTML entities.
#
# Example input: "Isn't this fun?"
# Example output: &#8220;Isn&#8217;t this fun?&#8221;
#
# Make our own "punctuation" character class, because the POSIX-style
# [:PUNCT:] is only available in Perl 5.6 or later:
$punct_class = "[!\"#\\$\\%'()*+,-.\\/:;<=>?\\@\\[\\\\\]\\^_`{|}~]";
# Special case if the very first character is a quote
# followed by punctuation at a non-word-break. Close the quotes by brute force:
$_ = preg_replace(
array("/^'(?=$punct_class\\B)/", "/^\"(?=$punct_class\\B)/"),
array('&#8217;', '&#8221;'), $_);
# Special case for double sets of quotes, e.g.:
# <p>He said, "'Quoted' words in a larger quote."</p>
$_ = preg_replace(
array("/\"'(?=\w)/", "/'\"(?=\w)/"),
array('&#8220;&#8216;', '&#8216;&#8220;'), $_);
# Special case for decade abbreviations (the '80s):
$_ = preg_replace("/'(?=\\d{2}s)/", '&#8217;', $_);
$close_class = '[^\ \t\r\n\[\{\(\-]';
$dec_dashes = '&\#8211;|&\#8212;';
# Get most opening single quotes:
$_ = preg_replace("{
(
\\s | # a whitespace char, or
&nbsp; | # a non-breaking space entity, or
-- | # dashes, or
&[mn]dash; | # named dash entities
$dec_dashes | # or decimal entities
&\\#x201[34]; # or hex
)
' # the quote
(?=\\w) # followed by a word character
}x", '\1&#8216;', $_);
# Single closing quotes:
$_ = preg_replace("{
($close_class)?
'
(?(1)| # If $1 captured, then do nothing;
(?=\\s | s\\b) # otherwise, positive lookahead for a whitespace
) # char or an 's' at a word ending position. This
# is a special case to handle something like:
# \"<i>Custer</i>'s Last Stand.\"
}xi", '\1&#8217;', $_);
# Any remaining single quotes should be opening ones:
$_ = str_replace("'", '&#8216;', $_);
# Get most opening double quotes:
$_ = preg_replace("{
(
\\s | # a whitespace char, or
&nbsp; | # a non-breaking space entity, or
-- | # dashes, or
&[mn]dash; | # named dash entities
$dec_dashes | # or decimal entities
&\\#x201[34]; # or hex
)
\" # the quote
(?=\\w) # followed by a word character
}x", '\1&#8220;', $_);
# Double closing quotes:
$_ = preg_replace("{
($close_class)?
\"
(?(1)|(?=\\s)) # If $1 captured, then do nothing;
# if not, then make sure the next char is whitespace.
}x", '\1&#8221;', $_);
# Any remaining quotes should be opening ones.
$_ = str_replace('"', '&#8220;', $_);
return $_;
}
function EducateBackticks($_) {
#
# Parameter: String.
# Returns: The string, with ``backticks'' -style double quotes
# translated into HTML curly quote entities.
#
# Example input: ``Isn't this fun?''
# Example output: &#8220;Isn't this fun?&#8221;
#
$_ = str_replace(array("``", "''",),
array('&#8220;', '&#8221;'), $_);
return $_;
}
function EducateSingleBackticks($_) {
#
# Parameter: String.
# Returns: The string, with `backticks' -style single quotes
# translated into HTML curly quote entities.
#
# Example input: `Isn't this fun?'
# Example output: &#8216;Isn&#8217;t this fun?&#8217;
#
$_ = str_replace(array("`", "'",),
array('&#8216;', '&#8217;'), $_);
return $_;
}
function EducateDashes($_) {
#
# Parameter: String.
#
# Returns: The string, with each instance of "--" translated to
# an em-dash HTML entity.
#
$_ = str_replace('--', '&#8212;', $_);
return $_;
}
function EducateDashesOldSchool($_) {
#
# Parameter: String.
#
# Returns: The string, with each instance of "--" translated to
# an en-dash HTML entity, and each "---" translated to
# an em-dash HTML entity.
#
# em en
$_ = str_replace(array("---", "--",),
array('&#8212;', '&#8211;'), $_);
return $_;
}
function EducateDashesOldSchoolInverted($_) {
#
# Parameter: String.
#
# Returns: The string, with each instance of "--" translated to
# an em-dash HTML entity, and each "---" translated to
# an en-dash HTML entity. Two reasons why: First, unlike the
# en- and em-dash syntax supported by
# EducateDashesOldSchool(), it's compatible with existing
# entries written before SmartyPants 1.1, back when "--" was
# only used for em-dashes. Second, em-dashes are more
# common than en-dashes, and so it sort of makes sense that
# the shortcut should be shorter to type. (Thanks to Aaron
# Swartz for the idea.)
#
# en em
$_ = str_replace(array("---", "--",),
array('&#8211;', '&#8212;'), $_);
return $_;
}
function EducateEllipses($_) {
#
# Parameter: String.
# Returns: The string, with each instance of "..." translated to
# an ellipsis HTML entity. Also converts the case where
# there are spaces between the dots.
#
# Example input: Huh...?
# Example output: Huh&#8230;?
#
$_ = str_replace(array("...", ". . .",), '&#8230;', $_);
return $_;
}
function StupefyEntities($_) {
#
# Parameter: String.
# Returns: The string, with each SmartyPants HTML entity translated to
# its ASCII counterpart.
#
# Example input: &#8220;Hello &#8212; world.&#8221;
# Example output: "Hello -- world."
#
# en-dash em-dash
$_ = str_replace(array('&#8211;', '&#8212;'),
array('-', '--'), $_);
# single quote open close
$_ = str_replace(array('&#8216;', '&#8217;'), "'", $_);
# double quote open close
$_ = str_replace(array('&#8220;', '&#8221;'), '"', $_);
$_ = str_replace('&#8230;', '...', $_); # ellipsis
return $_;
}
function ProcessEscapes($_) {
#
# Parameter: String.
# Returns: The string, with after processing the following backslash
# escape sequences. This is useful if you want to force a "dumb"
# quote or other character to appear.
#
# Escape Value
# ------ -----
# \\ &#92;
# \" &#34;
# \' &#39;
# \. &#46;
# \- &#45;
# \` &#96;
#
$_ = str_replace(
array('\\\\', '\"', "\'", '\.', '\-', '\`'),
array('&#92;', '&#34;', '&#39;', '&#46;', '&#45;', '&#96;'), $_);
return $_;
}
# _TokenizeHTML is shared between PHP SmartyPants and PHP Markdown.
# We only define it if it is not already defined.
if (!function_exists('_TokenizeHTML')) :
function _TokenizeHTML($str) {
#
# Parameter: String containing HTML markup.
# Returns: An array of the tokens comprising the input
# string. Each token is either a tag (possibly with nested,
# tags contained therein, such as <a href="<MTFoo>">, or a
# run of text between tags. Each element of the array is a
# two-element array; the first is either 'tag' or 'text';
# the second is the actual value.
#
#
# Regular expression derived from the _tokenize() subroutine in
# Brad Choate's MTRegex plugin.
# <http://www.bradchoate.com/past/mtregex.php>
#
$index = 0;
$tokens = array();
$match = '(?s:<!(?:--.*?--\s*)+>)|'. # comment
'(?s:<\?.*?\?>)|'. # processing instruction
# regular tags
'(?:<[/!$]?[-a-zA-Z0-9:]+\b(?>[^"\'>]+|"[^"]*"|\'[^\']*\')*>)';
$parts = preg_split("{($match)}", $str, -1, PREG_SPLIT_DELIM_CAPTURE);
foreach ($parts as $part) {
if (++$index % 2 && $part != '')
$tokens[] = array('text', $part);
else
$tokens[] = array('tag', $part);
}
return $tokens;
}
endif;
/*
PHP SmartyPants
===============
Description
-----------
This is a PHP translation of the original SmartyPants quote educator written in
Perl by John Gruber.
SmartyPants is a web publishing utility that translates plain ASCII
punctuation characters into "smart" typographic punctuation HTML
entities. SmartyPants can perform the following transformations:
* Straight quotes (`"` and `'`) into "curly" quote HTML entities
* Backticks-style quotes (` ``like this'' `) into "curly" quote HTML
entities
* Dashes (`--` and `---`) into en- and em-dash entities
* Three consecutive dots (`...`) into an ellipsis entity
SmartyPants does not modify characters within `<pre>`, `<code>`, `<kbd>`,
`<script>`, or `<math>` tag blocks. Typically, these tags are used to
display text where smart quotes and other "smart punctuation" would not
be appropriate, such as source code or example markup.
### Backslash Escapes ###
If you need to use literal straight quotes (or plain hyphens and
periods), SmartyPants accepts the following backslash escape sequences
to force non-smart punctuation. It does so by transforming the escape
sequence into a decimal-encoded HTML entity:
Escape Value Character
------ ----- ---------
\\ &#92; \
\" &#34; "
\' &#39; '
\. &#46; .
\- &#45; -
\` &#96; `
This is useful, for example, when you want to use straight quotes as
foot and inch marks: 6'2" tall; a 17" iMac.
Bugs
----
To file bug reports or feature requests (other than topics listed in the
Caveats section above) please send email to:
<michel.fortin@michelf.com>
If the bug involves quotes being curled the wrong way, please send example
text to illustrate.
### Algorithmic Shortcomings ###
One situation in which quotes will get curled the wrong way is when
apostrophes are used at the start of leading contractions. For example:
'Twas the night before Christmas.
In the case above, SmartyPants will turn the apostrophe into an opening
single-quote, when in fact it should be a closing one. I don't think
this problem can be solved in the general case -- every word processor
I've tried gets this wrong as well. In such cases, it's best to use the
proper HTML entity for closing single-quotes (`&#8217;`) by hand.
Version History
---------------
1.5.1e (9 Dec 2005)
* Corrected a bug that prevented special characters from being
escaped.
1.5.1d (25 May 2005)
* Corrected a small bug in `_TokenizeHTML` where a Doctype declaration
was not seen as HTML (smart quotes where applied inside).
1.5.1c (13 Dec 2004)
* Changed a regular expression in `_TokenizeHTML` that could lead to
a segmentation fault with PHP 4.3.8 on Linux.
1.5.1b (6 Sep 2004)
* Corrected a problem with quotes immediately following a dash
with no space between: `Text--"quoted text"--text.`
* PHP SmartyPants can now be used as a modifier by the Smarty
template engine. Rename the file to "modifier.smartypants.php"
and put it in your smarty plugins folder.
* Replaced a lot of space characters by tabs, saving about 4 KB.
1.5.1a (30 Jun 2004)
* PHP Markdown and PHP Smartypants now share the same `_TokenizeHTML`
function when loaded simultanously.
* Changed the internals of `_TokenizeHTML` to lower the PHP version
requirement to PHP 4.0.5.
1.5.1 (6 Jun 2004)
* Initial release of PHP SmartyPants, based on version 1.5.1 of the
original SmartyPants written in Perl.
Author
------
John Gruber
<http://daringfireball.net/>
Ported to PHP by Michel Fortin
<http://www.michelf.com/>
Additional Credits
------------------
Portions of this plug-in are based on Brad Choate's nifty MTRegex plug-in.
Brad Choate also contributed a few bits of source code to this plug-in.
Brad Choate is a fine hacker indeed. (<http://bradchoate.com/>)
Jeremy Hedley (<http://antipixel.com/>) and Charles Wiltgen
(<http://playbacktime.com/>) deserve mention for exemplary beta testing.
Copyright and License
---------------------
Copyright (c) 2003 John Gruber
<http://daringfireball.net/>
All rights reserved.
Copyright (c) 2004-2005 Michel Fortin
<http://www.michelf.com>
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 "SmartyPants" 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.
*/
?>

View File

@ -0,0 +1,124 @@
<?php
/**
* Another GeSHi example script
*
* Configure your Apache server with 'AcceptPathInfo true' and something like
* 'Alias /viewmysource /var/www/geshi/contrib/aliased.php'. Don't forget
* to protect this alias as necessary.
*
* Usage - visit /viewmysource/file.name.ext to see that file with syntax
* highlighting, where "viewmysource" is the name of the alias you set up.
* You can use this without an alias too, just by visiting
* aliased.php/file.name.ext.
*
* @author Ross Golder <ross@golder.org>
* @version $Id: aliased.php 785 2006-07-19 10:09:45Z oracleshinoda $
*/
// Your config here
define("SOURCE_ROOT", "/var/www/your/source/root/");
// Assume you've put geshi in the include_path already
require_once("geshi.php");
// Get path info
$path = SOURCE_ROOT.$_SERVER['PATH_INFO'];
// Check for dickheads trying to use '../' to get to sensitive areas
$base_path_len = strlen(SOURCE_ROOT);
$real_path = realpath($path);
if(strncmp($real_path, SOURCE_ROOT, $base_path_len)) {
exit("Stop that.");
}
// Check file exists
if(!file_exists($path)) {
exit("File not found ($path).");
}
// Gather contents
$contents = file_get_contents($path);
// Prepare GeSHi instance
$geshi =& new GeSHi($contents, "PHP");
$geshi->set_header_type(GESHI_HEADER_PRE);
$geshi->enable_classes();
$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 10);
$geshi->set_overall_style('color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', true);
$geshi->set_line_style('font: normal normal 95% \'Courier New\', Courier, monospace; color: #003030;', 'font-weight: bold; color: #006060;', true);
$geshi->set_code_style('color: #000020;', 'color: #000020;');
$geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
$geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
$geshi->set_header_content('Source code viewer');
$geshi->set_header_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;');
$geshi->set_footer_content('Parsed in <TIME> seconds, using GeSHi <VERSION>');
$geshi->set_footer_content_style('font-family: Verdana, Arial, sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;');
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Source code viewer - <?php echo $path; ?></title>
<style type="text/css">
<!--
<?php
// Output the stylesheet. Note it doesn't output the <style> tag
echo $geshi->get_stylesheet();
?>
html {
background-color: #f0f0f0;
}
body {
font-family: Verdana, Arial, sans-serif;
margin: 10px;
border: 2px solid #e0e0e0;
background-color: #fcfcfc;
padding: 5px;
}
h2 {
margin: .1em 0 .2em .5em;
border-bottom: 1px solid #b0b0b0;
color: #b0b0b0;
font-weight: normal;
font-size: 150%;
}
h3 {
margin: .1em 0 .2em .5em;
color: #b0b0b0;
font-weight: normal;
font-size: 120%;
}
#footer {
text-align: center;
font-size: 80%;
color: #a9a9a9;
}
#footer a {
color: #9999ff;
}
textarea {
border: 1px solid #b0b0b0;
font-size: 90%;
color: #333;
margin-left: 20px;
}
select, input {
margin-left: 20px;
}
p {
font-size: 90%;
margin-left: .5em;
}
-->
</style>
</head>
<body>
<?php
// The fun part :)
echo $geshi->parse_code();
?>
<hr/>
</body>
</html>

View File

@ -0,0 +1,456 @@
<?php
/*************************************************************************************
* cssgen.php
* ----------
* Author: Nigel McNie (nigel@geshi.org)
* Copyright: (c) 2004 Nigel McNie
* Release Version: 1.0.8.1
* Date Started: 2004/05/20
*
* Application to generate custom CSS files for GeSHi (based on an idea by Andreas
* Gohr)
*
*************************************************************************************
*
* This file is part of GeSHi.
*
* GeSHi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
************************************************************************************/
set_magic_quotes_runtime(0);
//
// Functions
//
function make_header ( $title )
{
echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>GeSHi CSS Generator :: ' . $title . ' </title>
<style type="text/css" media="screen">
<!--
html {
font-family: Verdana, Arial, sans-serif;
font-size: 80%;
background-color: #d0d0d0;
}
body {
margin: 10px;
padding: 5px;
border: 1px solid #f0f0f0;
background-color: #f6f6f6;
}
h1 {
border-bottom: 2px solid #e0e0e0;
font-weight: normal;
font-size: 150%;
color: #c0c0c0;
}
input, textarea {
border: 1px solid #d0d0d0;
}
th {
text-align: right;
font-weight: normal;
}
pre {
font-size: 110%;
color: #202020;
}
#footer {
color: #b0b0b0;
text-align: center;
font-size: 90%;
margin: 0 auto;
border-top: 1px solid #e0e0e0;
}
#footer a {
color: #c0c0c0;
}
-->
</style>
<script type="text/javascript">
function select (state)
{
var cboxes = document.getElementsByTagName(\'input\');
for (var i = 0; i < cboxes.length; i++) {
if (cboxes[i].type == "checkbox") {
if (state == "true") {
cboxes[i].checked = true;
} else if (state == "false") {
cboxes[i].checked = false;
} else if (state == "invert") {
cboxes[i].checked = !cboxes[i].checked;
}
}
}
}
</script>
</head>
<body>
<h1>' . $title . '</h1>
';
}
function make_footer ()
{
echo '<div id="footer"><a href="http://qbnz.com/highlighter/">GeSHi</a> &copy; Nigel McNie, 2004, released under the GPL</div></body>
</html>';
}
function get_var ( $var_name )
{
if ( isset($_GET[$var_name]) )
{
return str_replace("\'", "'", $_GET[$var_name]);
}
elseif ( isset($_POST[$var_name]) )
{
return str_replace("\'", "'", $_POST[$var_name]);
}
return null;
}
//
// Unset everything
//
foreach ( $_REQUEST as $var )
{
unset($$var);
}
foreach ( array(
'_POST' => 'HTTP_POST_VARS',
'_GET' => 'HTTP_GET_VARS',
'_COOKIE' => 'HTTP_COOKIE_VARS',
'_SERVER' => 'HTTP_SERVER_VARS',
'_ENV' => 'HTTP_ENV_VARS',
'_FILES' => 'HTTP_POST_FILES') as $array => $other )
{
if ( !isset($$array) )
{
$$array = $$other;
}
unset($$other);
}
// Get what step we're up to
$step = get_var('step');
if ( !$step || $step == 1 )
{
$errors = 0;
make_header('Step 1');
echo "Welcome to the GeSHi CSS generator.<br /><pre>Searching for GeSHi... ";
// Find GeSHi
$geshi_path = get_var('geshi-path');
$geshi_lang_path = get_var('geshi-lang-path');
if ( !$geshi_path )
{
$geshi_path = '../geshi.php';
}
if ( !$geshi_lang_path )
{
$geshi_lang_path = '../geshi/';
}
if ( is_file($geshi_path) && is_readable($geshi_path) )
{
// Get file contents and see if GeSHi is in here
$file = @file($geshi_path);
$contents = '';
foreach ( $file as $line )
{
$contents .= $line;
}
if ( strpos($contents, '<?php
/**
* GeSHi - Generic Syntax Highlighter') !== false )
{
echo '<span style="color: green;">Found at ' . realpath($geshi_path) . '</span>';
}
else
{
++$errors;
$no_geshi_dot_php_error = true;
echo '<span style="color: red;">Not found</span>';
}
}
else
{
++$errors;
$no_geshi_dot_php_error = true;
echo '<span style="color: red;">Not found</span>';
}
// Find language files
echo "\nSearching for language files... ";
if ( is_readable($geshi_lang_path . 'css-gen.cfg') )
{
echo '<span style="color: green;">Found at ' . realpath($geshi_lang_path) . '</span>';
}
else
{
++$errors;
$no_lang_dir_error = true;
echo '<span style="color: red;">Not found</span>';
}
echo "</pre>\n";
if ( $errors > 0 )
{
// We're gonna have to ask for the paths...
echo 'Unfortunately CSSGen could not detect the following paths. Please input them and press &quot;submit&quot; to try again.';
echo "
<form action=\"cssgen.php\" method=\"post\">";
if ( $no_geshi_dot_php_error )
{
echo "
<br />geshi.php: <input type=\"text\" name=\"geshi-path\" value=\"" . realpath('../geshi.php') . "\" size=\"50\" />";
}
else
{
echo '<input type="hidden" name="geshi-path" value="' . htmlspecialchars($geshi_path) . '" />';
}
if ( $no_lang_dir_error )
{
echo "
<br />language files directory: <input type=\"text\" name=\"geshi-lang-path\" value=\"" . realpath('../geshi/') . "/\" size=\"50\" /> (should have a trailing slash)";
}
else
{
echo '<input type="hidden" name="geshi-lang-path" value="' . $geshi_lang_path . '" />';
}
echo "
<br /><input type=\"submit\" value=\"Search\" /></form>";
}
else
{
// no errors - echo continue form
echo 'Everything seems to be detected successfully. Use the button to continue.
<br /><br /><form action="cssgen.php?step=2" method="post">
<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" />
<input type="submit" value="Step 2" />';
}
make_footer();
}
// Step 2
elseif ( $step == 2 )
{
make_header('Step 2');
$geshi_path = get_var('geshi-path');
$geshi_lang_path = get_var('geshi-lang-path');
$dh = opendir($geshi_lang_path);
$lang_files = array();
$file = readdir($dh);
while ( $file !== false )
{
if ( $file == '.' || $file == '..' || $file == 'CVS' || $file == 'css-gen.cfg' )
{
$file = readdir($dh);
continue;
}
$lang_files[] = $file;
$file = readdir($dh);
}
closedir($dh);
sort($lang_files);
// Now installed languages are in $lang_files
echo '<form action="cssgen.php?step=3" method="post" id="step2">
What languages are you wanting to make this stylesheet for?<br /><br />
Detected languages:<br />';
foreach ( $lang_files as $lang )
{
$lang = substr($lang, 0, strpos($lang, '.'));
if ($lang) {
echo "<input type=\"checkbox\" name=\"langs[$lang]\" checked=\"checked\" />&nbsp;$lang<br />\n";
}
}
echo "Select: <a href=\"javascript:select('true')\">All</a>, <a href=\"javascript:select('false')\">None</a>, <a href=\"javascript:select('invert')\">Invert</a><br />\n";
echo 'If you\'d like any other languages not detected here to be supported, please enter
them here, one per line:<br /><textarea rows="4" cols="20" name="extra-langs"></textarea><br />
';
echo '<br />Styles:
<table>
<tr><th>Style for the overall code block:</th><td><input type="text" name="overall" value="border: 1px dotted #a0a0a0; font-family: \'Courier New\', Courier, monospace; background-color: #f0f0f0; color: #0000bb;" /></td></tr>
<tr><th>Default Styles</th><td><input type="text" name="default-styles" value="font-weight:normal;background:transparent;color:#000; padding-left: 5px;" /></td></tr>
<tr><th>Keywords I (if, do, while etc)</th><td><input type="text" name="keywords-1" value="color: #a1a100;" /></td></tr>
<tr><th>Keywords II (null, true, false etc)</th><td><input type="text" name="keywords-2" value="color: #000; font-weight: bold;" /></td></tr>
<tr><th>Inbuilt Functions (echo, print etc)</th><td><input type="text" name="keywords-3" value="color: #000066;" /></td></tr>
<tr><th>Data Types (int, boolean etc)</th><td><input type="text" name="keywords-4" value="color: #f63333;" /></td></tr>
<tr><th>Comments (//, <!-- --> etc)</th><td><input type="text" name="comments" value="color: #808080;" /></td></tr>
<tr><th>Escaped Characters (\n, \t etc)</th><td><input type="text" name="escaped-chars" value="color: #000033; font-weight: bold;" /></td></tr>
<tr><th>Brackets ( ([{}]) etc)</th><td><input type="text" name="brackets" value="color: #66cc66;" /></td></tr>
<tr><th>Strings ("foo" etc)</th><td><input type="text" name="strings" value="color: #ff0000;" /></td></tr>
<tr><th>Numbers (1, -54, 2.5 etc)</th><td><input type="text" name="numbers" value="color: #ff33ff;" /></td></tr>
<tr><th>Methods (Foo.bar() etc)</th><td><input type="text" name="methods" value="color: #006600;" /></td></tr>
</table>';
echo '<input type="hidden" name="geshi-path" value="' . realpath($geshi_path) . '" /><input type="hidden" name="geshi-lang-path" value="' . realpath($geshi_lang_path) . '" />
<input type="submit" value="Step 3" /></form>';
make_footer();
}
// Step 3
elseif ( $step == 3 )
{
make_header('Step 3');
echo '<p>Here is your completed stylesheet. Note that it may not be perfect - no regular expression styles are included for one thing,
you\'ll have to add those yourself (php and xml are just two languages that use them), and line numbers are not included, however
it includes most of the basic information.</p>';
// Make the stylesheet
$part_selector_1 = '';
$part_selector_2 = '';
$part_selector_3 = '';
$langs = get_var('langs');
$extra_langs = trim(get_var('extra-langs'));
if ( $extra_langs != '' )
{
$l = explode("\r\n", $extra_langs);
foreach ( $l as $lng )
{
$langs[$lng] = true;
}
}
foreach ( $langs as $lang => $dummy )
{
$part_selector_1 .= ".$lang {PART}, ";
$part_selector_2 .= ".$lang {PART1}, .$lang {PART2}, ";
$part_selector_3 .= ".$lang {PART1}, .$lang {PART2}, .$lang {PART3}, ";
}
$part_selector_1 = substr($part_selector_1, 0, -2);
$part_selector_2 = substr($part_selector_2, 0, -2);
$part_selector_3 = substr($part_selector_3, 0, -2);
$default_styles = get_var('default-styles');
$ol_selector = str_replace('{PART}', 'ol', $part_selector_1);
$overall_styles = get_var('overall');
$overall_selector = str_replace('{PART}', '', $part_selector_1);
$stylesheet = "/* GeSHi (c) Nigel McNie 2004 (http://qbnz.com/highlighter) */";
if ( $overall != '' )
{
$stylesheet .= "\n$overall_selector {{$overall_styles}}";
}
if ( $default_styles != '' )
{
$default_selector = str_replace(array('{PART1}', '{PART2}'), array('.de1', '.de2'), $part_selector_2);
$stylesheet .= "\n$default_selector {{$default_styles}}";
}
// Do keywords
$keywords_1 = get_var('keywords-1');
$keyword_selector_1 = str_replace('{PART}', '.kw1', $part_selector_1);
if ( $keywords_1 != '' )
{
$stylesheet .= "\n$keyword_selector_1 {{$keywords_1}}";
}
$keywords_2 = get_var('keywords-2');
$keyword_selector_2 = str_replace('{PART}', '.kw2', $part_selector_1);
if ( $keywords_2 != '' )
{
$stylesheet .= "\n$keyword_selector_2 {{$keywords_2}}";
}
$keywords_3 = get_var('keywords-3');
$keyword_selector_3 = str_replace('{PART}', '.kw3', $part_selector_1);
if ( $keywords_3 != '' )
{
$stylesheet .= "\n$keyword_selector_3 {{$keywords_3}}";
}
$keywords_4 = get_var('keywords-4');
$keyword_selector_4 = str_replace('{PART}', '.kw4', $part_selector_1);
if ( $keywords_4 != '' )
{
$stylesheet .= "\n$keyword_selector_4 {{$keywords_4}}";
}
// Do other lexics
$comments = get_var('comments');
$comment_selector = str_replace(array('{PART1}', '{PART2}', '{PART3}'), array('.co1', '.co2', '.coMULTI'), $part_selector_3);
if ( $comments != '' )
{
$stylesheet .= "\n$comment_selector {{$comments}}";
}
$esc = get_var('escaped-chars');
$esc_selector = str_replace('{PART}', '.es0', $part_selector_1);
if ( $esc != '' )
{
$stylesheet .= "\n$esc_selector {{$esc}}";
}
$brackets = get_var('brackets');
$brk_selector = str_replace('{PART}', '.br0', $part_selector_1);
if ( $brackets != '' )
{
$stylesheet .= "\n$brk_selector {{$brackets}}";
}
$strings = get_var('strings');
$string_selector = str_replace('{PART}', '.st0', $part_selector_1);
if ( $strings != '' )
{
$stylesheet .= "\n$string_selector {{$strings}}";
}
$numbers = get_var('numbers');
$num_selector = str_replace('{PART}', '.nu0', $part_selector_1);
if ( $numbers != '' )
{
$stylesheet .= "\n$num_selector {{$numbers}}";
}
$methods = get_var('methods');
$method_selector = str_replace('{PART}', '.me0', $part_selector_1);
if ( $methods != '' )
{
$stylesheet .= "\n$method_selector {{$methods}}";
}
echo "<pre>$stylesheet</pre>";
make_footer();
}
?>

View File

@ -0,0 +1,59 @@
<?php
/**
* A simple script which outputs the CSS classes for all languages
* supported by GeSHi. You can access it directly to download
* the CSS file. On *NIX you can also do a simple `php cssgen.php > geshi.css`.
*
* This file is part of GeSHi.
*
* GeSHi is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* GeSHi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GeSHi; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* @package geshi
* @subpackage contrib
* @author revulo <revulon@gmail.com>
* @copyright 2008 revulo
* @license http://gnu.org/copyleft/gpl.html GNU GPL
*
*/
require dirname(dirname(__FILE__)) . DIRECTORY_SEPARATOR . 'geshi.php';
$geshi = new GeSHi;
$languages = array();
if ($handle = opendir($geshi->language_path)) {
while (($file = readdir($handle)) !== false) {
$pos = strpos($file, '.');
if ($pos > 0 && substr($file, $pos) == '.php') {
$languages[] = substr($file, 0, $pos);
}
}
closedir($handle);
}
sort($languages);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="geshi.css"');
echo "/**\n".
" * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann\n" .
" * (http://qbnz.com/highlighter/ and http://geshi.org/)\n".
" */\n";
foreach ($languages as $language) {
$geshi->set_language($language);
// note: the false argument is required for stylesheet generators, see API documentation
$css = $geshi->get_stylesheet(false);
echo preg_replace('/^\/\*\*.*?\*\//s', '', $css);
}

View File

@ -0,0 +1,217 @@
<?php
/**
* GeSHi example script
*
* Just point your browser at this script (with geshi.php in the parent directory,
* and the language files in subdirectory "../geshi/")
*
* @author Nigel McNie
* @version $Id: example.php 1512 2008-07-21 21:05:40Z benbe $
*/
header('Content-Type: text/html; charset=utf-8');
error_reporting(E_ALL);
// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but
// it could be in the current directory if the include_path is set. There's nowhere else
// we can reasonably guess.
if (is_readable('../geshi.php')) {
$path = '../';
} elseif (is_readable('geshi.php')) {
$path = './';
} else {
die('Could not find geshi.php - make sure it is in your include path!');
}
require $path . 'geshi.php';
$fill_source = false;
if (isset($_POST['submit'])) {
if (get_magic_quotes_gpc()) {
$_POST['source'] = stripslashes($_POST['source']);
}
if (!strlen(trim($_POST['source']))) {
$_POST['language'] = preg_replace('#[^a-zA-Z0-9\-_]#', '', $_POST['language']);
$_POST['source'] = implode('', @file($path . 'geshi/' . $_POST['language'] . '.php'));
$_POST['language'] = 'php';
} else {
$fill_source = true;
}
// Here's a free demo of how GeSHi works.
// First the initialisation: source code to highlight and the language to use. Make sure
// you sanitise correctly if you use $_POST of course - this very script has had a security
// advisory against it in the past because of this. Please try not to use this script on a
// live site.
$geshi = new GeSHi($_POST['source'], $_POST['language']);
// Use the PRE_VALID header. This means less output source since we don't have to output &nbsp;
// everywhere. Of course it also means you can't set the tab width.
// HEADER_PRE_VALID puts the <pre> tag inside the list items (<li>) thus producing valid HTML markup.
// HEADER_PRE puts the <pre> tag around the list (<ol>) which is invalid in HTML 4 and XHTML 1
// HEADER_DIV puts a <div> tag arount the list (valid!) but needs to replace whitespaces with &nbsp
// thus producing much larger overhead. You can set the tab width though.
$geshi->set_header_type(GESHI_HEADER_PRE_VALID);
// Enable CSS classes. You can use get_stylesheet() to output a stylesheet for your code. Using
// CSS classes results in much less output source.
$geshi->enable_classes();
// Enable line numbers. We want fancy line numbers, and we want every 5th line number to be fancy
$geshi->enable_line_numbers(GESHI_FANCY_LINE_NUMBERS, 5);
// Set the style for the PRE around the code. The line numbers are contained within this box (not
// XHTML compliant btw, but if you are liberally minded about these things then you'll appreciate
// the reduced source output).
$geshi->set_overall_style('font: normal normal 90% monospace; color: #000066; border: 1px solid #d0d0d0; background-color: #f0f0f0;', false);
// Set the style for line numbers. In order to get style for line numbers working, the <li> element
// is being styled. This means that the code on the line will also be styled, and most of the time
// you don't want this. So the set_code_style reverts styles for the line (by using a <div> on the line).
// So the source output looks like this:
//
// <pre style="[set_overall_style styles]"><ol>
// <li style="[set_line_style styles]"><div style="[set_code_style styles]>...</div></li>
// ...
// </ol></pre>
$geshi->set_line_style('color: #003030;', 'font-weight: bold; color: #006060;', true);
$geshi->set_code_style('color: #000020;', true);
// Styles for hyperlinks in the code. GESHI_LINK for default styles, GESHI_HOVER for hover style etc...
// note that classes must be enabled for this to work.
$geshi->set_link_styles(GESHI_LINK, 'color: #000060;');
$geshi->set_link_styles(GESHI_HOVER, 'background-color: #f0f000;');
// Use the header/footer functionality. This puts a div with content within the PRE element, so it is
// affected by the styles set by set_overall_style. So if the PRE has a border then the header/footer will
// appear inside it.
$geshi->set_header_content('<SPEED> <TIME> GeSHi &copy; 2004-2007, Nigel McNie, 2007-2008 Benny Baumann. View source of example.php for example of using GeSHi');
$geshi->set_header_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-bottom: 1px solid #d0d0d0; padding: 2px;');
// You can use <TIME> and <VERSION> as placeholders
$geshi->set_footer_content('Parsed in <TIME> seconds at <SPEED>, using GeSHi <VERSION>');
$geshi->set_footer_content_style('font-family: sans-serif; color: #808080; font-size: 70%; font-weight: bold; background-color: #f0f0ff; border-top: 1px solid #d0d0d0; padding: 2px;');
} else {
// make sure we don't preselect any language
$_POST['language'] = null;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>GeSHi examples</title>
<style type="text/css">
<!--
<?php
if (isset($_POST['submit'])) {
// Output the stylesheet. Note it doesn't output the <style> tag
echo $geshi->get_stylesheet(true);
}
?>
html {
background-color: #f0f0f0;
}
body {
font-family: Verdana, Arial, sans-serif;
margin: 10px;
border: 2px solid #e0e0e0;
background-color: #fcfcfc;
padding: 5px;
}
h2 {
margin: .1em 0 .2em .5em;
border-bottom: 1px solid #b0b0b0;
color: #b0b0b0;
font-weight: normal;
font-size: 150%;
}
h3 {
margin: .1em 0 .2em .5em;
color: #b0b0b0;
font-weight: normal;
font-size: 120%;
}
#footer {
text-align: center;
font-size: 80%;
color: #a9a9a9;
}
#footer a {
color: #9999ff;
}
textarea {
border: 1px solid #b0b0b0;
font-size: 90%;
color: #333;
margin-left: 20px;
}
select, input {
margin-left: 20px;
}
p {
font-size: 90%;
margin-left: .5em;
}
-->
</style>
</head>
<body>
<h2>GeSHi Example Script</h2>
<p>To use this script, make sure that <strong>geshi.php</strong> is in the parent directory or in your
include_path, and that the language files are in a subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p>
<p>Enter your source and a language to highlight the source in and submit, or just choose a language to
have that language file highlighted in PHP.</p>
<?php
if (isset($_POST['submit'])) {
// The fun part :)
echo $geshi->parse_code();
echo '<hr />';
}
?>
<form action="<?php echo basename($_SERVER['PHP_SELF']); ?>" method="post">
<h3>Source to highlight</h3>
<p>
<textarea rows="10" cols="60" name="source" id="source"><?php echo $fill_source ? htmlspecialchars($_POST['source']) : '' ?></textarea>
</p>
<h3>Choose a language</h3>
<p>
<select name="language" id="language">
<?php
if (!($dir = @opendir(dirname(__FILE__) . '/geshi'))) {
if (!($dir = @opendir(dirname(__FILE__) . '/../geshi'))) {
echo '<option>No languages available!</option>';
}
}
$languages = array();
while ($file = readdir($dir)) {
if ( $file[0] == '.' || strpos($file, '.', 1) === false) {
continue;
}
$lang = substr($file, 0, strpos($file, '.'));
$languages[] = $lang;
}
closedir($dir);
sort($languages);
foreach ($languages as $lang) {
if (isset($_POST['language']) && $_POST['language'] == $lang) {
$selected = 'selected="selected"';
} else {
$selected = '';
}
echo '<option value="' . $lang . '" '. $selected .'>' . $lang . "</option>\n";
}
?>
</select>
</p>
<p>
<input type="submit" name="submit" value="Highlight Source" />
<input type="submit" name="clear" onclick="document.getElementById('source').value='';document.getElementById('language').value='';return false" value="clear" />
</p>
</form>
<div id="footer">GeSHi &copy; Nigel McNie, 2004, released under the GNU GPL<br />
For a better demonstration, check out the <a href="http://qbnz.com/highlighter/demo.php">online demo</a>
</div>
</body>
</html>

View File

@ -0,0 +1,666 @@
<?php
/**
* GeSHi example script
*
* Just point your browser at this script (with geshi.php in the parent directory,
* and the language files in subdirectory "../geshi/")
*
* @author Nigel McNie
* @version $Id: langcheck.php 1971 2008-12-25 15:14:14Z benbe $
*/
header('Content-Type: text/html; charset=utf-8');
set_time_limit(0);
error_reporting(E_ALL);
$time_start = explode(' ', microtime());
define ('TYPE_NOTICE', 0);
define ('TYPE_WARNING', 1);
define ('TYPE_ERROR', 2);
$error_abort = false;
$error_cache = array();
function output_error_cache(){
global $error_cache, $error_abort;
if(count($error_cache)) {
echo "<span style=\"color: #F00; font-weight: bold;\">Failed</span><br />";
echo "<ol>\n";
foreach($error_cache as $error_msg) {
echo "<li>";
switch($error_msg['t']) {
case TYPE_NOTICE:
echo "<span style=\"color: #080; font-weight: bold;\">NOTICE:</span>";
break;
case TYPE_WARNING:
echo "<span style=\"color: #CC0; font-weight: bold;\">WARNING:</span>";
break;
case TYPE_ERROR:
echo "<span style=\"color: #F00; font-weight: bold;\">ERROR:</span>";
break;
}
echo " " . $error_msg['m'] . "</li>";
}
echo "</ol>\n";
} else {
echo "<span style=\"color: #080; font-weight: bold;\">OK</span><br />";
}
echo "\n";
$error_cache = array();
}
function report_error($type, $message) {
global $error_cache, $error_abort;
$error_cache[] = array('t' => $type, 'm' => $message);
if(TYPE_ERROR == $type) {
$error_abort = true;
}
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>GeSHi Language File Validation Script</title>
<style type="text/css">
<!--
html {
background-color: #f0f0f0;
}
body {
font-family: Verdana, Arial, sans-serif;
margin: 10px;
border: 2px solid #e0e0e0;
background-color: #fcfcfc;
padding: 5px;
font-size: 10pt;
}
h2 {
margin: .1em 0 .2em .5em;
border-bottom: 1px solid #b0b0b0;
color: #b0b0b0;
font-weight: normal;
font-size: 150%;
}
h3 {
margin: .1em 0 .2em .5em;
color: #b0b0b0;
font-weight: normal;
font-size: 120%;
}
#footer {
text-align: center;
font-size: 80%;
color: #a9a9a9;
}
#footer a {
color: #9999ff;
}
textarea {
border: 1px solid #b0b0b0;
font-size: 90%;
color: #333;
margin-left: 20px;
}
select, input {
margin-left: 20px;
}
p {
font-size: 90%;
margin-left: .5em;
}
-->
</style>
</head>
<body>
<h2>GeSHi Language File Validation Script</h2>
<p>To use this script, make sure that <strong>geshi.php</strong> is in the
parent directory or in your include_path, and that the language files are in a
subdirectory of GeSHi's directory called <strong>geshi/</strong>.</p>
<p>Everything else will be done by this script automatically. After the script
finished you should see messages of what could cause trouble with GeSHi or where
your language files can be improved. Please be patient, as this might take some time.</p>
<ol>
<li>Checking where to find GeSHi installation ... <?php
// Rudimentary checking of where GeSHi is. In a default install it will be in ../, but
// it could be in the current directory if the include_path is set. There's nowhere else
// we can reasonably guess.
if (is_readable('../geshi.php')) {
$path = '../';
} elseif (is_readable('geshi.php')) {
$path = './';
} else {
report_error(TYPE_ERROR, 'Could not find geshi.php - make sure it is in your include path!');
}
if(!$error_abort) {
require $path . 'geshi.php';
if(!class_exists('GeSHi')) {
report_error(TYPE_ERROR, 'The GeSHi class was not found, although it seemed we loaded the correct file!');
}
}
if(!$error_abort) {
if(!defined('GESHI_LANG_ROOT')) {
report_error(TYPE_ERROR, 'There\'s no information present on where to find the language files!');
} else if(!is_dir(GESHI_LANG_ROOT)) {
report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" given, does not ressemble a directory!');
} else if(!is_readable(GESHI_LANG_ROOT)) {
report_error(TYPE_ERROR, 'The path "'.GESHI_LANG_ROOT.'" is not readable to this script!');
}
}
output_error_cache();
if(!$error_abort) {
echo "</li>\n<li>Listing available language files ... ";
if (!($dir = @opendir(GESHI_LANG_ROOT))) {
report_error(TYPE_ERROR, 'Error requesting listing for available language files!');
}
$languages = array();
if(!$error_abort) {
while ($file = readdir($dir)) {
if (!$file || $file[0] == '.' || strpos($file, '.') === false) {
continue;
}
$lang = substr($file, 0, strpos($file, '.'));
$languages[] = $lang;
}
closedir($dir);
}
$languages = array_unique($languages);
sort($languages);
if(!count($languages)) {
report_error(TYPE_WARNING, 'Unable to locate any usable language files in "'.GESHI_LANG_ROOT.'"!');
}
output_error_cache();
}
if (isset($_REQUEST['show']) && in_array($_REQUEST['show'], $languages)) {
$languages = array($_REQUEST['show']);
}
if(!$error_abort) {
foreach ($languages as $lang) {
echo "</li>\n<li>Validating language file for '$lang' ... ";
$langfile = GESHI_LANG_ROOT . $lang . '.php';
unset($language_data);
if(!is_file($langfile)) {
report_error(TYPE_ERROR, 'The path "' .$langfile. '" does not ressemble a regular file!');
} else if(!is_readable($langfile)) {
report_error(TYPE_ERROR, 'Cannot read file "' .$langfile. '"!');
} else {
$langfile_content = file_get_contents($langfile);
if(preg_match("/\?>(?:\r?\n|\r(?!\n)){2,}\Z/", $langfile_content)) {
report_error(TYPE_ERROR, 'Language file contains trailing empty lines at EOF!');
}
if(!preg_match("/\?>(?:\r?\n|\r(?!\n))?\Z/", $langfile_content)) {
report_error(TYPE_ERROR, 'Language file contains no PHP end marker at EOF!');
}
if(preg_match("/\t/", $langfile_content)) {
report_error(TYPE_NOTICE, 'Language file contains unescaped tabulator chars (probably for indentation)!');
}
if(preg_match('/^(?: )*(?! )(?! \*) /m', $langfile_content)) {
report_error(TYPE_NOTICE, 'Language file contains irregular indentation (other than 4 spaces per indentation level)!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?Author:((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not contain a specification of an author!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?Copyright:((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not contain a specification of the copyright!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?Release Version:((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not contain a specification of the release version!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?Date Started:((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not contain a specification of the date it was started!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?This file is part of GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not state that it belongs to GeSHi!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?language file for GeSHi\.((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not state that it is a language file for GeSHi!');
}
if(!preg_match("/\/\*\*((?!\*\/).)*?GNU General Public License((?!\*\/).)*?\*\//s", $langfile_content)) {
report_error(TYPE_WARNING, 'Language file does not state that it is provided under the terms of the GNU GPL!');
}
unset($langfile_content);
include $langfile;
if(!isset($language_data)) {
report_error(TYPE_ERROR, 'Language file does not contain a $language_data structure to check!');
} else if (!is_array($language_data)) {
report_error(TYPE_ERROR, 'Language file contains a $language_data structure which is not an array!');
}
}
if(!$error_abort) {
if(!isset($language_data['LANG_NAME'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'LANG_NAME\'] specification!');
} else if (!is_string($language_data['LANG_NAME'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'LANG_NAME\'] specification which is not a string!');
}
if(!isset($language_data['COMMENT_SINGLE'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_SIGNLE\'] structure to check!');
} else if (!is_array($language_data['COMMENT_SINGLE'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_SINGLE\'] structure which is not an array!');
}
if(!isset($language_data['COMMENT_MULTI'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'COMMENT_MULTI\'] structure to check!');
} else if (!is_array($language_data['COMMENT_MULTI'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_MULTI\'] structure which is not an array!');
}
if(isset($language_data['COMMENT_REGEXP'])) {
if (!is_array($language_data['COMMENT_REGEXP'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'COMMENT_REGEXP\'] structure which is not an array!');
}
}
if(!isset($language_data['QUOTEMARKS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'QUOTEMARKS\'] structure to check!');
} else if (!is_array($language_data['QUOTEMARKS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'QUOTEMARKS\'] structure which is not an array!');
}
if(isset($language_data['HARDQUOTE'])) {
if (!is_array($language_data['HARDQUOTE'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HARDQUOTE\'] structure which is not an array!');
}
}
if(!isset($language_data['ESCAPE_CHAR'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'ESCAPE_CHAR\'] specification to check!');
} else if (!is_string($language_data['ESCAPE_CHAR'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification which is not a string!');
} else if (1 < strlen($language_data['ESCAPE_CHAR'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'ESCAPE_CHAR\'] specification is not empty or exactly one char!');
}
if(!isset($language_data['CASE_KEYWORDS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_KEYWORDS\'] specification!');
} else if (!is_int($language_data['CASE_KEYWORDS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is not an integer!');
} else if (GESHI_CAPS_NO_CHANGE != $language_data['CASE_KEYWORDS'] &&
GESHI_CAPS_LOWER != $language_data['CASE_KEYWORDS'] &&
GESHI_CAPS_UPPER != $language_data['CASE_KEYWORDS']) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_KEYWORDS\'] specification which is neither of GESHI_CAPS_NO_CHANGE, GESHI_CAPS_LOWER nor GESHI_CAPS_UPPER!');
}
if(!isset($language_data['KEYWORDS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'KEYWORDS\'] structure to check!');
} else if (!is_array($language_data['KEYWORDS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'KEYWORDS\'] structure which is not an array!');
} else {
foreach($language_data['KEYWORDS'] as $kw_key => $kw_value) {
if(!is_integer($kw_key)) {
report_error(TYPE_WARNING, "Language file contains an key '$kw_key' in \$language_data['KEYWORDS'] that is not integer!");
} else if (!is_array($kw_value)) {
report_error(TYPE_ERROR, "Language file contains a \$language_data['CASE_SENSITIVE']['$kw_value'] structure which is not an array!");
}
}
}
if(!isset($language_data['SYMBOLS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SYMBOLS\'] structure to check!');
} else if (!is_array($language_data['SYMBOLS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SYMBOLS\'] structure which is not an array!');
}
if(!isset($language_data['CASE_SENSITIVE'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'CASE_SENSITIVE\'] structure to check!');
} else if (!is_array($language_data['CASE_SENSITIVE'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'CASE_SENSITIVE\'] structure which is not an array!');
} else {
foreach($language_data['CASE_SENSITIVE'] as $cs_key => $cs_value) {
if(!is_integer($cs_key)) {
report_error(TYPE_WARNING, "Language file contains an key '$cs_key' in \$language_data['CASE_SENSITIVE'] that is not integer!");
} else if (!is_bool($cs_value)) {
report_error(TYPE_ERROR, "Language file contains a Case Sensitivity specification for \$language_data['CASE_SENSITIVE']['$cs_value'] which is not a boolean!");
}
}
}
if(!isset($language_data['URLS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'URLS\'] structure to check!');
} else if (!is_array($language_data['URLS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'URLS\'] structure which is not an array!');
} else {
foreach($language_data['URLS'] as $url_key => $url_value) {
if(!is_integer($url_key)) {
report_error(TYPE_WARNING, "Language file contains an key '$url_key' in \$language_data['URLS'] that is not integer!");
} else if (!is_string($url_value)) {
report_error(TYPE_ERROR, "Language file contains a Documentation URL specification for \$language_data['URLS']['$url_value'] which is not a string!");
} else if (preg_match('#&([^;]*(=|$))#U', $url_value)) {
report_error(TYPE_ERROR, "Language file contains unescaped ampersands (&amp;) in \$language_data['URLS']!");
}
}
}
if(!isset($language_data['OOLANG'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OOLANG\'] specification!');
} else if (!is_int($language_data['OOLANG']) && !is_bool($language_data['OOLANG'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither boolean nor integer!');
} else if (false !== $language_data['OOLANG'] &&
true !== $language_data['OOLANG'] &&
2 !== $language_data['OOLANG']) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OOLANG\'] specification which is neither of false, true or 2!');
}
if(!isset($language_data['OBJECT_SPLITTERS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'OBJECT_SPLITTERS\'] structure to check!');
} else if (!is_array($language_data['OBJECT_SPLITTERS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'OBJECT_SPLITTERS\'] structure which is not an array!');
}
if(!isset($language_data['REGEXPS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'REGEXPS\'] structure to check!');
} else if (!is_array($language_data['REGEXPS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'REGEXPS\'] structure which is not an array!');
}
if(!isset($language_data['STRICT_MODE_APPLIES'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STRICT_MODE_APPLIES\'] specification!');
} else if (!is_int($language_data['STRICT_MODE_APPLIES'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is not an integer!');
} else if (GESHI_MAYBE != $language_data['STRICT_MODE_APPLIES'] &&
GESHI_ALWAYS != $language_data['STRICT_MODE_APPLIES'] &&
GESHI_NEVER != $language_data['STRICT_MODE_APPLIES']) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STRICT_MODE_APPLIES\'] specification which is neither of GESHI_MAYBE, GESHI_ALWAYS nor GESHI_NEVER!');
}
if(!isset($language_data['SCRIPT_DELIMITERS'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'SCRIPT_DELIMITERS\'] structure to check!');
} else if (!is_array($language_data['SCRIPT_DELIMITERS'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'SCRIPT_DELIMITERS\'] structure which is not an array!');
}
if(!isset($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure to check!');
} else if (!is_array($language_data['HIGHLIGHT_STRICT_BLOCK'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'HIGHLIGHT_STRICT_BLOCK\'] structure which is not an array!');
}
if(isset($language_data['TAB_WIDTH'])) {
if (!is_int($language_data['TAB_WIDTH'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is not an integer!');
} else if (1 > $language_data['TAB_WIDTH']) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'TAB_WIDTH\'] specification which is less than 1!');
}
}
if(isset($language_data['PARSER_CONTROL'])) {
if (!is_array($language_data['PARSER_CONTROL'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'PARSER_CONTROL\'] structure which is not an array!');
}
}
if(!isset($language_data['STYLES'])) {
report_error(TYPE_ERROR, 'Language file contains no $language_data[\'STYLES\'] structure to check!');
} else if (!is_array($language_data['STYLES'])) {
report_error(TYPE_ERROR, 'Language file contains a $language_data[\'STYLES\'] structure which is not an array!');
} else {
$style_arrays = array('KEYWORDS', 'COMMENTS', 'ESCAPE_CHAR',
'BRACKETS', 'STRINGS', 'NUMBERS', 'METHODS', 'SYMBOLS',
'REGEXPS', 'SCRIPT');
foreach($style_arrays as $style_kind) {
if(!isset($language_data['STYLES'][$style_kind])) {
report_error(TYPE_ERROR, "Language file contains no \$language_data['STYLES']['$style_kind'] structure to check!");
} else if (!is_array($language_data['STYLES'][$style_kind])) {
report_error(TYPE_ERROR, "Language file contains a \$language_data['STYLES\']['$style_kind'] structure which is not an array!");
} else {
foreach($language_data['STYLES'][$style_kind] as $sk_key => $sk_value) {
if(!is_int($sk_key) && ('COMMENTS' != $style_kind && 'MULTI' != $sk_key)
&& !(('STRINGS' == $style_kind || 'ESCAPE_CHAR' == $style_kind) && 'HARD' == $sk_key)) {
report_error(TYPE_WARNING, "Language file contains an key '$sk_key' in \$language_data['STYLES']['$style_kind'] that is not integer!");
} else if (!is_string($sk_value)) {
report_error(TYPE_WARNING, "Language file contains a CSS specification for \$language_data['STYLES']['$style_kind'][$key] which is not a string!");
}
}
}
}
unset($style_arrays);
}
}
if(!$error_abort) {
//Initial sanity checks survived? --> Let's dig deeper!
foreach($language_data['KEYWORDS'] as $key => $keywords) {
if(!isset($language_data['CASE_SENSITIVE'][$key])) {
report_error(TYPE_ERROR, "Language file contains no \$language_data['CASE_SENSITIVE'] specification for keyword group $key!");
}
if(!isset($language_data['URLS'][$key])) {
report_error(TYPE_ERROR, "Language file contains no \$language_data['URLS'] specification for keyword group $key!");
}
if(empty($keywords)) {
report_error(TYPE_WARNING, "Language file contains an empty keyword list in \$language_data['KEYWORDS'] for group $key!");
}
foreach($keywords as $id => $kw) {
if(!is_string($kw)) {
report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['KEYWORDS'][$key][$id]!");
} else if (!strlen($kw)) {
report_error(TYPE_ERROR, "Language file contains an empty string entry at \$language_data['KEYWORDS'][$key][$id]!");
} else if (preg_match('/^([\(\)\{\}\[\]\^=.,:;\-+\*\/%\$\"\'\?]|&[\w#]\w*;)+$/i', $kw)) {
report_error(TYPE_NOTICE, "Language file contains an keyword ('$kw') at \$language_data['KEYWORDS'][$key][$id] which seems to be better suited for the symbols section!");
}
}
if(count($keywords) != count(array_unique($keywords))) {
$kw_diffs = array_count_values($keywords);
foreach($kw_diffs as $kw => $kw_count) {
if($kw_count > 1) {
report_error(TYPE_WARNING, "Language file contains per-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key]!");
}
}
}
}
$disallowed_before = "(?<![a-zA-Z0-9\$_\|\#;>|^&";
$disallowed_after = "(?![a-zA-Z0-9_\|%\\-&;";
foreach($language_data['KEYWORDS'] as $key => $keywords) {
foreach($language_data['KEYWORDS'] as $key2 => $keywords2) {
if($key2 <= $key) {
continue;
}
$kw_diffs = array_intersect($keywords, $keywords2);
foreach($kw_diffs as $kw) {
if(isset($language_data['PARSER_CONTROL']['KEYWORDS'])) {
//Check the precondition\post-cindition for the involved keyword groups
$g1_pre = $disallowed_before;
$g2_pre = $disallowed_before;
$g1_post = $disallowed_after;
$g2_post = $disallowed_after;
if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'])) {
$g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
$g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_BEFORE'];
}
if(isset($language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'])) {
$g1_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
$g2_post = $language_data['PARSER_CONTROL']['KEYWORDS']['DISALLOWED_AFTER'];
}
if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'])) {
$g1_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_BEFORE'];
}
if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'])) {
$g1_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key]['DISALLOWED_AFTER'];
}
if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'])) {
$g2_pre = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_BEFORE'];
}
if(isset($language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'])) {
$g2_post = $language_data['PARSER_CONTROL']['KEYWORDS'][$key2]['DISALLOWED_AFTER'];
}
if($g1_pre != $g2_pre || $g1_post != $g2_post) {
continue;
}
}
report_error(TYPE_WARNING, "Language file contains cross-group duplicate keyword '$kw' in \$language_data['KEYWORDS'][$key] and \$language_data['KEYWORDS'][$key2]!");
}
}
}
foreach($language_data['CASE_SENSITIVE'] as $key => $keywords) {
if(!isset($language_data['KEYWORDS'][$key]) && $key != GESHI_COMMENTS) {
report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['CASE_SENSITIVE'] specification for non-existing keyword group $key!");
}
}
foreach($language_data['URLS'] as $key => $keywords) {
if(!isset($language_data['KEYWORDS'][$key])) {
report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['URLS'] specification for non-existing keyword group $key!");
}
}
foreach($language_data['STYLES']['KEYWORDS'] as $key => $keywords) {
if(!isset($language_data['KEYWORDS'][$key])) {
report_error(TYPE_WARNING, "Language file contains an superfluous \$language_data['STYLES']['KEYWORDS'] specification for non-existing keyword group $key!");
}
}
foreach($language_data['COMMENT_SINGLE'] as $ck => $cv) {
if(!is_int($ck)) {
report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_SINGLE'] that is not integer!");
}
if(!is_string($cv)) {
report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_SINGLE'][$ck]!");
}
if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
}
}
if(isset($language_data['COMMENT_REGEXP'])) {
foreach($language_data['COMMENT_REGEXP'] as $ck => $cv) {
if(!is_int($ck)) {
report_error(TYPE_WARNING, "Language file contains an key '$ck' in \$language_data['COMMENT_REGEXP'] that is not integer!");
}
if(!is_string($cv)) {
report_error(TYPE_WARNING, "Language file contains an non-string entry at \$language_data['COMMENT_REGEXP'][$ck]!");
}
if(!isset($language_data['STYLES']['COMMENTS'][$ck])) {
report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['COMMENTS'] specification for comment group $ck!");
}
}
}
foreach($language_data['STYLES']['COMMENTS'] as $ck => $cv) {
if($ck != 'MULTI' && !isset($language_data['COMMENT_SINGLE'][$ck]) &&
!isset($language_data['COMMENT_REGEXP'][$ck])) {
report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['COMMENTS'] specification for Single Line or Regular-Expression Comment key $ck!");
}
}
if (isset($language_data['STYLES']['STRINGS']['HARD'])) {
if (empty($language_data['HARDQUOTE'])) {
report_error(TYPE_NOTICE, "Language file contains superfluous \$language_data['STYLES']['STRINGS'] specification for key 'HARD', but no 'HARDQUOTE's are defined!");
}
unset($language_data['STYLES']['STRINGS']['HARD']);
}
foreach($language_data['STYLES']['STRINGS'] as $sk => $sv) {
if($sk && !isset($language_data['QUOTEMARKS'][$sk])) {
report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['STRINGS'] specification for non-existing quotemark key $sk!");
}
}
foreach($language_data['REGEXPS'] as $rk => $rv) {
if(!is_int($rk)) {
report_error(TYPE_WARNING, "Language file contains an key '$rk' in \$language_data['REGEXPS'] that is not integer!");
}
if(is_string($rv)) {
//Check for unmasked / in regular expressions ...
if(empty($rv)) {
report_error(TYPE_WARNING, "Language file contains an empty regular expression at \$language_data['REGEXPS'][$rk]!");
} else {
if(preg_match("/(?<!\\\\)\//s", $rv)) {
report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
} elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv)) {
report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
}
}
} elseif(is_array($rv)) {
if(!isset($rv[GESHI_SEARCH])) {
report_error(TYPE_ERROR, "Language file contains no GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
} elseif(!is_string($rv[GESHI_SEARCH])) {
report_error(TYPE_ERROR, "Language file contains a GESHI_SEARCH entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
} else {
if(preg_match("/(?<!\\\\)\//s", $rv[GESHI_SEARCH])) {
report_error(TYPE_WARNING, "Language file contains a regular expression with an unmasked / character at \$language_data['REGEXPS'][$rk]!");
} elseif (preg_match("/(?<!<)(\\\\\\\\)*\\\\\|(?!>)/s", $rv[GESHI_SEARCH])) {
report_error(TYPE_WARNING, "Language file contains a regular expression with an unescaped match for a pipe character '|' which needs escaping as '&lt;PIPE&gt;' instead at \$language_data['REGEXPS'][$rk]!");
}
}
if(!isset($rv[GESHI_REPLACE])) {
report_error(TYPE_WARNING, "Language file contains no GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
} elseif(!is_string($rv[GESHI_REPLACE])) {
report_error(TYPE_ERROR, "Language file contains a GESHI_REPLACE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
}
if(!isset($rv[GESHI_MODIFIERS])) {
report_error(TYPE_WARNING, "Language file contains no GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
} elseif(!is_string($rv[GESHI_MODIFIERS])) {
report_error(TYPE_ERROR, "Language file contains a GESHI_MODIFIERS entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
}
if(!isset($rv[GESHI_BEFORE])) {
report_error(TYPE_WARNING, "Language file contains no GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
} elseif(!is_string($rv[GESHI_BEFORE])) {
report_error(TYPE_ERROR, "Language file contains a GESHI_BEFORE entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
}
if(!isset($rv[GESHI_AFTER])) {
report_error(TYPE_WARNING, "Language file contains no GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk]!");
} elseif(!is_string($rv[GESHI_AFTER])) {
report_error(TYPE_ERROR, "Language file contains a GESHI_AFTER entry in extended regular expression at \$language_data['REGEXPS'][$rk] which is not a string!");
}
} else {
report_error(TYPE_WARNING, "Language file contains an non-string and non-array entry at \$language_data['REGEXPS'][$rk]!");
}
if(!isset($language_data['STYLES']['REGEXPS'][$rk])) {
report_error(TYPE_WARNING, "Language file contains no \$language_data['STYLES']['REGEXPS'] specification for regexp group $rk!");
}
}
foreach($language_data['STYLES']['REGEXPS'] as $rk => $rv) {
if(!isset($language_data['REGEXPS'][$rk])) {
report_error(TYPE_NOTICE, "Language file contains an superfluous \$language_data['STYLES']['REGEXPS'] specification for regexp key $rk!");
}
}
}
output_error_cache();
flush();
if($error_abort) {
break;
}
}
}
?></li>
</ol>
<p>Validation process completed in <?
$time_end = explode(' ', microtime());
$time_diff = $time_end[0] + $time_end[1] - $time_start[0] - $time_start[1];
echo sprintf("%.2f", $time_diff);
?> seconds.</p>
<div id="footer">GeSHi &copy; 2004-2007 Nigel McNie, 2007-2008 Benny Baumann, released under the GNU GPL</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
BUGS - list of known bugs in GeSHi
Version 1.0.8
- Number highlighting is quite poor [possibly better now]
- I'm not happy with URLS - there still could be extra bugs, and it's rather unflexible
(see TODO for a possible fix)
- "Important" sections for some reason seem to have their spans added after every
newline up until the next lexic, instead of stopping at the <END GeSHi> part. In fact,
context sensitiveness is quite poor...
- Using the extra line number highlighting feature without actually using line numbers
will result in malformed XHTML (not sure about this one though...)
- Slow!!! Especially for source with lots of strings in it. GeSHi will work acceptably
for sourcecode under 5K (for simple language files like SQL, a 100K file can be
highlighted in just 6 seconds), but above about 25K things get a little slow... If
you're using this as part of some larger software, you may want to think about
making some sort of "cache" effect to speed things up and reduce server load.
- The result is built by string replacement instead of by building another string based
on the source, that would be much safer. The focus of releases beyond 1.0.7 will be on
changing this behaviour, which may well fix some of the other bugs mentioned above.
- As of 1.0.7.1, dots (.) are allowed before keywords. This may change highlighting of some
things slightly, if you notice anything odd about the highlighting then please report
it to me.
- Perl/Javascript /.../ regex syntax is only supported basically and there's no
guarantee it is working all the time.
- The <pre> header output is not XHTML compliant. Please use the <div> header instead.
Send any bug reports to BenBE@omorphia.de, or submit them via the bug tracker at
sourceforge (http://sourceforge.net/tracker/?group_id=114997&atid=670231)

View File

@ -0,0 +1,682 @@
CHANGES - Changelog for GeSHi (geshi.php only)
Changes to the code are listed under the version they occured in, with who suggested
it by each one (if there's nobody listed as suggesting it I dreamed it up :)). Users
who suggested an idea often also provided the code that was used as a basis for the
changes - thanks to all who suggested these ideas and gave me the code to show me how!
Language files listed under each version were made by the author beside them, and then
modified by me for consistency/bug fixing.
Please send any bug reports to BenBE@omorphia.de, or use the bug report tracker
at sourceforge (http://sourceforge.net/tracker/?group_id=114997&atid=670231)
Version 1.0.8.3
- Added language files
* DCS (Stelio Passaris)
* Locomotive Basic (Nacho Cabanes)
* LSL2 (Linden Scripting Language) (William Fry)
* Modula-3 (Martin Bishop)
* Oberon-2 (Mike Mol)
* Rebol (Lecanu Guillaume)
- Fixed a problem where HardEscapes weren't working when no escape char was given (BenBE)
- Added a PARSER_CONTROL setting to treat whitespace inside of keywords in
the language file as "any whitespace" in the source (i.e. "CREATE TABLE"
in SQL will match "CREATE\s+TABLE" instead of literally matching) (BenBE)
- Added a possibility to allow setting the style for escape characters (BenBE)
- Improvements to language files (BenBE)
* Added some missing Perl keywords and obscure default variables (BenBE)
* Allow for escaped colons to appear in CSS names (BenBE, simon)
* Added multiline continuation suppoert of preprocessor defines for
C, C for Mac, C++ and CC++ with Qt support (BenBE)
* keywords for C-based languages are case-sensitive (BenBE)
* Broken AutoIt highlighting (BenBE)
* Problem with escaped backslash in PHP and D (BenBE)
* Added some more functions for PHP (BenBE)
* Some changes for AppleScript (Stefan Klieme)
* Forbid highlighting keywords followed by / in bash (BenBE)
* Updated the LaTeX file to link some keywords (BenBE)
* Additional text rendered when matching special variables for PowerShell (BenBE)
* Added some more keywords for ABAP (BenBE, Sandra Rossi, Jacob Laursen)
Version 1.0.8.2
- Added language files
* Brainfuck \ Brainfork (Benny Baumann)
* HQ9+ (Benny Baumann)
* INTERCAL (Benny Baumann)
* LOLcode (Benny Baumann)
* LScript (Beau McGuigan)
* Pixel Bender (Richard Olsson)
* ProvideX (Jeff Wilder)
* VIM Script (Swaroop C H)
* Visual Prolog (Thomas Linder Puls)
* Whitespace (Benny Baumann)
- Changed priority for COMMENT_REGEXP compared to String highlighting (BenBE)
- Fixed correct escaping of spaces inside of URLs (BenBE)
- Updated the list of common file extensions (BenBE)
- Updated the language file check script in contrib/ (BenBE)
- Fixed a problem with link targets resulting in unclickable links (SF#2379120, BenBE)
- Fixed an undefined variable issue in langcheck.php (BenBE)
- Improvements to language files (BenBE)
* eMail Header highlighting now uses the correct delimiters for keywords (BenBE)
* eMail (RFC822\mbox) highlighting now highlights IPs, MIME types and
subfield assignments correctly (BenBE)
* Minor style changes in COBOL to improve loading performance (BenBE)
* Added some missing keywords for D (BenBE)
* Removed duplicate keywords from Progres, SAS and TSQL (BenBE)
* Fixed Heredoc Syntax for Bash (SF#2185319, BenBE)
* Moved symbol-lookalike sequences from keyword groups to separate symbol group
for languages asp, klonec, klonecpp, php, php-brief (BenBE)
* Fixed a lot of duplicate keyword warnings (BenBE)
* Added missing keywords to the Python language file,
introducing support for Python 3.0. (SF#2441839, milian)
* Updated documentation links for TypoScript (SF#2014276, BenBE)
* Fixed a problem with tag and attribute names in XML highlighting (SF#2276119, BenBE)
* Improved MySQL language file (BenBE, JavaWoman)
* Some commentss accidentially mistaken for DocComments (SF#2454897, BenBE)
* Added improved Escape Char handling for c, c_mac, cpp and cpp_qt (SF#2458743, BenBE)
Version 1.0.8.1
- Added language files
* AviSynth (Ryan Jones)
* eMail \ mbox (Benny Baumann)
* GNU Make (Neil Bird)
* Oracle 11i support (Simon Redhead)
* Prolog (Benny Baumann)
* SciLab (Christophe David)
* TeraTerm macro language (Boris Maisuradze)
- Added support for Escape Regular Expressions (BenBE)
* Implemented C-style Escapes in PHP (BenBE)
* Introduced support for \xAB and \007 style Char Escapes in PHP (BenBE)
* Implemented Variable Highlighting in PHP (BenBE)
* Implemented Variable Highlighting in Bash (milian)
- Fixed a problem with PCRE patterns for Keyword matching sometimes producing
very large strings, that could not be handled by some versions of PCRE lib,
causing broken highlighting an Regexp Compile errors (BenBE, milian)
- Fixed broken highlighting of bash commands like `dbus-send --dest=org.....`,
i.e. the dest was highlighted as variable declaration (milian)
- Fixed broken highlighting of some symbols in their escaped form (BenBE)
(<SEMI> and <PIPE> were accidentially filtered even though they are valid)
- Fixed a "memory leak" in the *_regexp_caches (milian)
- Fixed broken Escape chars if classes were disabled
- start_line_numbers_at() was ignored when GESHI_HEADER_PRE_TABLE was set (revulo)
- Fixed a problem allowing Remote Code Inclusion under certain circumstances (BenBE)
- Changes to default CSS in order to make the GESHI_HEADER_PRE_TABLE align properly,
even on Windows / Mac systems with strange fonts (milian, revulo, ^RT)
- Minor style changes to the following languages:
* cpp-qt (milian)
* MySQL (BenBE)
* PHP (BenBE)
- Improvements to language files (BenBE, milian)
* Added MinSpareThread\MaxSpareThreads to Apache highlighter (BenBE)
* Added new Keyword group for APT sources.list highlighter (BenBE)
* Fixed highlighting in LaTeX for \begin{} and \end{}, i.e. the stuff inside
the curly braces. (milian, thanks for the report go to Matthias Pospiech)
* Improved String support for D (BenBE)
* MySQL was seriously broken (BenBE)
* Reworked Keyword groups for MySQL to allow for more configuration (BenBE)
* Improved Mirc script language file (milian)
* Improved C++ Qt language file (milian)
* Minor bug with Transpose Operator in Matlab (BenBE, Daniele de Rigo)
* Highlighting of Batch Files for Windows (BenBE)
* Updated AutoIt to include latest changes for AutoIt v3.2.12.1 (BenBE, Thierry)
* Fixed duplicate keyword warnings for Perl, Tcl and Typoscript (BenBE)
* Fixed Doc-URL getting reparsed by highlighted keywords of other groups (BenBE, Jordi Boggiano)
Version 1.0.8
- Added language files
* APT sources.list (milian)
* Boo (Marcus Griep)
* CIL (Common Intermediate Language, .NET Assembly) (Marcus Griep)
* COBOL (Benny Baumann)
* Gnuplot (milian)
* KLoneC (Mickael Auger)
* KLoneC++ (Mickael Auger)
* PIC16xxx assembler (Phil Mattison)
* POV-Ray (Carl Fürstenberg)
* PowerShell (Frode Aarebrot)
* Progress (Marco Aurelio de Pasqual)
* TypoScript (Jan-Philipp Halle)
* Xorg configuration (milian)
- Make GeSHi's constructor arguments optional, so something like `$foo = new GeSHi;` is possible. (milian)
- Added an optimizer for lists to regular expressions. Using these cached lists results in a speedup of approx. 50%.
The slightly increased memory consumption (~150KB for PHP language file) is more than worth it! (milian)
- Some more memory & speed optimizations all over GeSHi (milian)
* Reduced memory overhead when highlighting keywords (BenBE)
* Keyword Linking now uses considerably less strtolower calls (milian)
* Cache Symbol Search Regexp and make Symbol Highlighting faster (milian)
* Use more native functions like substr_replace and strcasecmp to speed things up (milian)
* Use considerably less strlen() calls on various points by caching the results (milian)
* Properly set comments to be case insensitive where appropriate to increase performance (milian)
* Improve the performance of the strict mode tokenizer, making highlighting of languages like
HTML, ColdFusion or XML faster (milian)
* Setup caches for parsing on demand to make stylesheet generators fast (milian)
- Various improvements to Strict Block Handling (BenBE, milian)
* Added support for RegExp-based Strict Blocks (BenBE)
* Fixed highlighting incorrectly stopping at ?> in PHP (SF#1330968, BenBE)
* Languages with STRICT_MODE_APPLIES = GESHI_MAYBE default to strict mode now. When no highlightable
code is found in this mode, we fallback to the same setting as if GESHI_NEVER was set. That way it
should not be needed to call enable_strictmode() manually. (milian)
- Added new GESHI_HEADER_PRE_VALID type which uses the following markup: (milian)
* With line numbers: <div>header<ol><li><pre>...</pre></li>...</ol></div>
* Without line numbers: <pre>header...CODE...</pre>
=> valid HTML and no need for &nbsp; indentation
- Added new GESHI_HEADER_PRE_TABLE type which can be used to prevent linenumber-selection in Firefox
on copy'n'paste. (milian)
- set_language will not reset any language settings by default anymore.
* Added $force_reset param for to force full reload of a language. (milian)
* Make sure strict_mode is set properly when doing repeated set_language calls (milian)
- Fixed some problems with old PHP versions (SF#1975625, milian, BenBE)
- Fixed broken use with Suhosin Patch when /e modifier was disabled (SF#2021800, BenBE)
- Added support for external style information files to override language defaults without modifying language files (BenBE)
- The overall_class is now up to the user, and the language-code is _always_ added as a class (milian)
- Fixed Economy Mode for GeSHi::get_stylesheet() - now it just makes so much more sense! (milian)
- Fixed Economy Mode when COMMENT_REGEXP are used (BenBE)
- Changed the default encoding to use UTF-8, due to SF#2037598, BenBE)
- Improved overall string support:
* Added support for multichar string delimiters (SF#1932083, BenBE)
* Fixed problems of unfinished strings and comments producing invalid XHTML (SF#1996353, BenBE)
* Multichar Quotemarks sometimes had inconsistent behaviour (BenBE)
* Support for multiple styles of strings depending on the starter (BenBE)
* Properly handle escapes in strings, i.e. '\\' was not working properly before (milian)
* Fixed escape char support when an escape char is followed by multi-byte chars (SF#2037598, BenBE)
- Improved flexibility in language files (BenBE, milian)
* Added PARSER_CONTROL for OOLANG method highlighting (SF#1923060, BenBE)
* Added possibility to define strict blocks using an Regexp (BenBE)
* Removed explicit escaping of / in Regular Expressions (BenBE)
* Ignoring empty keyword groups when highlighting (milian)
* Make language_permissions configurable in language files via ['PARSER_CONTROL']['ENABLE_FLAGS']
this makes is_a calls unneeded and thus prevents PHP notices in PHP 5.x (milian)
* Extended support for number formats now covering the most common formats (SF#1923058, BenBE)
* Lifted a limitation that keywords had to have at least 2 subsequent letters (BenBE)
* Changed behaviour of PARSER_CONTROL now allowing to provide the full Lookahead and Lookbehind
expressions used as delimiters inside keywords instead of a simple char group (BenBE)
* Fixed improper handling of newlines in REGEXPS so this does not produce invalid html anylonger (milian)
- Some typos and mistakes in the documentation (BenBE)
- Added a script to contrib/ to verify language files are correct (BenBE)
- Fixed loads of compliancy warnings detected with that automated compliance testing script (BenBE)
- Many other improvements to various language files (BenBE, milian)
* Reduce strict errors & notices for language files (milian)
* Fixed symbol highlighting with C++ sometimes missing keywords after ; and comments (BenBE)
* Improved comment handling with TCL (Lars Hellström, BenBE)
* Fixed broken handling with XML comments (BenBE, SF#1849233)
* Fixed HTML comments spawning multiple lines producing invalid XHTML output (SF#1738173, BenBE)
* Added support for parameters beginning with dash in BASH language (BenBE)
* Support Apache's configuration sections, see http://httpd.apache.org/docs/2.2/sections.html (milian)
* Minor issue with PHP Heredoc and Nowdoc syntax sometimes not getting highlighted (BenBE)
* Updated Objective-C language file (SF#2013961, Quinn Taylor, BenBE)
* Added some keywords for VHDL (beshig, BenBE)
* Fixed severly broken ColdFusion language file (milian)
* Fixed some incorrectly highlighted things with the CSS language file (milian, BenBE)
* Improved Smarty language file (milian)
* Improved CSS language file (milian)
* Improved Pascal language file (milian)
* Improved LaTeX language file (Андрей Парамонов, BenBE)
* Fixed a regular expression in mIRC language file that caused a warning message to be issued (BenBE)
* Removed <, > and / from HTML names, now only containing the real tag names (BenBE)
* Use spaces instead of tabs for indendation in language files to have a consistent
coding standard accross geshi files (milian)
* Added some comment styles, keywords and added index highlighting (Chusslove Illich, Часлав Илић)
- Removed some private methods which were only called at exactly one place (milian)
* format_header_content
* format_footer_content
* get_attributes
- Second part of default style changes. Affected in this release:
* C++
* C++ (QT)
* CSS
* VHDL
Version 1.0.7.22
- Added language files
* glSlang (BenBE)
* KiXtart (Riley McArdle)
* Lotus Notes @Formulas (Richard Civil)
* LotusScript (Richard Civil)
* MXML (David Spurr)
* Scala (Franco Lombardo)
* ActionScript 3 (Jordi Boggiano)
* GNU Gettext .po/.pot (Milian Wolff)
* Verilog (Günter Dannoritzer)
- Fixed a problem not yet addressed in 1.0.7.21 regarding highlighting of
symbols that caused some extra characters to be added in the output or
broke highlighting and standard compliance due to missing escaping of
internally used characters (SF#192320 and SF#1926259, BenBE)
- Fixed missing style information for ocaml language file (The_PHP_Jedi)
- Fixed a bug causing masses of warnings in rendered output if language file
miss style information (The_PHP_Jedi, BenBE)
- Missing tab width information could lead to warnings (BenBE)
- Missing symbol information for ASP (SF#1952038, nfsupport, BenBE)
- Empty delimiter message with OOoBasic (BenBE, Ccornell)
- Escaping of comments in LaTeX ignored (SF#1749806, BenBE)
- Modified Math environment $$ in LaTeX to be non-greedy (BenBE)
- Added possibility to match a regexp as comment (SF#1914640, SF#1945301, SF#1934832, BenBE)
- Introduced C-Style multiline continuation comments (SF#1914640, SF#1945301, BenBE)
- Introduced Fortran Comments (SF#1914640, SF#1934832, BenBE)
- Implemented Heredoc and Nowdoc Syntax for PHP and Perl (SF#1914640, BenBE)
- Implemented Compiler Directives for Delphi (SF#1914640, BenBE)
- Implemented minimalistic support for JavaScript \ Perl Regular Expressions (SF#1786665, SF#1754333, SF#1956631, BenBE)
- Fixed Strings in Matlab to be handled as comments instead of regexps, to prevent keywords being linked (BenBE)
- Applied PARSER_CONTROL fix of CPP for CPP-QT-Derivative (BenBE)
- Fixed incorrect treatment of unequally long multiline comment separators (related to SF #1891630, BenBE)
- Added PARSER_CONTROL settings for keywords in ASM language file (SF#1835148, BenBE)
- Fixed missing CASSE_SENSITIVE entry for DOS language file (SF#1956314, BenBE)
- Fixed accidential highlighting of keywords in argument names (SF#1956456, Milian Wolff, BenBE)
- Fixed yet again some #-related bash problem (SF#1956459, Milian Wolff, BenBE)
- Added backticks as symbols (Milian Wolff)
- Example script remembers selections and source submitted (Milian Wolff)
- Example script allows remembered source and preselected language to be cleared (Milian Wolff)
- Example script now properly includes geshi and doesn't suppress error messages anylonger. (Milian Wolff)
- Code cleanup by using direct string indexing instead of substr with length 1 (Milian Wolff)
- Optimized generation of code parts in strict mode (Milian Wolff)
- Optimized COMMENT_REGEXP by using an incremental regexp cache (Milian Wolff, BenBE)
- Fixed a problem that rarely skipped highlighting of escaped chars which usually should have gotten highlighted (BenBE)
- Optimized generation of highlighted strings to use fast skip forward while highlighting them (Milian Wolff, BenBE)
- Optimization using basic rework of indent function improving tab expansion performance (BenBE)
- Lots of other minor optimizations based on coding style improvements (Milian Wolff)
- Implemented setting to force spans to be closed before newlines, see SF#1727398 (Milian Wolff)
- Added missing credits for D language file to THANKS file (SF#1720899, BenBE)
- Optimization to prevent loading the current language file twice (Milian Wolff)
- Optimization: Use file_get_contents() to load sourcecode from files.
Even if GeSHi worked with PHP 4.1 before, it doesn't now. (Milian Wolff)
- Added description of extra language features (SF#1970248, BenBE)
- Added support for highlighting the C# using and namespace directives (SF #1395677, BenBE)
- Added support for highlighting the Java import and package directives (SF #1395677, BenBE)
- Fixed minor problem in Haskell cuasing accidential start of comment (SF#1987221, BenBE)
- Fixed minor issue causing loads of warnings if a language files defines no symbols (BenBE)
- Updated some aspects of the documentation and included further hints (BenBE)
- First of series of color scheme changes. Affected languages (sofar):
* Assembler (x86)
* Bash
* C
* C#
* Delphi
* Fortran77
* glSlang
* Java & Java 5
* JavaScript
* OCaml
* OpenOffice.org Basic
* Pascal
* Perl
* PHP and PHP-Brief
Version 1.0.7.21
- Added language files
* Basic4GL (Matthew Webb)
- Fixed problem with mIRC language highlighting spaces only (BenBE)
- Language files can now specify a function to be called to decide the
colour of a regular expression match
- Added single quote to Lua (Darrin Roenfanz)
- Compare comments case insensitively (fixes AutoIT comments somewhat)
(Daniel Gordon)
- Fixed symbols not being highlighted at all (SF #1767953, BenBE)
- Fixed brackets not correctly managed (SF #1767954, BenBE)
- Changed default languages for some extensions
- Included color and character information for symbol highlighting in some languages (BenBE)
- Fixed a problem with extension detection if default was used (BenBE)
- Fixed a highlighting problem with the LaTeX language (SF #1776182, BenBE)
- Added a new parameter for enable_highlighting to reduce source duplication (SF #1786104, BenBE)
- Updated doxygen documentation to include since tags and some missing parameters
- Disabled symbol highlighting by default (doesn't affect brackets, cf. documentation) (BenBE)
- Added a check for set_case_keywords for the given param to be supported (BenBE)
- Minor rework of the HTML documentation layout \ W3C compliance (BenBE)
- Fixed highlighting error in bash language avoiding keywords in comments (SF #1786314, SF #1564839, BenBE)
- Fixed template params for C++ and C# not being highlighted (SF #1772919, BenBE)
- Fixed more reported problems about mirc highlighting
- Added some missing keywords for VB.NET
- Fixed some warnings in DOS language file (Florian Angehrn)
- Add possibility to handle more than one extra line style (SF #1698255, German Rumm, BenBE)
- Fixed handling of URLs when output case differs from URL case (SF #1815504, Tom Samstag, BenBE)
- Fixed POD (Plain Old Documentation) format problems breaking highlighting of Perl (SF #1891630, Shannon Wynter, BenBE)
- Fixed a problem with mIRC when & was used for identifiers (SF #1875552, BenBE)
Version 1.0.7.20
- Added language files
* Genero (logic) and Per (forms) (FOURJ's Genero 4GL) (Lars Gersmann)
* Haskell (Dagit)
* ABAP (Andres Picazo)
* Motorola 68k Assembler (for MC68HC908GP32 Microcontroller) (BenBE)
* Dot (Adrien Friggeri)
- Fixed java documentation search for keywords to actually go to the
documentation (spaze)
- Applied fix for bug 1688864 (bad regexes) (Tim Starling)
- Fixed comment CSS rule in visualfoxpro
- ThinBASIC language update (Eros Olmi)
- mIRC language update (BenBE)
- Fixed outdated documentation URL of Perl language file (RuralMoon by BenBE)
- Fixed tab replacement code not generating the correct number of spaces in
some cases (Guillermo Calvo)
- Fixed two typos in Z80 language file
- Applied fix for bug 1730168 (Daniel Naber)
- Applied fix for bug 1705482 (Jason Frame)
* Configurable line endings (Replace \n by custom string)
* per-language tab-widths (Adjustable for width>=1)
* Included defaults for ASM (x86, m68k, z80), C, C (Mac), C++, C++ (QT), C#,
Delphi, CSS,, HTML, PHP, PHP (Brief), QBasic, Ruby, XML
- Added a possibility to force generation of a surrounding tag around
the highlighted source
- Applied fix for additional keywords for the bash language
(cf. http://bash.thefreebizhost.com/bash_geshi.php, BenBE / Jan G)
- Fix bad colour definition in GML language (Andreas Gohr)
- Fixed phpdoc comments not being indented one space if they should be (Andy
Hassall)
Version 1.0.7.19
- Added language files
* X++ (Simon Butcher)
* Rails (Moises Deniz)
- Fixed invalid HTML being generated and doctypes not being highlighted over
multiple lines properly when line numbers are on (Validome)
- Improved the ruby syntax highlighting by basing it off the Rails file
- Changed some regular expressions to possibly help with badly performing
regex support in PHP (Tim Starling)
- Allow {TIME}, {LANGUAGE} and {VERSION} to be used in the header as well as
the normal <TIME>/<LANGUAGE>/<VERSION> (AthanD)
- Changed comment regex in bash to prevent malformed XHTML (rv1971)
Version 1.0.7.18
- Added language files
* ZiLOG Z80 Assembly (BenBE)
- Fixed incorrect highlighting when the starter of a multiline comment is
longer than the ender (Robert Anthony).
- Fixed "</span" generated if a multiline comment is the last thing in the
source (related to the above).
- Added #cs => #ce comment markers to AutoIT (Robert Anthony)
- Fixed spelling mistake for keyword in Python (wd3)
- Added a method to enable/disable keyword linking (Ian McKellar)
- Improved empty line detection for HTML output (BenBE)
- Changed code style of geshi.php, and removed tabs
Version 1.0.7.17
- Fixed up ends of files having too many newlines (binarygroop)
- Removed background colour on keyword group in eiffel (Julian Tschannen)
- Removed GESHI_DIR_SEPARATOR constant usage, it's unnecessary (Aleksey Zapparov)
- Added /* ... */ comments to coldfusion (Jeff Howden)
Version 1.0.7.16
- Added language files
* ActionScript (Steffen Krause)
* C++/QT (Iulian M)
* PL/SQL (Victor Engmark)
- Fixed up my e-mail address everywhere
- Fixed notice with "error" property (IZIU Zielona Góra)
- Added some entries to the get_language_name_from_extension table
(Stebastian Schuberth)
Version 1.0.7.15
- Added language files
* BNF (Rowan Rodrik van der Molen)
* IO (me, thanks to Johnathan Wright)
* mIRC (Alberto de Areba Sánchez)
- Fixed use of colon in XML (Grigory Rubtsov)
- Fixed notices in text.php, reg.php and latex.php when $this is not
available (Clemens Weiß)
- Made third parameter of geshi_highlight optional (Gaetano Giunta)
- Fix incorrect highlighting of the $# variable in bash (Michael Knight)
- Fixed single line comment mistake in thinbasic.php (Eros Olmi)
Version 1.0.7.14
- Added language files
* thinBasic (Eros Olmi)
* LaTeX (Matthais Pospiech)
- Removed extra newlines at the end of some files
- Fixed SF bug 1556404 - check before using $this in language files
(Clemens Weiß)
Version 1.0.7.13
- Added language files
* Uno IDL (Cedric Bosdonnat)
- Fixed add_ids causing odd XHTML (RyanJ)
- Fixed extra newline being added to end of result (Andreas Gohr)
Version 1.0.7.12
- Fixed lines being collapsed when they contain just a space (artlover)
- Allowed matching for regexes using start/end matchers at the start/end
of the code (Sheri)
- Added (dubious) fix for google "I'm feeling lucky" search for java keywords
(dubious in that it doesn't work for me)
- mysql - Made the symbols into their own keyword group as the symbol group
isn't used. Added a style for multiline comments.
- Added a couple of php5 keywords to the php language files.
- Allow XML tags to have dashes.
- Changed LANG_NAME for many languages to be more sensible/correct case
(Matthias Mohr)
- Added case-sensitivity indices to python
Version 1.0.7.11
- Added language files
* Smalltalk (Bananeweizen)
- Minor style improvements to matlab
- Moved a couple of functions to the correct group in smarty (arwan)
Version 1.0.7.10
- Added language files
* TCL (Reid van Melle)
* Winbatch (Craig Storey)
* Groovy (Ivan F. Villanueva B.)
* Text (SmokingRope)
* Reg (SmokingRope)
- Removed \ as an escape character in T-SQL (Dave Jackson)
- Reset extra lines to highlight if source is changed (Diogo Resende)
- Allow setting of lexic permissions in language files (SmokingRope)
- Allow regexes to set a CSS class name (SmokingRope)
- Added URL support to DOS language (mastrboy)
Version 1.0.7.9
- Added language files
* Fortran (Cedric Arrabie)
* SAS (Galen Johnson)
* CFDG (John Horigan)
- Fixed & in URL in java5 (Clemens Weiß)
- Added MD5 and SHA1 to mysql keywords (polarina)
- Fixes for highlight_lines_extra with line numbers (ithcy)
- Fixed backslash characters being removed (ArTourter)
Version 1.0.7.8
- Fixed blank at start of MySQL file (W. Tasin)
- Fixed smarty functions being broken (ultrabob)
- Changed keyword and regexp detection and parsing
slightly to allow more "meta characters" (like #) in
keywords
- Minor fixes for XML and GML
Version 1.0.7.7
- Added language files
* T-SQL (Duncan Lock)
* Robots.txt (Christian Lescuyer)
* AutoIT (mastrboy)
* Java 5 (Clemens Bruckmann)
* ColdFusion (Diego)
- A few keyword changes in java, removed :: object splitter (amphi)
- Now using a simpler regular expression for numbers (Brice Bernard)
- Fixed ah, bh etc. regs being highlighted as numbers (Unknown)
Version 1.0.7.6
- Fix backtick-string highlighting in ruby (Juan J. Martínez)
- Add =begin multiline comments in ruby (Juan J. Martínez)
- Added support for :keywords and ::access in lisp (Denis Mashkevich)
- Prevented number highlighting if they are just after underscores (Joce)
- Removed escape characters for strings in XML and HTML (floele)
- Added instanceof keyword to java (jgottschling)
- Fixed comments in ASP (SBD)
- Removed unnecessary keyword style index from ini
- Added support for " strings in ini
- Removed unnecessary regex style index from blitzbasic
- Keyword case of URL-ed keywords should be defined by language file (Benny Baumann)
- Added "Hardquote" feature, provides more accurate string highlighting (Cliff Stanford)
- Used hardquote support for @"..." strings in C# (Cliff Stanford)
- Used hardquote support for ' strings in perl (Cliff Stanford)
- Fixed setting of language path (Cliff Stanford)
- Display source correctly formatted with line numbers (if requested) if an error
has occured (several people)
- Having no source to highlight is not an error condition anymore
- Delphi language updated to include more keywords and types (BenBE)
- Updated NSIS to version 2.11 (deguix)
Version 1.0.7.5
- Fix for using escape characters to escape newlines breaking XHTML compliance (Yves Goergen)
- Fixed method highlighting in VB (Matt Beale)
- Fixed multiline comment highlighting in SQL (MrBaseball34)
- Fixed two ">" symbols being outputted when using a footer but not CSS classes (MrBaseball34)
- Marked important block stuff as deprecated
- Some documentation tidyup
- Updated GML language file (Jos? Jorge Enr?quez Rodr?guez)
- THANKS file tidied up
- Fixed double </a> for elements in HTML (Yves Goergen)
- Added some keywords for ASM (Dreuzzo)
Version 1.0.7.4
- Added language files
* MySQL (Carl Fürstenberg)
* BlitzBasic (Pàdraig O`Connel)
- Fixed up geshi_highlight function: it now correctly uses <code> instead of <div> (Remi Faure)
- When using GESHI_HEADER_NONE, remove the <ol> if line numbering is not enabled
- Commented example.php so people can use it as a guide better
- Fixed extra newline being generated if a comment is at the end
of the source (many people, including Yves Goergen)
- Fixed up some documentation issues
- Some minor language file fixes (C++, Lua) (Lua fixes by chromix)
- Fixed up no </span> in XML and other strict languages (regression from 1.0.7.3 fix: removed
unnecessary </span> when using strict mode) (Daniel Ecer, drskrud),
Version 1.0.7.3
- Added language files
* Scheme (Jon Raphaelson)
* Ocaml and Ocaml-brief (Flaie)
* Ruby (Amit Gupta)
- Make urls generated for java highlighting XHTML compliant (Tim Van Wassenhove)
- Removed unnecessary </span> when using strict mode (Tim Van Wassenhove)
- Fixed warning in dos.php about undefined constant (Tim Van Wassenhove)
- Fixed security hole in contrib/example.php - able to view any file if source
not set and language is set to wierd value (Maksymilian Arciemowicz)
Version 1.0.7.2
- Added language files
* Inno (Thomas Klinger)
* Ini (Deguix)
* DOS (Batchfile) (Alessandro Staltali)
* Applescript (Stephan Klimek)
* Freebasic (Roberto Rossi)
* SDLBasic (Roberto Rossi)
* ActionScript (links to French documentation) (NikO)
- NSIS language file updated (deguix)
- Lua language file updated (Roberto Rossi)
- Bugfix: Styles incorrectly overriding default styles instead of being merged
in set_*_styles methods (Stebastian Werner)
- Added GESHI_HEADER_NONE as valid header type. This still allows header content.
Version 1.0.7.1
- Added language files:
* Div (Gabriel Lorenzo)
* GML (José Jorge Enríquez Rodríguez)
* Eiffel (Zoran Simic)
- Minor change to rules regarding when keywords can appear - now dots (.) are
allowed before keywords. (NikO)
- Bugfix: the line style for non-fancy lines when fancy highlighting is enabled
is now applied (Amit Gupta)
Version 1.0.7
- Added language files:
* Diff (Conny Brunnkvist)
* VHDL (Alexander Krause)
* D (Thomas Kuehne)
* Matlab (Florian Knorn)
- Python highlighting improved (thither, Federico Quagliata)
- Changed file comments to use phpdoc syntax, and changed code style to be more
like PEAR
- Fixed bug in set_code_style: Second parameter is now optional
- The $_GESHI_ERRORS array is gone, error messages are internal to the GeSHi class
- Changed name of XML language to XML from HTML
- Removed min and max tab width checks
- Backported GeSHi 1.1.X's automatic language file path detection so you no longer
need to use the third parameter of the constructor or set_language_path except for
special circumstances.
- Source is checked to make sure it is not empty else an error occurs
- Removed excess characters after ?> in ada.php, apache.php and cpp.php that caused
http headers to be sent (psichron)
- Removed second "foreach" keyword for smarty language file that was causing
duplication (Iss)
- Added underscore to allowed characters in match for XML tags (anonymous)
- Added some missing java keywords like "abstract" and "transient"
- Added "list" and "continue" PHP keywords
- set_language resets error status and strict mode (Andrew Black)
- Removed margin:0 declaration from cssgen.php (Andrzej Kubaszek)
- Fixed multiline comment selector in cssgen.php (Andrzej Kubaszek)
Version 1.0.6
- Added support for smart tabs - tabs that behave just like normal tabs when in
GESHI_HEADER_DIV mode.
- Partial patch for UTF-8 encoding applied (doesn't quite work however...)
Version 1.0.5
- Added language files:
* MPASM (Bakalex)
* Oracle 8 (Guy Wicks)
- Fixed bug where not using an encoding type would sometime result in warnings (although
there still seems to be issues with encoding in general that I'm trying to gather more
data on) (Alexander Spennemann)
- Removed "margin: 0" from <ol> in an attempt to make line numbers visible in IE again
by default (untested, but I don't really care if it works... get firefox! ;))
- Added note on php5 support (Karim Scheik)
- Added two new methods: load_from_file and get_language_name_from_extension, that can
help automate file highlighting (though the extension array at this time is quite bare)
(David Gartner, Brian Cheesman)
Version 1.0.4
- Fixed many version-reporting bugs (Jack Lloyd)
- Fixed bug where methods were not having the correct CSS generated for them
by get_stylesheet() (Jack Lloyd)
- Added new keywords to C and C++ files (Jack Lloyd)
- Added section on case sensitivity to documentation that wasn't in the other versions
Version 1.0.3
- Added language files:
* Smarty (Alan Juden)
* C# (Alan Juden)
* VB.NET (Alan Juden)
* C for Macs (M. Uli Kusterer)
* Objective C (M. Uli Kusterer)
- Links can have a target attribute (Andreas Gohr)
- Fixed multiline string bug if not using classes
- Added method set_encoding that allows you to set the character
set used by calls to htmlentities() in GeSHi
- You can now specify an array of object splitters, and each
type of method separated by each object splitter can be highlighted
differently
- If a language uses a case sensitive keyword group and that group
has a URL associated with it, the keyword will not be lowercased
in the URL (M. Uli Kusterer)
Version 1.0.2
- Added language files:
* Actionscript (Steffen Krause)
* ASP (Amit Gupta)
* Bash (Andreas Gohr)
* CADDCL (Roberto Rossi)
* CadLisp (Roberto Rossi)
* C++ (Dennis Bayer)
* Delphi (Járja Norbert)
* Javascript (Ben Keen)
* Lisp (Roberto Rossi)
* OpenOffice.org BASIC (Roberto Rossi)
* Perl (Andreas Gohr and Ben Keen)
* Python (Roberto Rossi)
* VisualFoxPro (Roberto Armellin)
* XML (Nigel McNie, from an idea/file by Christian Weiske)
- Added contrib/ directory with script to create one external stylesheet
from many languages(base script by Andreas Gohr, modified by Nigel McNie),
and an example script (needs lotsa work...)
- Code lines can have their own unique ID (for use with javascript)
(suggested by Andreas von Oettingen)
- Certain rows can be specified to be highlighted differently (suggested by
Andreas von Oettingen)
- Getter available for human-readable language name (suggested by Simon Patterson)
- Line numbers aren't highlighted when a user selects the code
- Contextual highlighting with <BEGIN GeSHi> ... <END GeSHi> in the code (which
can be disabled)
- Functions can be made into URLs to appropriate documentation (suggested
by cybot_tm). Also thanks to Marcin Gryszkalis for the links for C, Java
and Perl.
- Code can have a header and footer
- Time taken to parse the code is recorded and made available with the get_time()
method
- error() now returns a human-readable error message
- Function geshi_highlight added to make it even easier to highlight on the fly
- Advanced regular expression handling
- Bug fixes to lexic_permission handling
Version 1.0.1
- Added methods set_symbols_style() and set_symbols_highlighting(). These should be used
instead of set_brackets_style and set_brackets_highlighting respectively.
- Added a new field - language_path - that can be set either when the constructor is
called, or by the new method set_language_path(), that specifies a path to the directory
containing the language files (bug reported by bbspliff)
- Added a new method set_case_keywords(), that allows the auto-casing feature to be
changed on the fly instead of simply being specified in the language file
- If there is an error the source that is outputted is now handled much better
- Lines are broken in the source only by \n now, not by \r\n (to save on output source)
- Indentation moved into its own method
- Method header() modified to allow the user to choose whether the code is surrounded in
a <div> or a <pre> (see documentation for benefits of both). Method footer() likewise
modified.
- Method get_stylesheet() modified so that a smaller comment is outputted in economy mode,
and bugs with when line number classes are outputted in economy mode have been fixed
- Bug where spans had two quotes at the end of the attributes fixed (ie. <span style=".."">)
- Added language files:
* Ada (Tux)
* Apache log file (Tux)
* ASM (Tux)
* NSIS (Tux)
* Pascal (Tux)
Version 1.0.0
- Initial Release

View File

@ -0,0 +1,340 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License.

View File

@ -0,0 +1,33 @@
GeSHi - GEneric Syntax HIghlighter
----------------------------------
Version 1.0.8
Author: Nigel McNie, Benny Baumann
Email: nigel@geshi.org, BenBE@omorphia.de
GeSHi Website: http://qbnz.com/highlighter
GeSHi is a generic syntax highlighter, written in PHP. You simply
input the source code you wish to highlight with the language you
wish to use, and the output will be a file syntax highlighted to
XHTML standards.
For more information on how to use GeSHi, please consult the
documentation. If you got this readme from a GeSHi package, then
the documentation is available in the docs/ directory. Documentation
is also available at http://qbnz.com/highlighter/documentation.php
If you think you've found a bug in GeSHi, contact me with a bug
report at BenBE@omorphia.de, or submit it to the bug tracker at
http://sourceforge.net/tracker/?group_id=114997&atid=670231. Be
aware that minor highlighting errors may well just be incorrect
language files, but if you do find something major please contact me.
And if you're using GeSHi as a plugin/mod for some other software,
please tell me about it! It's worth a link to you, and I can give
you specialist help if you need it.
GeSHi is free software, released under the GNU GPL. Please see the
COPYING file for more information. If you do modify this program,
please tell me about it! Perhaps you've made a good improvement that
I can learn from :)

View File

@ -0,0 +1,163 @@
THANKS - List of credits for GeSHi
I owe these people/groups my thanks for help with GeSHi. Thanks, guys!
- Amit Gupta - Thanks for all that constructive criticism - it's
a great help for making GeSHi even better. And
thanks for the Wordpress plugin! (Anyone who is
interested in the plugin can visit:
http://blog.igeek.info/still-fresh/category/wp-plugins/igsyntax-hiliter/)
- Andreas Gohr - Thanks for language files and for using GeSHi for DokuWiki
(http://www.splitbrain.org/dokuwiki/wiki:dokuwiki). And thanks
for all your criticisms and for that stylesheet-maker code :).
Also, thanks for the UTF-8 patch.
- Andreas von Oettingen - Thanks for those great ideas! :)
- bbspliff - Thanks for pointing out that bug (pity I already
found it though ;))
- Benny Baumann - Thanks for your innumerable suggestions for improvements, and your
work on Delphi support :)
- Ben Keen - Thanks for the language files and pointing out some
ideas for future releases. Lookin' forward to seeing that
software soon! ;)
- Brian Cheesman - Thanks for using GeSHi in phpCvsView, and for the suggestion about
extension => language lookup
- Christian Weiske - Thanks for the inspiration for creating advanced regexp
highlighting :D
- Cliff Stanford - Thanks for the hardquote support for C# and Perl (can be used elsewhere
I'm sure)
- David Gartner - Thanks for using GeSHi in net2ftp, and for the idea about a load_from_file
method
- forum.qbasicnews.com - Thanks for putting up with the crappy versions
that I "forced" on you guys before ;)
- Jack Lloyd - Thanks for pointing out the versioning and method CSS bugs, and giving
me the extra C/C++ keywords
- Karim Scheik - Thanks for the php5 support report
- Marcin Gryszkalis - Thanks for those links for C, Java, Perl
- M. Uli Kusterer - Thanks for the idea about URL case conversion
- Milian Wolff - Thanks for the loads of optimizations
- Thanks for helping with implementation of various features
- Roberto Armellin - Thanks for pointing out some flaws in GeSHi (that will be solved
in 1.2 guaranteed)
- Sterling Christensen - Thanks for those links to language specs
- Tux - Thanks for making all those language files :D
- zbw - Thanks for proving a phpBB port was possible
PEOPE WHO MADE LANGUAGE FILES
- ABAP Andres Picazo
- Actionscript Steffen Krause (french translation by NikO)
- ActionScript 3 Jordi Boggiano (version for ActionScript3 and MXML)
- Ada Tux
- Apache Tux
- Applescript Stephan Klimek
- Apt sources.list Milian Wolff
- ASM Tux
- ASP Amit Gupta
- AutoIT mastrboy
- AviSynth Ryan Jones
- Bash Andreas Gohr
- Basic4GL Matthew Webb
- BlitzBasic P<>draig O`Connel
- BNF Rowan Rodrik van der Molen
- Boo Marcus Griep
- Brainfuck \ Brainfork Benny Baumann
- C++ Dennis Bayer, M. Uli Kusterer
- C++/QT Iulian M
- C# Alan Juden
- C for Macs M. Uli Kusterer
- CADDCL Roberto Rossi
- CadLisp Roberto Rossi
- CDFG John Horigan
- CIL Marcus Griep
- COBOL Benny Baumann
- ColdFusion Diego
- D Thomas Kuehne
- DCS Stelio Passaris
- Delphi Járja Norbert, Benny Baumann
- Div Gabriel Lorenzo
- DOS Alessandro Staltari
- Eiffel Zoran Simic
- eMail \ mbox Benny Baumann
- FreeBasic Roberto Rossi
- Fortran Cedric Arrabie
- glSlang Benny Baumann
- Gettext Milian Wolff
- GNU make Neil Bird
- Gnuplot Milian Wolff
- GML José Jorge Enríquez Rodríguez
- Groovy Ivan F. Villanueva B.
- Haskell Dagit
- HQ9+ Benny Baumann
- Ini Deguix
- Inno Thomas Klinger
- INTERCAL Benny Baumann
- Java 5 Clemens Bruckmann
- Javascript Ben Keen
- KiXtart Riley McArdle
- KLone C Mickael Auger
- KLone C++ Mickael Auger
- LaTeX Matthais Pospiech
- Lisp Roberto Rossi
- Locomotive Basic Nacho Cabanes
- LOLcode Benny Baumann
- LScript Beau McGuigan
- LSL2 William Fry
- Lua Roberto Rossi
- m86k Benny Baumann
- mIRC Alberto de Areba Sánchez
- Modula-3 Martin Bishop
- MPASM Bakalex
- MXML David Spurr
- MySQL Carl Fürstenberg, Marjolein Katsma
- NSIS Tux, Deguix
- Oberon-2 Mike Mol
- Objective C M. Uli Kusterer
- Ocaml Flaie
- Ocaml-brief Flaie
- OpenOffice.org BASIC Roberto Rossi
- Oracle 8 Guy Wicks
- Oracle 11i Simon Redhead
- Pascal Tux
- Perl Andreas Gohr, Ben Keen
- PIC16xxx assembler Phil Mattison
- Pixel Bender Richard Olsson
- PL/SQL Victor Engmark
- POV-Ray Carl Fürstenberg
- PowerShell Frode Aarebrot
- Progress Marco Aurelio de Pasqual
- Prolog Benny Baumann
- ProvideX Jeff Wilder
- Python Roberto Rossi
- Rails Moises Deniz
- Rebol Lecanu Guillaume
- Reg SmokingRope
- Robots Christian Lescuyer
- Ruby Amit Gupta, Moises Deniz
- SAS Galen Johnson
- SDLBasic Roberto Rossi
- Scheme Jon Raphaelson
- SciLab Christophe David
- Smalltalk Bananeweizen
- Smarty Alan Juden
- T-SQL Duncan Lock
- TeraTerm Boris Maisuradze
- Text SmokingRope
- TCL Reid van Melle
- thinBasic Eros Olmi
- TypoScript Jan-Philipp Halle
- Uno IDL Cedric Bosdonnat
- VB Roberto Rossi
- VB.NET Alan Juden
- Verilog Günter Dannoritzer
- VIM Script Swaroop C H
- Visual FoxPro Roberto Armellin
- Visual Prolog Thomas Linder Puls
- Whitespace Benny Baumann
- Winbatch Craig Storey
- X++ Simon Butcher
- Xorg config Milian Wolff
- Z80 Assembler Benny Baumann
Do you want your name in here? Help me out! Make a language file, or suggest a new
feature, or make a plugin for GeSHi for some other software, then tell me about it!

View File

@ -0,0 +1,71 @@
TODO - List of things to do as of 2005/01/29
Suggestions for things to add are welcome, if you have a feature request you
can either post it to the forums:
http://qbnz.com/highlighter/forum.php
Or to the feature request tracker:
http://sourceforge.net/tracker/?group_id=114997&atid=670234
TODO for version 1.0.8.x
- Rework the load_from_file method and the one for getting a file extension,
as documented in the source.
- use analogous vars to $next_comment_regexp_pos for more GeSHi structures,
should reduce number of functions called and hence improve performance
- make a set of default colours which can be used in the language files.
this way we can give languages a uniform look and maybe even add "themes"
- Get better coverage in our coderepo
- README / INSTALL / ... file for phpdoc integration => take geshi-doc.*?
- rework HARDQUOTE + styles, currently this is a bit of a mess imo (milian)
- Allow per-keywordgroup AutoCaps/NoCaps
- Complete API to support latest features
set_number_style ($key missing)
set_string_style ($key missing)
set_case_keywords (support for per_keywordgroup AutoCaps)
TODO for version 1.2.0
- Rewrite engine to use remove/replace method (will hopefully almost
eliminate the need for regular expressions except for numbers/methods
etc). This will also assist for making different output formats [DONE]
- "Intelligent" output format - eg if the user doesn't want lines to
wrap and wants line numbers don't use <ol>, use the <table> method
instead. (This saves on output)
- Clear split between "public" and "private" methods [DONE]
- PHP5 version
- "Themes" for styles - basically pre-made stylesheets that can be used
to highlight code of any language in a similar manner [DONE]
- "Dialects" for languages - eg php4, php5. One master language definition
file, and a bunch of "specialised" dialect files for each language
Ability to specify a "specialised" dialect as default? [DONE]
- Look at load/memory usage and try to reduce
- Make tabs into tab-stops like a normal editor [DONE]
- Ability to add more than one multiline comment or string [DONE]
- Ability to specify that strings cannot be multiline [DONE]
- Create a "wrapper" class for ultra-easy use
- Code written in a style that conforms to a phpdoc utility [DONE, PEAR]
- Dig functions/methods out of code and where they are called make an internal
link back to their definition
TODO for version 2.0.0
- Support for multiple output formats (XHTML, XML, PDF, RTF etc) [DONE IN 1.2]
- Support for auto-indent/code "beautifing"
- Option for "Lite" highlighting - aims for speed and low server load
- "Intelligent" highlighting inside comments, and ability to highlight
source in multiple languages at once (eg PHP+HTML) [DONE IN 1.2]
- Perhaps a script on the GeSHi site that would map urls to appropriate
definitions and relocate the user? (eg, java documentation is
structured in such a way that urls are not able to be used with GeSHi.
Instead the URL could become:
http://qbnz.com/highlighter/redirect.php?lang=java&kw=KeyWord
and that script would redirect to the correct location.
[BETTER FIX IN 1.2]
$Id: TODO 1727 2008-08-08 13:36:52Z benbe $

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,13 @@
<html>
<head>
<title>GeSHi 1.0.8</title>
<link rel="stylesheet" href="media/stylesheet.css" />
<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
</head>
<body>
<div align="center"><h1>GeSHi 1.0.8</h1></div>
<b>Welcome to geshi!</b><br />
<br />
This documentation was generated by <a href="http://www.phpdoc.org">phpDocumentor v1.4.2</a><br />
</body>
</html>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- template designed by Marco Von Ballmoos -->
<title></title>
<link rel="stylesheet" href="media/stylesheet.css" />
<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
</head>
<body>
<!-- Start of Class Data -->
<H2>
</H2>
<h2>Root class GeSHi</h2>
<ul>
<li><a href="geshi/core/GeSHi.html">GeSHi</a></li></ul>
<p class="notes" id="credit">
Documentation generated on Thu, 25 Dec 2008 14:34:34 +0100 by <a href="http://www.phpdoc.org" target="_blank">phpDocumentor 1.4.2</a>
</p>
</body>
</html>

View File

@ -0,0 +1,867 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- template designed by Marco Von Ballmoos -->
<title></title>
<link rel="stylesheet" href="media/stylesheet.css" />
<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
</head>
<body>
<a name="top"></a>
<h2>Full index</h2>
<h3>Package indexes</h3>
<ul>
<li><a href="elementindex_geshi.html">geshi</a></li>
</ul>
<br />
<div class="index-letter-menu">
<a class="index-letter" href="elementindex.html#a">a</a>
<a class="index-letter" href="elementindex.html#d">d</a>
<a class="index-letter" href="elementindex.html#e">e</a>
<a class="index-letter" href="elementindex.html#g">g</a>
<a class="index-letter" href="elementindex.html#h">h</a>
<a class="index-letter" href="elementindex.html#l">l</a>
<a class="index-letter" href="elementindex.html#o">o</a>
<a class="index-letter" href="elementindex.html#p">p</a>
<a class="index-letter" href="elementindex.html#r">r</a>
<a class="index-letter" href="elementindex.html#s">s</a>
</div>
<a name="a"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">a</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">add_keyword</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword">GeSHi::add_keyword()</a> in geshi.php</div>
<div class="index-item-description">Adds a keyword to a keyword group for highlighting</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">add_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword_group">GeSHi::add_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Creates a new keyword group</div>
</dd>
</dl>
<a name="d"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">d</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">disable_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methoddisable_highlighting">GeSHi::disable_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Disables all highlighting</div>
</dd>
</dl>
<a name="e"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">e</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_classes</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_classes">GeSHi::enable_classes()</a> in geshi.php</div>
<div class="index-item-description">Sets whether CSS classes should be used to highlight the source. Default is off, calling this method with no arguments will turn it on</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_highlighting">GeSHi::enable_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Enables all highlighting</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_ids</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_ids">GeSHi::enable_ids()</a> in geshi.php</div>
<div class="index-item-description">Whether CSS IDs should be added to each line</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_important_blocks</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_important_blocks">GeSHi::enable_important_blocks()</a> in geshi.php</div>
<div class="index-item-description">Sets whether context-important blocks are highlighted</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_inner_code_block</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_inner_code_block">GeSHi::enable_inner_code_block()</a> in geshi.php</div>
<div class="index-item-description">Sets whether to force a surrounding block around the highlighted code or not</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_keyword_links</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_keyword_links">GeSHi::enable_keyword_links()</a> in geshi.php</div>
<div class="index-item-description">Turns linking of keywords on or off.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_line_numbers</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_line_numbers">GeSHi::enable_line_numbers()</a> in geshi.php</div>
<div class="index-item-description">Sets whether line numbers should be displayed.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_multiline_span</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_multiline_span">GeSHi::enable_multiline_span()</a> in geshi.php</div>
<div class="index-item-description">Sets wether spans and other HTML markup generated by GeSHi can span over multiple lines or not. Defaults to true to reduce overhead.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_strict_mode</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_strict_mode">GeSHi::enable_strict_mode()</a> in geshi.php</div>
<div class="index-item-description">Enables/disables strict highlighting. Default is off, calling this method without parameters will turn it on. See documentation for more details on strict mode and where to use it.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">error</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methoderror">GeSHi::error()</a> in geshi.php</div>
<div class="index-item-description">Returns an error message associated with the last GeSHi operation, or false if no error has occured</div>
</dd>
</dl>
<a name="g"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">g</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Constructor.png" alt="Method" title="Method" /></title>
<span class="method-title">GeSHi</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodGeSHi">GeSHi::GeSHi()</a> in geshi.php</div>
<div class="index-item-description">Creates a new GeSHi object, with source and language</div>
</dd>
<dt class="field">
<img src="media/images/Class.png" alt="Class" title="Class" /></title>
GeSHi
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html">GeSHi</a> in geshi.php</div>
<div class="index-item-description">The GeSHi Class.</div>
</dd>
<dt class="field">
<img src="media/images/Page.png" alt="Page" title="Page" /></title>
<span class="include-title">geshi.php</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html">geshi.php</a> in geshi.php</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_ACTIVE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ACTIVE">GESHI_ACTIVE</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :active state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_LOWER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER">GESHI_CAPS_LOWER</a> in geshi.php</div>
<div class="index-item-description">Leave keywords found as the case that they are</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_NO_CHANGE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_NO_CHANGE">GESHI_CAPS_NO_CHANGE</a> in geshi.php</div>
<div class="index-item-description">Lowercase keywords found</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_UPPER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER">GESHI_CAPS_UPPER</a> in geshi.php</div>
<div class="index-item-description">Uppercase keywords found</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_END_IMPORTANT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT">GESHI_END_IMPORTANT</a> in geshi.php</div>
<div class="index-item-description">The ender for important parts of the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_FANCY_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS">GESHI_FANCY_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use fancy line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_DIV</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV">GESHI_HEADER_DIV</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;div&quot; to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_NONE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE">GESHI_HEADER_NONE</a> in geshi.php</div>
<div class="index-item-description">Use nothing to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE">GESHI_HEADER_PRE</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;pre&quot; to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE_TABLE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE">GESHI_HEADER_PRE_TABLE</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;table&quot; to surround the source:</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE_VALID</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID">GESHI_HEADER_PRE_VALID</a> in geshi.php</div>
<div class="index-item-description">Use a pre to wrap lines when line numbers are enabled or to wrap the whole code.</div>
</dd>
<dt class="field">
<img src="media/images/Function.png" alt="Function" title="Function" /></title>
<span class="method-title">geshi_highlight</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#functiongeshi_highlight">geshi_highlight()</a> in geshi.php</div>
<div class="index-item-description">Easy way to highlight stuff. Behaves just like highlight_string</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HOVER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HOVER">GESHI_HOVER</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :hover state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_LANG_ROOT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LANG_ROOT">GESHI_LANG_ROOT</a> in geshi.php</div>
<div class="index-item-description">The language file directory for GeSHi</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_LINK</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LINK">GESHI_LINK</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :link state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_NORMAL_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NORMAL_LINE_NUMBERS">GESHI_NORMAL_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use normal line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_NO_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use no line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_ROOT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ROOT">GESHI_ROOT</a> in geshi.php</div>
<div class="index-item-description">The root directory for GeSHi</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_SECURITY_PARANOID</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID">GESHI_SECURITY_PARANOID</a> in geshi.php</div>
<div class="index-item-description">Tells GeSHi to be paranoid about security settings</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_START_IMPORTANT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT">GESHI_START_IMPORTANT</a> in geshi.php</div>
<div class="index-item-description">The starter for important parts of the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_VERSION</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VERSION">GESHI_VERSION</a> in geshi.php</div>
<div class="index-item-description">The version of this GeSHi file</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_VISITED</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VISITED">GESHI_VISITED</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :visited state</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_language_name</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name">GeSHi::get_language_name()</a> in geshi.php</div>
<div class="index-item-description">Gets a human-readable language name (thanks to Simon Patterson for the idea :))</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_language_name_from_extension</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name_from_extension">GeSHi::get_language_name_from_extension()</a> in geshi.php</div>
<div class="index-item-description">Given a file extension, this method returns either a valid geshi language name, or the empty string if it couldn't be found</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_multiline_span</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_multiline_span">GeSHi::get_multiline_span()</a> in geshi.php</div>
<div class="index-item-description">Get current setting for multiline spans, see GeSHi-&gt;enable_multiline_span().</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_real_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_real_tab_width">GeSHi::get_real_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Returns the tab width to use, based on the current language and user preference</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_stylesheet</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_stylesheet">GeSHi::get_stylesheet()</a> in geshi.php</div>
<div class="index-item-description">Returns a stylesheet for the highlighted code. If $economy mode is true, we only return the stylesheet declarations that matter for this code block instead of the whole thing</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_time</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_time">GeSHi::get_time()</a> in geshi.php</div>
<div class="index-item-description">Gets the time taken to parse the code</div>
</dd>
</dl>
<a name="h"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">h</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">highlight_lines_extra</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodhighlight_lines_extra">GeSHi::highlight_lines_extra()</a> in geshi.php</div>
<div class="index-item-description">Specifies which lines to highlight extra</div>
</dd>
</dl>
<a name="l"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">l</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">load_from_file</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodload_from_file">GeSHi::load_from_file()</a> in geshi.php</div>
<div class="index-item-description">Given a file name, this method loads its contents in, and attempts</div>
</dd>
</dl>
<a name="o"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">o</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">optimize_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodoptimize_keyword_group">GeSHi::optimize_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">compile optimized regexp list for keyword group</div>
</dd>
</dl>
<a name="p"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">p</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">parse_code</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodparse_code">GeSHi::parse_code()</a> in geshi.php</div>
<div class="index-item-description">Returns the code in $this-&gt;source, highlighted and surrounded by the nessecary HTML.</div>
</dd>
</dl>
<a name="r"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">r</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">remove_keyword</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword">GeSHi::remove_keyword()</a> in geshi.php</div>
<div class="index-item-description">Removes a keyword from a keyword group</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">remove_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword_group">GeSHi::remove_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Removes a keyword group</div>
</dd>
</dl>
<a name="s"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">s</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_brackets_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_highlighting">GeSHi::set_brackets_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for brackets</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_brackets_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_style">GeSHi::set_brackets_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for brackets. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_case_keywords</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_keywords">GeSHi::set_case_keywords()</a> in geshi.php</div>
<div class="index-item-description">Sets the case that keywords should use when found. Use the constants:</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_case_sensitivity</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_sensitivity">GeSHi::set_case_sensitivity()</a> in geshi.php</div>
<div class="index-item-description">Sets whether a set of keywords are checked for in a case sensitive manner</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_code_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_code_style">GeSHi::set_code_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the actual code. This should be a string</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_comments_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_highlighting">GeSHi::set_comments_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for comment groups</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_comments_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_style">GeSHi::set_comments_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for comment groups. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_encoding</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_encoding">GeSHi::set_encoding()</a> in geshi.php</div>
<div class="index-item-description">Sets the encoding used for htmlspecialchars(), for international support.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_escape_characters_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_highlighting">GeSHi::set_escape_characters_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for escaped characters</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_escape_characters_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_style">GeSHi::set_escape_characters_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for escaped characters. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_footer_content</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content">GeSHi::set_footer_content()</a> in geshi.php</div>
<div class="index-item-description">Sets the content of the footer block</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_footer_content_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content_style">GeSHi::set_footer_content_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the footer content</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_content</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content">GeSHi::set_header_content()</a> in geshi.php</div>
<div class="index-item-description">Sets the content of the header block</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_content_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content_style">GeSHi::set_header_content_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the header content</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_type</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_type">GeSHi::set_header_type()</a> in geshi.php</div>
<div class="index-item-description">Sets the type of header to be used.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_highlight_lines_extra_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_highlight_lines_extra_style">GeSHi::set_highlight_lines_extra_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for extra-highlighted lines</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_important_styles</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_important_styles">GeSHi::set_important_styles()</a> in geshi.php</div>
<div class="index-item-description">Sets styles for important parts of the code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_keyword_group_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_highlighting">GeSHi::set_keyword_group_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for a keyword group</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_keyword_group_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_style">GeSHi::set_keyword_group_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for a keyword group. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_language</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language">GeSHi::set_language()</a> in geshi.php</div>
<div class="index-item-description">Sets the language for this object</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_language_path</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language_path">GeSHi::set_language_path()</a> in geshi.php</div>
<div class="index-item-description">Sets the path to the directory containing the language files. Note that this path is relative to the directory of the script that included geshi.php, NOT geshi.php itself.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_line_ending</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_ending">GeSHi::set_line_ending()</a> in geshi.php</div>
<div class="index-item-description">Sets the line-ending</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_line_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_style">GeSHi::set_line_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for the line numbers.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_link_styles</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_styles">GeSHi::set_link_styles()</a> in geshi.php</div>
<div class="index-item-description">Sets styles for links in code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_link_target</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_target">GeSHi::set_link_target()</a> in geshi.php</div>
<div class="index-item-description">Sets the target for links in code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_methods_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_highlighting">GeSHi::set_methods_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for methods</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_methods_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_style">GeSHi::set_methods_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for methods. $key is a number that references the</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_numbers_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_highlighting">GeSHi::set_numbers_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for numbers</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_numbers_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_style">GeSHi::set_numbers_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for numbers. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_class</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_class">GeSHi::set_overall_class()</a> in geshi.php</div>
<div class="index-item-description">Sets the overall classname for this block of code. This class can then be used in a stylesheet to style this object's output</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_id</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_id">GeSHi::set_overall_id()</a> in geshi.php</div>
<div class="index-item-description">Sets the overall id for this block of code. This id can then be used in a stylesheet to style this object's output</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_style">GeSHi::set_overall_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for the code that will be outputted when this object is parsed. The style should be a string of valid stylesheet declarations</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_regexps_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_highlighting">GeSHi::set_regexps_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for regexps</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_regexps_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_style">GeSHi::set_regexps_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for regexps. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_source</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_source">GeSHi::set_source()</a> in geshi.php</div>
<div class="index-item-description">Sets the source code for this object</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_strings_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_highlighting">GeSHi::set_strings_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for strings</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_strings_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_style">GeSHi::set_strings_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for strings. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_symbols_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_highlighting">GeSHi::set_symbols_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for symbols</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_symbols_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_style">GeSHi::set_symbols_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for symbols. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_tab_width">GeSHi::set_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Sets how many spaces a tab is substituted for</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_url_for_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_url_for_keyword_group">GeSHi::set_url_for_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Sets the base URL to be used for keywords</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_use_language_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_use_language_tab_width">GeSHi::set_use_language_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Sets whether or not to use tab-stop width specifed by language</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">start_line_numbers_at</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodstart_line_numbers_at">GeSHi::start_line_numbers_at()</a> in geshi.php</div>
<div class="index-item-description">Sets what number line numbers should start at. Should be a positive integer, and will be converted to one.</div>
</dd>
</dl>
<div class="index-letter-menu">
<a class="index-letter" href="elementindex.html#a">a</a>
<a class="index-letter" href="elementindex.html#d">d</a>
<a class="index-letter" href="elementindex.html#e">e</a>
<a class="index-letter" href="elementindex.html#g">g</a>
<a class="index-letter" href="elementindex.html#h">h</a>
<a class="index-letter" href="elementindex.html#l">l</a>
<a class="index-letter" href="elementindex.html#o">o</a>
<a class="index-letter" href="elementindex.html#p">p</a>
<a class="index-letter" href="elementindex.html#r">r</a>
<a class="index-letter" href="elementindex.html#s">s</a>
</div> </body>
</html>

View File

@ -0,0 +1,864 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!-- template designed by Marco Von Ballmoos -->
<title></title>
<link rel="stylesheet" href="media/stylesheet.css" />
<meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'/>
</head>
<body>
<a name="top"></a>
<h2>[geshi] element index</h2>
<a href="elementindex.html">All elements</a>
<br />
<div class="index-letter-menu">
<a class="index-letter" href="elementindex_geshi.html#a">a</a>
<a class="index-letter" href="elementindex_geshi.html#d">d</a>
<a class="index-letter" href="elementindex_geshi.html#e">e</a>
<a class="index-letter" href="elementindex_geshi.html#g">g</a>
<a class="index-letter" href="elementindex_geshi.html#h">h</a>
<a class="index-letter" href="elementindex_geshi.html#l">l</a>
<a class="index-letter" href="elementindex_geshi.html#o">o</a>
<a class="index-letter" href="elementindex_geshi.html#p">p</a>
<a class="index-letter" href="elementindex_geshi.html#r">r</a>
<a class="index-letter" href="elementindex_geshi.html#s">s</a>
</div>
<a name="a"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">a</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">add_keyword</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword">GeSHi::add_keyword()</a> in geshi.php</div>
<div class="index-item-description">Adds a keyword to a keyword group for highlighting</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">add_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodadd_keyword_group">GeSHi::add_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Creates a new keyword group</div>
</dd>
</dl>
<a name="d"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">d</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">disable_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methoddisable_highlighting">GeSHi::disable_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Disables all highlighting</div>
</dd>
</dl>
<a name="e"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">e</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_classes</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_classes">GeSHi::enable_classes()</a> in geshi.php</div>
<div class="index-item-description">Sets whether CSS classes should be used to highlight the source. Default is off, calling this method with no arguments will turn it on</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_highlighting">GeSHi::enable_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Enables all highlighting</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_ids</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_ids">GeSHi::enable_ids()</a> in geshi.php</div>
<div class="index-item-description">Whether CSS IDs should be added to each line</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_important_blocks</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_important_blocks">GeSHi::enable_important_blocks()</a> in geshi.php</div>
<div class="index-item-description">Sets whether context-important blocks are highlighted</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_inner_code_block</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_inner_code_block">GeSHi::enable_inner_code_block()</a> in geshi.php</div>
<div class="index-item-description">Sets whether to force a surrounding block around the highlighted code or not</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_keyword_links</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_keyword_links">GeSHi::enable_keyword_links()</a> in geshi.php</div>
<div class="index-item-description">Turns linking of keywords on or off.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_line_numbers</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_line_numbers">GeSHi::enable_line_numbers()</a> in geshi.php</div>
<div class="index-item-description">Sets whether line numbers should be displayed.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_multiline_span</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_multiline_span">GeSHi::enable_multiline_span()</a> in geshi.php</div>
<div class="index-item-description">Sets wether spans and other HTML markup generated by GeSHi can span over multiple lines or not. Defaults to true to reduce overhead.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">enable_strict_mode</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodenable_strict_mode">GeSHi::enable_strict_mode()</a> in geshi.php</div>
<div class="index-item-description">Enables/disables strict highlighting. Default is off, calling this method without parameters will turn it on. See documentation for more details on strict mode and where to use it.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">error</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methoderror">GeSHi::error()</a> in geshi.php</div>
<div class="index-item-description">Returns an error message associated with the last GeSHi operation, or false if no error has occured</div>
</dd>
</dl>
<a name="g"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">g</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Constructor.png" alt="Method" title="Method" /></title>
<span class="method-title">GeSHi</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodGeSHi">GeSHi::GeSHi()</a> in geshi.php</div>
<div class="index-item-description">Creates a new GeSHi object, with source and language</div>
</dd>
<dt class="field">
<img src="media/images/Class.png" alt="Class" title="Class" /></title>
GeSHi
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html">GeSHi</a> in geshi.php</div>
<div class="index-item-description">The GeSHi Class.</div>
</dd>
<dt class="field">
<img src="media/images/Page.png" alt="Page" title="Page" /></title>
<span class="include-title">geshi.php</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html">geshi.php</a> in geshi.php</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_ACTIVE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ACTIVE">GESHI_ACTIVE</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :active state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_LOWER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_LOWER">GESHI_CAPS_LOWER</a> in geshi.php</div>
<div class="index-item-description">Leave keywords found as the case that they are</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_NO_CHANGE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_NO_CHANGE">GESHI_CAPS_NO_CHANGE</a> in geshi.php</div>
<div class="index-item-description">Lowercase keywords found</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_CAPS_UPPER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_CAPS_UPPER">GESHI_CAPS_UPPER</a> in geshi.php</div>
<div class="index-item-description">Uppercase keywords found</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_END_IMPORTANT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_END_IMPORTANT">GESHI_END_IMPORTANT</a> in geshi.php</div>
<div class="index-item-description">The ender for important parts of the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_FANCY_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_FANCY_LINE_NUMBERS">GESHI_FANCY_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use fancy line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_DIV</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_DIV">GESHI_HEADER_DIV</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;div&quot; to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_NONE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_NONE">GESHI_HEADER_NONE</a> in geshi.php</div>
<div class="index-item-description">Use nothing to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE">GESHI_HEADER_PRE</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;pre&quot; to surround the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE_TABLE</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_TABLE">GESHI_HEADER_PRE_TABLE</a> in geshi.php</div>
<div class="index-item-description">Use a &quot;table&quot; to surround the source:</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HEADER_PRE_VALID</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HEADER_PRE_VALID">GESHI_HEADER_PRE_VALID</a> in geshi.php</div>
<div class="index-item-description">Use a pre to wrap lines when line numbers are enabled or to wrap the whole code.</div>
</dd>
<dt class="field">
<img src="media/images/Function.png" alt="Function" title="Function" /></title>
<span class="method-title">geshi_highlight</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#functiongeshi_highlight">geshi_highlight()</a> in geshi.php</div>
<div class="index-item-description">Easy way to highlight stuff. Behaves just like highlight_string</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_HOVER</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_HOVER">GESHI_HOVER</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :hover state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_LANG_ROOT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LANG_ROOT">GESHI_LANG_ROOT</a> in geshi.php</div>
<div class="index-item-description">The language file directory for GeSHi</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_LINK</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_LINK">GESHI_LINK</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :link state</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_NORMAL_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NORMAL_LINE_NUMBERS">GESHI_NORMAL_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use normal line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_NO_LINE_NUMBERS</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_NO_LINE_NUMBERS">GESHI_NO_LINE_NUMBERS</a> in geshi.php</div>
<div class="index-item-description">Use no line numbers when building the result</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_ROOT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_ROOT">GESHI_ROOT</a> in geshi.php</div>
<div class="index-item-description">The root directory for GeSHi</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_SECURITY_PARANOID</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_SECURITY_PARANOID">GESHI_SECURITY_PARANOID</a> in geshi.php</div>
<div class="index-item-description">Tells GeSHi to be paranoid about security settings</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_START_IMPORTANT</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_START_IMPORTANT">GESHI_START_IMPORTANT</a> in geshi.php</div>
<div class="index-item-description">The starter for important parts of the source</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_VERSION</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VERSION">GESHI_VERSION</a> in geshi.php</div>
<div class="index-item-description">The version of this GeSHi file</div>
</dd>
<dt class="field">
<img src="media/images/Constant.png" alt="Constant" title="Constant" /></title>
<span class="const-title">GESHI_VISITED</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/_geshi.php.html#defineGESHI_VISITED">GESHI_VISITED</a> in geshi.php</div>
<div class="index-item-description">Links in the source in the :visited state</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_language_name</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name">GeSHi::get_language_name()</a> in geshi.php</div>
<div class="index-item-description">Gets a human-readable language name (thanks to Simon Patterson for the idea :))</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_language_name_from_extension</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_language_name_from_extension">GeSHi::get_language_name_from_extension()</a> in geshi.php</div>
<div class="index-item-description">Given a file extension, this method returns either a valid geshi language name, or the empty string if it couldn't be found</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_multiline_span</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_multiline_span">GeSHi::get_multiline_span()</a> in geshi.php</div>
<div class="index-item-description">Get current setting for multiline spans, see GeSHi-&gt;enable_multiline_span().</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_real_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_real_tab_width">GeSHi::get_real_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Returns the tab width to use, based on the current language and user preference</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_stylesheet</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_stylesheet">GeSHi::get_stylesheet()</a> in geshi.php</div>
<div class="index-item-description">Returns a stylesheet for the highlighted code. If $economy mode is true, we only return the stylesheet declarations that matter for this code block instead of the whole thing</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">get_time</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodget_time">GeSHi::get_time()</a> in geshi.php</div>
<div class="index-item-description">Gets the time taken to parse the code</div>
</dd>
</dl>
<a name="h"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">h</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">highlight_lines_extra</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodhighlight_lines_extra">GeSHi::highlight_lines_extra()</a> in geshi.php</div>
<div class="index-item-description">Specifies which lines to highlight extra</div>
</dd>
</dl>
<a name="l"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">l</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">load_from_file</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodload_from_file">GeSHi::load_from_file()</a> in geshi.php</div>
<div class="index-item-description">Given a file name, this method loads its contents in, and attempts</div>
</dd>
</dl>
<a name="o"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">o</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">optimize_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodoptimize_keyword_group">GeSHi::optimize_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">compile optimized regexp list for keyword group</div>
</dd>
</dl>
<a name="p"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">p</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">parse_code</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodparse_code">GeSHi::parse_code()</a> in geshi.php</div>
<div class="index-item-description">Returns the code in $this-&gt;source, highlighted and surrounded by the nessecary HTML.</div>
</dd>
</dl>
<a name="r"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">r</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">remove_keyword</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword">GeSHi::remove_keyword()</a> in geshi.php</div>
<div class="index-item-description">Removes a keyword from a keyword group</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">remove_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodremove_keyword_group">GeSHi::remove_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Removes a keyword group</div>
</dd>
</dl>
<a name="s"></a>
<div class="index-letter-section">
<div style="float: left" class="index-letter-title">s</div>
<div style="float: right"><a href="#top">top</a></div>
<div style="clear: both"></div>
</div>
<dl>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_brackets_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_highlighting">GeSHi::set_brackets_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for brackets</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_brackets_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_brackets_style">GeSHi::set_brackets_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for brackets. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_case_keywords</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_keywords">GeSHi::set_case_keywords()</a> in geshi.php</div>
<div class="index-item-description">Sets the case that keywords should use when found. Use the constants:</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_case_sensitivity</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_case_sensitivity">GeSHi::set_case_sensitivity()</a> in geshi.php</div>
<div class="index-item-description">Sets whether a set of keywords are checked for in a case sensitive manner</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_code_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_code_style">GeSHi::set_code_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the actual code. This should be a string</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_comments_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_highlighting">GeSHi::set_comments_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for comment groups</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_comments_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_comments_style">GeSHi::set_comments_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for comment groups. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_encoding</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_encoding">GeSHi::set_encoding()</a> in geshi.php</div>
<div class="index-item-description">Sets the encoding used for htmlspecialchars(), for international support.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_escape_characters_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_highlighting">GeSHi::set_escape_characters_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for escaped characters</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_escape_characters_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_escape_characters_style">GeSHi::set_escape_characters_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for escaped characters. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_footer_content</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content">GeSHi::set_footer_content()</a> in geshi.php</div>
<div class="index-item-description">Sets the content of the footer block</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_footer_content_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_footer_content_style">GeSHi::set_footer_content_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the footer content</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_content</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content">GeSHi::set_header_content()</a> in geshi.php</div>
<div class="index-item-description">Sets the content of the header block</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_content_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_content_style">GeSHi::set_header_content_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for the header content</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_header_type</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_header_type">GeSHi::set_header_type()</a> in geshi.php</div>
<div class="index-item-description">Sets the type of header to be used.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_highlight_lines_extra_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_highlight_lines_extra_style">GeSHi::set_highlight_lines_extra_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for extra-highlighted lines</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_important_styles</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_important_styles">GeSHi::set_important_styles()</a> in geshi.php</div>
<div class="index-item-description">Sets styles for important parts of the code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_keyword_group_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_highlighting">GeSHi::set_keyword_group_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for a keyword group</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_keyword_group_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_keyword_group_style">GeSHi::set_keyword_group_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the style for a keyword group. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_language</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language">GeSHi::set_language()</a> in geshi.php</div>
<div class="index-item-description">Sets the language for this object</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_language_path</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_language_path">GeSHi::set_language_path()</a> in geshi.php</div>
<div class="index-item-description">Sets the path to the directory containing the language files. Note that this path is relative to the directory of the script that included geshi.php, NOT geshi.php itself.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_line_ending</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_ending">GeSHi::set_line_ending()</a> in geshi.php</div>
<div class="index-item-description">Sets the line-ending</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_line_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_line_style">GeSHi::set_line_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for the line numbers.</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_link_styles</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_styles">GeSHi::set_link_styles()</a> in geshi.php</div>
<div class="index-item-description">Sets styles for links in code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_link_target</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_link_target">GeSHi::set_link_target()</a> in geshi.php</div>
<div class="index-item-description">Sets the target for links in code</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_methods_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_highlighting">GeSHi::set_methods_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for methods</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_methods_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_methods_style">GeSHi::set_methods_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for methods. $key is a number that references the</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_numbers_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_highlighting">GeSHi::set_numbers_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for numbers</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_numbers_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_numbers_style">GeSHi::set_numbers_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for numbers. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_class</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_class">GeSHi::set_overall_class()</a> in geshi.php</div>
<div class="index-item-description">Sets the overall classname for this block of code. This class can then be used in a stylesheet to style this object's output</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_id</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_id">GeSHi::set_overall_id()</a> in geshi.php</div>
<div class="index-item-description">Sets the overall id for this block of code. This id can then be used in a stylesheet to style this object's output</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_overall_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_overall_style">GeSHi::set_overall_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for the code that will be outputted when this object is parsed. The style should be a string of valid stylesheet declarations</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_regexps_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_highlighting">GeSHi::set_regexps_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for regexps</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_regexps_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_regexps_style">GeSHi::set_regexps_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for regexps. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_source</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_source">GeSHi::set_source()</a> in geshi.php</div>
<div class="index-item-description">Sets the source code for this object</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_strings_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_highlighting">GeSHi::set_strings_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for strings</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_strings_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_strings_style">GeSHi::set_strings_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for strings. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_symbols_highlighting</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_highlighting">GeSHi::set_symbols_highlighting()</a> in geshi.php</div>
<div class="index-item-description">Turns highlighting on/off for symbols</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_symbols_style</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_symbols_style">GeSHi::set_symbols_style()</a> in geshi.php</div>
<div class="index-item-description">Sets the styles for symbols. If $preserve_defaults is true, then styles are merged with the default styles, with the user defined styles having priority</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_tab_width">GeSHi::set_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Sets how many spaces a tab is substituted for</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_url_for_keyword_group</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_url_for_keyword_group">GeSHi::set_url_for_keyword_group()</a> in geshi.php</div>
<div class="index-item-description">Sets the base URL to be used for keywords</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">set_use_language_tab_width</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodset_use_language_tab_width">GeSHi::set_use_language_tab_width()</a> in geshi.php</div>
<div class="index-item-description">Sets whether or not to use tab-stop width specifed by language</div>
</dd>
<dt class="field">
<img src="media/images/Method.png" alt="Method" title="Method" /></title>
<span class="method-title">start_line_numbers_at</span>
</dt>
<dd class="index-item-body">
<div class="index-item-details"><a href="geshi/core/GeSHi.html#methodstart_line_numbers_at">GeSHi::start_line_numbers_at()</a> in geshi.php</div>
<div class="index-item-description">Sets what number line numbers should start at. Should be a positive integer, and will be converted to one.</div>
</dd>
</dl>
<div class="index-letter-menu">
<a class="index-letter" href="elementindex_geshi.html#a">a</a>
<a class="index-letter" href="elementindex_geshi.html#d">d</a>
<a class="index-letter" href="elementindex_geshi.html#e">e</a>
<a class="index-letter" href="elementindex_geshi.html#g">g</a>
<a class="index-letter" href="elementindex_geshi.html#h">h</a>
<a class="index-letter" href="elementindex_geshi.html#l">l</a>
<a class="index-letter" href="elementindex_geshi.html#o">o</a>
<a class="index-letter" href="elementindex_geshi.html#p">p</a>
<a class="index-letter" href="elementindex_geshi.html#r">r</a>
<a class="index-letter" href="elementindex_geshi.html#s">s</a>
</div> </body>
</html>

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