History

Initial WebM release

John Koleszar committed 16 years agov0.9.0

Commit 0ea50ceNo parent (first commit)724 files · +210045 −-49Browse files

Unified · Split

604 files
  1. .gitattributes +18 −0
  2. AUTHORS +4 −0
  3. CHANGELOG +3 −0
  4. LICENSE +48 −0
  5. README +106 −0
  6. args.c +215 −0
  7. args.h +43 −0
  8. build/.gitignore +1 −0
  9. build/arm-wince-vs8/.gitattributes +1 −0
  10. build/arm-wince-vs8/armasmv5.rules +20 −0
  11. build/arm-wince-vs8/armasmv6.rules +20 −0
  12. build/arm-wince-vs8/armasmxscale.rules +20 −0
  13. build/arm-wince-vs8/obj_int_extract.bat +12 −0
  14. build/arm-wince-vs8/vpx_decoder.sln +88 −0
  15. build/make/Makefile +341 −0
  16. build/make/ads2gas.pl +149 −0
  17. build/make/ads2gas_apple.pl +194 −0
  18. build/make/armlink_adapter.sh +51 −0
  19. build/make/configure.sh +907 −0
  20. build/make/gen_asm_deps.sh +63 −0
  21. build/make/gen_msvs_def.sh +82 −0
  22. build/make/gen_msvs_proj.sh +717 −0
  23. build/make/gen_msvs_sln.sh +272 −0
  24. build/make/obj_int_extract.c +755 −0
  25. build/make/version.sh +75 −0
  26. configure +515 −0
  27. docs.mk +54 −0
  28. example_xma.c +213 −0
  29. examples.mk +231 −0
  30. examples/decode_to_md5.txt +48 −0
  31. examples/decode_with_drops.txt +73 −0
  32. examples/decoder_tmpl.c +102 −0
  33. examples/decoder_tmpl.txt +61 −0
  34. examples/encoder_tmpl.c +189 −0
  35. examples/encoder_tmpl.txt +73 −0
  36. examples/error_resilient.txt +25 −0
  37. examples/force_keyframe.txt +28 −0
  38. examples/gen_example_code.sh +84 −0
  39. examples/gen_example_doxy.php +223 −0
  40. examples/gen_example_text.sh +83 −0
  41. examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php +218 −0
  42. examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php +1119 −0
  43. examples/includes/ASCIIMathPHP-2.0/htmlMathML.js +86 −0
  44. examples/includes/HTML-Toc-0.91/.gitattributes +1 −0
  45. examples/includes/HTML-Toc-0.91/Changes +26 −0
  46. examples/includes/HTML-Toc-0.91/MANIFEST +26 −0
  47. examples/includes/HTML-Toc-0.91/Makefile.PL +8 −0
  48. examples/includes/HTML-Toc-0.91/Toc.pm +549 −0
  49. examples/includes/HTML-Toc-0.91/Toc.pod +1710 −0
  50. examples/includes/HTML-Toc-0.91/TocGenerator.pm +1793 −0
  51. examples/includes/HTML-Toc-0.91/TocInsertor.pm +1066 −0
  52. examples/includes/HTML-Toc-0.91/TocUpdator.pm +693 −0
  53. examples/includes/HTML-Toc-0.91/t/ManualTest/manualTest1.htm +92 −0
  54. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/SubSubDir1/index.htm +5 −0
  55. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/index.htm +5 −0
  56. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir1/index.htm +5 −0
  57. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir2/index.htm +5 −0
  58. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/index.htm +5 −0
  59. examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir3/index.htm +5 −0
  60. examples/includes/HTML-Toc-0.91/t/SiteMap/index.htm +5 −0
  61. examples/includes/HTML-Toc-0.91/t/extend.t +87 −0
  62. examples/includes/HTML-Toc-0.91/t/format.t +157 −0
  63. examples/includes/HTML-Toc-0.91/t/generate.t +200 −0
  64. examples/includes/HTML-Toc-0.91/t/insert.t +336 −0
  65. examples/includes/HTML-Toc-0.91/t/manualTest.t +768 −0
  66. examples/includes/HTML-Toc-0.91/t/options.t +194 −0
  67. examples/includes/HTML-Toc-0.91/t/podExamples.t +709 −0
  68. examples/includes/HTML-Toc-0.91/t/propagate.t +176 −0
  69. examples/includes/HTML-Toc-0.91/t/siteMap.t +97 −0
  70. examples/includes/HTML-Toc-0.91/t/update.t +114 −0
  71. examples/includes/PHP-Markdown-Extra-1.2.3/License.text +36 −0
  72. examples/includes/PHP-Markdown-Extra-1.2.3/PHP Markdown Extra Readme.text +731 −0
  73. examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php +2909 −0
  74. examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php.orig +2909 −0
  75. examples/includes/PHP-SmartyPants-1.5.1e/PHP SmartyPants Readme.txt +394 −0
  76. examples/includes/PHP-SmartyPants-1.5.1e/smartypants.php +860 −0
  77. examples/includes/geshi/contrib/aliased.php +124 −0
  78. examples/includes/geshi/contrib/cssgen.php +456 −0
  79. examples/includes/geshi/contrib/cssgen2.php +59 −0
  80. examples/includes/geshi/contrib/example.php +217 −0
  81. examples/includes/geshi/contrib/langcheck.php +666 −0
  82. examples/includes/geshi/docs/BUGS +29 −0
  83. examples/includes/geshi/docs/CHANGES +682 −0
  84. examples/includes/geshi/docs/COPYING +340 −0
  85. examples/includes/geshi/docs/README +33 −0
  86. examples/includes/geshi/docs/THANKS +163 −0
  87. examples/includes/geshi/docs/TODO +71 −0
  88. examples/includes/geshi/docs/api/__filesource/fsource_geshi_core_geshi.php.html +4616 −0
  89. examples/includes/geshi/docs/api/blank.html +13 −0
  90. examples/includes/geshi/docs/api/classtrees_geshi.html +24 −0
  91. examples/includes/geshi/docs/api/elementindex.html +867 −0
  92. examples/includes/geshi/docs/api/elementindex_geshi.html +864 −0
  93. examples/includes/geshi/docs/api/errors.html +20 −0
  94. examples/includes/geshi/docs/api/geshi/core/GeSHi.html +2676 −0
  95. examples/includes/geshi/docs/api/geshi/core/_geshi.php.html +478 −0
  96. examples/includes/geshi/docs/api/index.html +24 −0
  97. examples/includes/geshi/docs/api/li_geshi.html +46 −0
  98. examples/includes/geshi/docs/api/media/banner.css +33 −0
  99. examples/includes/geshi/docs/api/media/images/AbstractClass.png +0 −0
  100. examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png +0 −0
  101. examples/includes/geshi/docs/api/media/images/AbstractMethod.png +0 −0
  102. examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png +0 −0
  103. examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png +0 −0
  104. examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png +0 −0
  105. examples/includes/geshi/docs/api/media/images/Class.png +0 −0
  106. examples/includes/geshi/docs/api/media/images/Class_logo.png +0 −0
  107. examples/includes/geshi/docs/api/media/images/Constant.png +0 −0
  108. examples/includes/geshi/docs/api/media/images/Constructor.png +0 −0
  109. examples/includes/geshi/docs/api/media/images/Destructor.png +0 −0
  110. examples/includes/geshi/docs/api/media/images/Function.png +0 −0
  111. examples/includes/geshi/docs/api/media/images/Global.png +0 −0
  112. examples/includes/geshi/docs/api/media/images/I.png +0 −0
  113. examples/includes/geshi/docs/api/media/images/Index.png +0 −0
  114. examples/includes/geshi/docs/api/media/images/Interface.png +0 −0
  115. examples/includes/geshi/docs/api/media/images/Interface_logo.png +0 −0
  116. examples/includes/geshi/docs/api/media/images/L.png +0 −0
  117. examples/includes/geshi/docs/api/media/images/Lminus.png +0 −0
  118. examples/includes/geshi/docs/api/media/images/Lplus.png +0 −0
  119. examples/includes/geshi/docs/api/media/images/Method.png +0 −0
  120. examples/includes/geshi/docs/api/media/images/Page.png +0 −0
  121. examples/includes/geshi/docs/api/media/images/Page_logo.png +0 −0
  122. examples/includes/geshi/docs/api/media/images/PrivateClass.png +0 −0
  123. examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png +0 −0
  124. examples/includes/geshi/docs/api/media/images/PrivateMethod.png +0 −0
  125. examples/includes/geshi/docs/api/media/images/PrivateVariable.png +0 −0
  126. examples/includes/geshi/docs/api/media/images/StaticMethod.png +0 −0
  127. examples/includes/geshi/docs/api/media/images/StaticVariable.png +0 −0
  128. examples/includes/geshi/docs/api/media/images/T.png +0 −0
  129. examples/includes/geshi/docs/api/media/images/Tminus.png +0 −0
  130. examples/includes/geshi/docs/api/media/images/Tplus.png +0 −0
  131. examples/includes/geshi/docs/api/media/images/Variable.png +0 −0
  132. examples/includes/geshi/docs/api/media/images/blank.png +0 −0
  133. examples/includes/geshi/docs/api/media/images/class_folder.png +0 −0
  134. examples/includes/geshi/docs/api/media/images/empty.png +0 −0
  135. examples/includes/geshi/docs/api/media/images/file.png +0 −0
  136. examples/includes/geshi/docs/api/media/images/folder.png +0 −0
  137. examples/includes/geshi/docs/api/media/images/function_folder.png +0 −0
  138. examples/includes/geshi/docs/api/media/images/next_button.png +0 −0
  139. examples/includes/geshi/docs/api/media/images/next_button_disabled.png +0 −0
  140. examples/includes/geshi/docs/api/media/images/package.png +0 −0
  141. examples/includes/geshi/docs/api/media/images/package_folder.png +0 −0
  142. examples/includes/geshi/docs/api/media/images/previous_button.png +0 −0
  143. examples/includes/geshi/docs/api/media/images/previous_button_disabled.png +0 −0
  144. examples/includes/geshi/docs/api/media/images/private_class_logo.png +0 −0
  145. examples/includes/geshi/docs/api/media/images/tutorial.png +0 −0
  146. examples/includes/geshi/docs/api/media/images/tutorial_folder.png +0 −0
  147. examples/includes/geshi/docs/api/media/images/up_button.png +0 −0
  148. examples/includes/geshi/docs/api/media/stylesheet.css +145 −0
  149. examples/includes/geshi/docs/api/packages.html +29 −0
  150. examples/includes/geshi/docs/api/todolist.html +42 −0
  151. examples/includes/geshi/docs/geshi-doc.html +4051 −0
  152. examples/includes/geshi/docs/geshi-doc.txt +1740 −0
  153. examples/includes/geshi/docs/phpdoc.ini +90 −0
  154. examples/includes/geshi/geshi.php +4619 −0
  155. examples/includes/geshi/geshi/abap.php +1419 −0
  156. examples/includes/geshi/geshi/actionscript.php +197 −0
  157. examples/includes/geshi/geshi/actionscript3.php +467 −0
  158. examples/includes/geshi/geshi/ada.php +133 −0
  159. examples/includes/geshi/geshi/apache.php +206 −0
  160. examples/includes/geshi/geshi/applescript.php +157 −0
  161. examples/includes/geshi/geshi/apt_sources.php +144 −0
  162. examples/includes/geshi/geshi/asm.php +225 −0
  163. examples/includes/geshi/geshi/asp.php +164 −0
  164. examples/includes/geshi/geshi/autoit.php +1171 −0
  165. examples/includes/geshi/geshi/avisynth.php +194 −0
  166. examples/includes/geshi/geshi/bash.php +282 −0
  167. examples/includes/geshi/geshi/basic4gl.php +341 −0
  168. examples/includes/geshi/geshi/bf.php +114 −0
  169. examples/includes/geshi/geshi/blitzbasic.php +185 −0
  170. examples/includes/geshi/geshi/bnf.php +110 −0
  171. examples/includes/geshi/geshi/boo.php +217 −0
  172. examples/includes/geshi/geshi/c.php +188 −0
  173. examples/includes/geshi/geshi/c_mac.php +212 −0
  174. examples/includes/geshi/geshi/caddcl.php +126 −0
  175. examples/includes/geshi/geshi/cadlisp.php +186 −0
  176. examples/includes/geshi/geshi/cfdg.php +124 −0
  177. examples/includes/geshi/geshi/cfm.php +299 −0
  178. examples/includes/geshi/geshi/cil.php +196 −0
  179. examples/includes/geshi/geshi/cobol.php +244 −0
  180. examples/includes/geshi/geshi/cpp-qt.php +315 −0
  181. examples/includes/geshi/geshi/cpp.php +226 −0
  182. examples/includes/geshi/geshi/csharp.php +249 −0
  183. examples/includes/geshi/geshi/css.php +212 −0
  184. examples/includes/geshi/geshi/d.php +272 −0
  185. examples/includes/geshi/geshi/dcs.php +185 −0
  186. examples/includes/geshi/geshi/delphi.php +289 −0
  187. examples/includes/geshi/geshi/diff.php +196 −0
  188. examples/includes/geshi/geshi/div.php +126 −0
  189. examples/includes/geshi/geshi/dos.php +198 −0
  190. examples/includes/geshi/geshi/dot.php +164 −0
  191. examples/includes/geshi/geshi/eiffel.php +395 −0
  192. examples/includes/geshi/geshi/email.php +209 −0
  193. examples/includes/geshi/geshi/fortran.php +160 −0
  194. examples/includes/geshi/geshi/freebasic.php +141 −0
  195. examples/includes/geshi/geshi/genero.php +463 −0
  196. examples/includes/geshi/geshi/gettext.php +97 −0
  197. examples/includes/geshi/geshi/glsl.php +205 −0
  198. examples/includes/geshi/geshi/gml.php +506 −0
  199. examples/includes/geshi/geshi/gnuplot.php +296 −0
  200. examples/includes/geshi/geshi/groovy.php +1011 −0
  201. examples/includes/geshi/geshi/haskell.php +198 −0
  202. examples/includes/geshi/geshi/hq9plus.php +104 −0
  203. examples/includes/geshi/geshi/html4strict.php +203 −0
  204. examples/includes/geshi/geshi/idl.php +123 −0
  205. examples/includes/geshi/geshi/ini.php +128 −0
  206. examples/includes/geshi/geshi/inno.php +212 −0
  207. examples/includes/geshi/geshi/intercal.php +122 −0
  208. examples/includes/geshi/geshi/io.php +138 −0
  209. examples/includes/geshi/geshi/java.php +983 −0
  210. examples/includes/geshi/geshi/java5.php +1031 −0
  211. examples/includes/geshi/geshi/javascript.php +150 −0
  212. examples/includes/geshi/geshi/kixtart.php +329 −0
  213. examples/includes/geshi/geshi/klonec.php +282 −0
  214. examples/includes/geshi/geshi/klonecpp.php +310 −0
  215. examples/includes/geshi/geshi/latex.php +209 −0
  216. examples/includes/geshi/geshi/lisp.php +144 −0
  217. examples/includes/geshi/geshi/locobasic.php +130 −0
  218. examples/includes/geshi/geshi/lolcode.php +152 −0
  219. examples/includes/geshi/geshi/lotusformulas.php +318 −0
  220. examples/includes/geshi/geshi/lotusscript.php +191 −0
  221. examples/includes/geshi/geshi/lscript.php +387 −0
  222. examples/includes/geshi/geshi/lsl2.php +898 −0
  223. examples/includes/geshi/geshi/lua.php +137 −0
  224. examples/includes/geshi/geshi/m68k.php +143 −0
  225. examples/includes/geshi/geshi/make.php +151 −0
  226. examples/includes/geshi/geshi/matlab.php +227 −0
  227. examples/includes/geshi/geshi/mirc.php +173 −0
  228. examples/includes/geshi/geshi/modula3.php +135 −0
  229. examples/includes/geshi/geshi/mpasm.php +164 −0
  230. examples/includes/geshi/geshi/mxml.php +145 −0
  231. examples/includes/geshi/geshi/mysql.php +475 −0
  232. examples/includes/geshi/geshi/nsis.php +351 −0
  233. examples/includes/geshi/geshi/objc.php +358 −0
  234. examples/includes/geshi/geshi/ocaml-brief.php +112 −0
  235. examples/includes/geshi/geshi/ocaml.php +174 −0
  236. examples/includes/geshi/geshi/oobas.php +135 −0
  237. examples/includes/geshi/geshi/oracle11.php +614 −0
  238. examples/includes/geshi/geshi/oracle8.php +496 −0
  239. examples/includes/geshi/geshi/pascal.php +152 −0
  240. examples/includes/geshi/geshi/per.php +302 −0
  241. examples/includes/geshi/geshi/perl.php +213 −0
  242. examples/includes/geshi/geshi/php-brief.php +202 −0
  243. examples/includes/geshi/geshi/php.php +1094 −0
  244. examples/includes/geshi/geshi/pic16.php +141 −0
  245. examples/includes/geshi/geshi/pixelbender.php +176 −0
  246. examples/includes/geshi/geshi/plsql.php +256 −0
  247. examples/includes/geshi/geshi/povray.php +199 −0
  248. examples/includes/geshi/geshi/powershell.php +279 −0
  249. examples/includes/geshi/geshi/progress.php +479 −0
  250. examples/includes/geshi/geshi/prolog.php +143 −0
  251. examples/includes/geshi/geshi/providex.php +299 −0
  252. examples/includes/geshi/geshi/python.php +237 −0
  253. examples/includes/geshi/geshi/qbasic.php +151 −0
  254. examples/includes/geshi/geshi/rails.php +406 −0
  255. examples/includes/geshi/geshi/rebol.php +196 −0
  256. examples/includes/geshi/geshi/reg.php +233 −0
  257. examples/includes/geshi/geshi/robots.php +98 −0
  258. examples/includes/geshi/geshi/ruby.php +226 −0
  259. examples/includes/geshi/geshi/sas.php +290 −0
  260. examples/includes/geshi/geshi/scala.php +122 −0
  261. examples/includes/geshi/geshi/scheme.php +170 −0
  262. examples/includes/geshi/geshi/scilab.php +295 −0
  263. examples/includes/geshi/geshi/sdlbasic.php +165 −0
  264. examples/includes/geshi/geshi/smalltalk.php +160 −0
  265. examples/includes/geshi/geshi/smarty.php +192 −0
  266. examples/includes/geshi/geshi/sql.php +140 −0
  267. examples/includes/geshi/geshi/tcl.php +194 −0
  268. examples/includes/geshi/geshi/teraterm.php +317 −0
  269. examples/includes/geshi/geshi/text.php +84 −0
  270. examples/includes/geshi/geshi/thinbasic.php +868 −0
  271. examples/includes/geshi/geshi/tsql.php +378 −0
  272. examples/includes/geshi/geshi/typoscript.php +300 −0
  273. examples/includes/geshi/geshi/vb.php +133 −0
  274. examples/includes/geshi/geshi/vbnet.php +201 −0
  275. examples/includes/geshi/geshi/verilog.php +173 −0
  276. examples/includes/geshi/geshi/vhdl.php +144 −0
  277. examples/includes/geshi/geshi/vim.php +185 −0
  278. examples/includes/geshi/geshi/visualfoxpro.php +456 −0
  279. examples/includes/geshi/geshi/visualprolog.php +129 −0
  280. examples/includes/geshi/geshi/whitespace.php +121 −0
  281. examples/includes/geshi/geshi/winbatch.php +369 −0
  282. examples/includes/geshi/geshi/xml.php +157 −0
  283. examples/includes/geshi/geshi/xorg_conf.php +124 −0
  284. examples/includes/geshi/geshi/xpp.php +436 −0
  285. examples/includes/geshi/geshi/z80.php +144 −0
  286. examples/includes/vp8_doc_tools.php +207 −0
  287. examples/postproc.txt +67 −0
  288. examples/simple_decoder.txt +96 −0
  289. examples/simple_encoder.txt +105 −0
  290. examples/twopass_encoder.txt +75 −0
  291. examples/vp8_scalable_patterns.txt +143 −0
  292. examples/vp8_set_maps.txt +96 −0
  293. examples/vp8cx_set_ref.txt +73 −0
  294. ivfdec.c +593 −0
  295. ivfenc.c +1059 −0
  296. keywords.dox +51 −0
  297. libs.doxy_template +1307 −0
  298. libs.mk +225 −0
  299. mainpage.dox +45 −0
  300. md5_utils.c +298 −0
  301. md5_utils.h +51 −0
  302. release.sh +209 −0
  303. solution.mk +54 −0
  304. usage.dox +203 −0
  305. usage_cx.dox +14 −0
  306. usage_dx.dox +62 −0
  307. vp8/common/alloccommon.c +251 −0
  308. vp8/common/alloccommon.h +22 −0
  309. vp8/common/arm/armv6/bilinearfilter_v6.asm +237 −0
  310. vp8/common/arm/armv6/copymem16x16_v6.asm +181 −0
  311. vp8/common/arm/armv6/copymem8x4_v6.asm +127 −0
  312. vp8/common/arm/armv6/copymem8x8_v6.asm +127 −0
  313. vp8/common/arm/armv6/filter_v6.asm +383 −0
  314. vp8/common/arm/armv6/idct_v6.asm +376 −0
  315. vp8/common/arm/armv6/iwalsh_v6.asm +151 −0
  316. vp8/common/arm/armv6/loopfilter_v6.asm +1263 −0
  317. vp8/common/arm/armv6/recon_v6.asm +280 −0
  318. vp8/common/arm/armv6/simpleloopfilter_v6.asm +321 −0
  319. vp8/common/arm/armv6/sixtappredict8x4_v6.asm +277 −0
  320. vp8/common/arm/bilinearfilter_arm.c +211 −0
  321. vp8/common/arm/filter_arm.c +234 −0
  322. vp8/common/arm/idct_arm.h +60 −0
  323. vp8/common/arm/loopfilter_arm.c +246 −0
  324. vp8/common/arm/loopfilter_arm.h +84 −0
  325. vp8/common/arm/neon/bilinearpredict16x16_neon.asm +361 −0
  326. vp8/common/arm/neon/bilinearpredict4x4_neon.asm +134 −0
  327. vp8/common/arm/neon/bilinearpredict8x4_neon.asm +139 −0
  328. vp8/common/arm/neon/bilinearpredict8x8_neon.asm +187 −0
  329. vp8/common/arm/neon/buildintrapredictorsmby_neon.asm +583 −0
  330. vp8/common/arm/neon/copymem16x16_neon.asm +58 −0
  331. vp8/common/arm/neon/copymem8x4_neon.asm +33 −0
  332. vp8/common/arm/neon/copymem8x8_neon.asm +42 −0
  333. vp8/common/arm/neon/iwalsh_neon.asm +95 −0
  334. vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm +205 −0
  335. vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm +188 −0
  336. vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm +117 −0
  337. vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm +158 −0
  338. vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm +231 −0
  339. vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm +235 −0
  340. vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm +257 −0
  341. vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm +236 −0
  342. vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm +296 −0
  343. vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm +303 −0
  344. vp8/common/arm/neon/recon16x16mb_neon.asm +130 −0
  345. vp8/common/arm/neon/recon2b_neon.asm +53 −0
  346. vp8/common/arm/neon/recon4b_neon.asm +68 −0
  347. vp8/common/arm/neon/reconb_neon.asm +60 −0
  348. vp8/common/arm/neon/save_neon_reg.asm +35 −0
  349. vp8/common/arm/neon/shortidct4x4llm_1_neon.asm +66 −0
  350. vp8/common/arm/neon/shortidct4x4llm_neon.asm +126 −0
  351. vp8/common/arm/neon/sixtappredict16x16_neon.asm +494 −0
  352. vp8/common/arm/neon/sixtappredict4x4_neon.asm +425 −0
  353. vp8/common/arm/neon/sixtappredict8x4_neon.asm +476 −0
  354. vp8/common/arm/neon/sixtappredict8x8_neon.asm +527 −0
  355. vp8/common/arm/recon_arm.c +108 −0
  356. vp8/common/arm/recon_arm.h +70 −0
  357. vp8/common/arm/reconintra4x4_arm.c +408 −0
  358. vp8/common/arm/reconintra_arm.c +61 −0
  359. vp8/common/arm/subpixel_arm.h +84 −0
  360. vp8/common/arm/systemdependent.c +148 −0
  361. vp8/common/arm/vpx_asm_offsets.c +91 −0
  362. vp8/common/bigend.h +31 −0
  363. vp8/common/blockd.c +23 −0
  364. vp8/common/blockd.h +299 −0
  365. vp8/common/boolcoder.h +569 −0
  366. vp8/common/codec_common_interface.h +92 −0
  367. vp8/common/coefupdateprobs.h +184 −0
  368. vp8/common/common.h +41 −0
  369. vp8/common/common_types.h +17 −0
  370. vp8/common/context.c +398 −0
  371. vp8/common/debugmodes.c +156 −0
  372. vp8/common/defaultcoefcounts.h +220 −0
  373. vp8/common/dma_desc.h +124 −0
  374. vp8/common/duck_io.h +115 −0
  375. vp8/common/entropy.c +161 −0
  376. vp8/common/entropy.h +101 −0
  377. vp8/common/entropymode.c +270 −0
  378. vp8/common/entropymode.h +71 −0
  379. vp8/common/entropymv.c +48 −0
  380. vp8/common/entropymv.h +41 −0
  381. vp8/common/extend.c +120 −0
  382. vp8/common/extend.h +20 −0
  383. vp8/common/filter_c.c +539 −0
  384. vp8/common/findnearmv.c +207 −0
  385. vp8/common/findnearmv.h +41 −0
  386. vp8/common/fourcc.hpp +120 −0
  387. vp8/common/g_common.h +20 −0
  388. vp8/common/generic/systemdependent.c +79 −0
  389. vp8/common/header.h +42 −0
  390. vp8/common/idct.h +77 −0
  391. vp8/common/idctllm.c +189 −0
  392. vp8/common/invtrans.c +86 −0
  393. vp8/common/invtrans.h +22 −0
  394. vp8/common/littlend.h +32 −0
  395. vp8/common/loopfilter.c +601 −0
  396. vp8/common/loopfilter.h +120 −0
  397. vp8/common/loopfilter_filters.c +368 −0
  398. vp8/common/mac_specs.h +30 −0
  399. vp8/common/mbpitch.c +128 −0
  400. vp8/common/modecont.c +39 −0
  401. vp8/common/modecont.h +16 −0
  402. vp8/common/modecontext.c +145 −0
  403. vp8/common/mv.h +20 −0
  404. vp8/common/onyx.h +222 −0
  405. vp8/common/onyxc_int.h +205 −0
  406. vp8/common/onyxd.h +67 −0
  407. vp8/common/partialgfupdate.h +18 −0
  408. vp8/common/postproc.c +641 −0
  409. vp8/common/postproc.h +90 −0
  410. vp8/common/ppc/copy_altivec.asm +46 −0
  411. vp8/common/ppc/filter_altivec.asm +1012 −0
  412. vp8/common/ppc/filter_bilinear_altivec.asm +676 −0
  413. vp8/common/ppc/idctllm_altivec.asm +188 −0
  414. vp8/common/ppc/loopfilter_altivec.c +142 −0
  415. vp8/common/ppc/loopfilter_filters_altivec.asm +1252 −0
  416. vp8/common/ppc/platform_altivec.asm +58 −0
  417. vp8/common/ppc/recon_altivec.asm +174 −0
  418. vp8/common/ppc/systemdependent.c +170 −0
  419. vp8/common/ppflags.h +25 −0
  420. vp8/common/pragmas.h +18 −0
  421. vp8/common/predictdc.c +43 −0
  422. vp8/common/predictdc.h +17 −0
  423. vp8/common/preproc.h +45 −0
  424. vp8/common/preprocif.h +75 −0
  425. vp8/common/proposed.h +70 −0
  426. vp8/common/quant_common.c +131 −0
  427. vp8/common/quant_common.h +20 −0
  428. vp8/common/recon.c +137 −0
  429. vp8/common/recon.h +81 −0
  430. vp8/common/reconinter.c +680 −0
  431. vp8/common/reconinter.h +22 −0
  432. vp8/common/reconintra.c +555 −0
  433. vp8/common/reconintra.h +28 −0
  434. vp8/common/reconintra4x4.c +330 −0
  435. vp8/common/reconintra4x4.h +16 −0
  436. vp8/common/segmentation_common.c +63 −0
  437. vp8/common/segmentation_common.h +15 −0
  438. vp8/common/setupintrarecon.c +37 −0
  439. vp8/common/setupintrarecon.h +12 −0
  440. vp8/common/subpixel.h +85 −0
  441. vp8/common/swapyv12buffer.c +33 −0
  442. vp8/common/swapyv12buffer.h +18 −0
  443. vp8/common/systemdependent.h +20 −0
  444. vp8/common/textblit.c +52 −0
  445. vp8/common/threading.h +89 −0
  446. vp8/common/treecoder.c +136 −0
  447. vp8/common/treecoder.h +87 −0
  448. vp8/common/type_aliases.h +116 −0
  449. vp8/common/vfwsetting.hpp +75 −0
  450. vp8/common/vpx_ref_build_prefix.h +23 −0
  451. vp8/common/vpxblit.h +111 −0
  452. vp8/common/vpxblit_c64.h +47 −0
  453. vp8/common/vpxerrors.h +12 −0
  454. vp8/common/x86/boolcoder.cxx +493 −0
  455. vp8/common/x86/idct_x86.h +63 −0
  456. vp8/common/x86/idctllm_mmx.asm +265 −0
  457. vp8/common/x86/iwalsh_mmx.asm +172 −0
  458. vp8/common/x86/iwalsh_sse2.asm +116 −0
  459. vp8/common/x86/loopfilter_mmx.asm +1776 −0
  460. vp8/common/x86/loopfilter_sse2.asm +1978 −0
  461. vp8/common/x86/loopfilter_x86.c +274 −0
  462. vp8/common/x86/loopfilter_x86.h +99 −0
  463. vp8/common/x86/postproc_mmx.asm +533 −0
  464. vp8/common/x86/postproc_mmx.c +1507 −0
  465. vp8/common/x86/postproc_sse2.asm +688 −0
  466. vp8/common/x86/postproc_x86.h +63 −0
  467. vp8/common/x86/recon_mmx.asm +320 −0
  468. vp8/common/x86/recon_sse2.asm +228 −0
  469. vp8/common/x86/recon_x86.h +61 −0
  470. vp8/common/x86/subpixel_mmx.asm +817 −0
  471. vp8/common/x86/subpixel_sse2.asm +1032 −0
  472. vp8/common/x86/subpixel_x86.h +88 −0
  473. vp8/common/x86/vp8_asm_stubs.c +342 −0
  474. vp8/common/x86/x86_systemdependent.c +117 −0
  475. vp8/decoder/arm/armv5/dequantize_v5.asm +51 −0
  476. vp8/decoder/arm/armv6/dboolhuff_v6.asm +162 −0
  477. vp8/decoder/arm/armv6/dequantdcidct_v6.asm +202 −0
  478. vp8/decoder/arm/armv6/dequantidct_v6.asm +183 −0
  479. vp8/decoder/arm/armv6/dequantize_v6.asm +68 −0
  480. vp8/decoder/arm/dboolhuff_arm.h +49 −0
  481. vp8/decoder/arm/dequantize_arm.c +48 −0
  482. vp8/decoder/arm/dequantize_arm.h +44 −0
  483. vp8/decoder/arm/detokenizearm_sjl.c +730 −0
  484. vp8/decoder/arm/detokenizearm_v6.asm +364 −0
  485. vp8/decoder/arm/dsystemdependent.c +44 −0
  486. vp8/decoder/arm/neon/dboolhuff_neon.asm +159 −0
  487. vp8/decoder/arm/neon/dequantdcidct_neon.asm +133 −0
  488. vp8/decoder/arm/neon/dequantidct_neon.asm +128 −0
  489. vp8/decoder/arm/neon/dequantizeb_neon.asm +33 −0
  490. vp8/decoder/dboolhuff.c +174 −0
  491. vp8/decoder/dboolhuff.h +226 −0
  492. vp8/decoder/decodemv.c +418 −0
  493. vp8/decoder/decodemv.h +13 −0
  494. vp8/decoder/decoderthreading.h +24 −0
  495. vp8/decoder/decodframe.c +907 −0
  496. vp8/decoder/demode.c +149 −0
  497. vp8/decoder/demode.h +32 −0
  498. vp8/decoder/dequantize.c +60 −0
  499. vp8/decoder/dequantize.h +64 −0
  500. vp8/decoder/detokenize.c +374 −0
  501. vp8/decoder/detokenize.h +19 −0
  502. vp8/decoder/generic/dsystemdependent.c +37 −0
  503. vp8/decoder/onyxd_if.c +451 −0
  504. vp8/decoder/onyxd_if_sjl.c +398 −0
  505. vp8/decoder/onyxd_int.h +149 −0
  506. vp8/decoder/threading.c +596 −0
  507. vp8/decoder/treereader.h +63 −0
  508. vp8/decoder/x86/dequantize_mmx.asm +410 −0
  509. vp8/decoder/x86/dequantize_x86.h +40 −0
  510. vp8/decoder/x86/onyxdxv.c +1079 −0
  511. vp8/decoder/x86/x86_dsystemdependent.c +51 −0
  512. vp8/decoder/xprintf.c +163 −0
  513. vp8/decoder/xprintf.h +32 −0
  514. vp8/encoder/arm/armv6/walsh_v6.asm +144 −0
  515. vp8/encoder/arm/boolhuff_arm.c +33 −0
  516. vp8/encoder/arm/csystemdependent.c +159 −0
  517. vp8/encoder/arm/dct_arm.h +45 −0
  518. vp8/encoder/arm/encodemb_arm.c +30 −0
  519. vp8/encoder/arm/encodemb_arm.h +43 −0
  520. vp8/encoder/arm/mcomp_arm.c +1662 −0
  521. vp8/encoder/arm/neon/boolhuff_armv7.asm +292 −0
  522. vp8/encoder/arm/neon/fastfdct4x4_neon.asm +126 −0
  523. vp8/encoder/arm/neon/fastfdct8x4_neon.asm +179 −0
  524. vp8/encoder/arm/neon/fastquantizeb_neon.asm +117 −0
  525. vp8/encoder/arm/neon/sad16_neon.asm +206 −0
  526. vp8/encoder/arm/neon/sad8_neon.asm +208 −0
  527. vp8/encoder/arm/neon/shortfdct_neon.asm +146 −0
  528. vp8/encoder/arm/neon/subtract_neon.asm +171 −0
  529. vp8/encoder/arm/neon/variance_neon.asm +275 −0
  530. vp8/encoder/arm/neon/vp8_memcpy_neon.asm +67 −0
  531. vp8/encoder/arm/neon/vp8_mse16x16_neon.asm +172 −0
  532. vp8/encoder/arm/neon/vp8_packtokens_armv7.asm +300 −0
  533. vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm +335 −0
  534. vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm +471 −0
  535. vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm +75 −0
  536. vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm +427 −0
  537. vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm +571 −0
  538. vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm +226 −0
  539. vp8/encoder/arm/picklpf_arm.c +49 −0
  540. vp8/encoder/arm/quantize_arm.c +79 −0
  541. vp8/encoder/arm/quantize_arm.h +22 −0
  542. vp8/encoder/arm/variance_arm.h +105 −0
  543. vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c +77 −0
  544. vp8/encoder/bitstream.c +1719 −0
  545. vp8/encoder/bitstream.h +38 −0
  546. vp8/encoder/block.h +115 −0
  547. vp8/encoder/boolhuff.c +147 −0
  548. vp8/encoder/boolhuff.h +42 −0
  549. vp8/encoder/dct.c +223 −0
  550. vp8/encoder/dct.h +65 −0
  551. vp8/encoder/encodeframe.c +1223 −0
  552. vp8/encoder/encodeintra.c +236 −0
  553. vp8/encoder/encodeintra.h +24 −0
  554. vp8/encoder/encodemb.c +1129 −0
  555. vp8/encoder/encodemb.h +112 −0
  556. vp8/encoder/encodemv.c +445 −0
  557. vp8/encoder/encodemv.h +20 −0
  558. vp8/encoder/ethreading.c +510 −0
  559. vp8/encoder/firstpass.c +2512 −0
  560. vp8/encoder/firstpass.h +22 −0
  561. vp8/encoder/generic/csystemdependent.c +96 −0
  562. vp8/encoder/mcomp.c +1467 −0
  563. vp8/encoder/mcomp.h +121 −0
  564. vp8/encoder/modecosts.c +46 −0
  565. vp8/encoder/modecosts.h +16 −0
  566. vp8/encoder/onyx_if.c +5428 −0
  567. vp8/encoder/onyx_int.h +670 −0
  568. vp8/encoder/parms.cpp +106 −0
  569. vp8/encoder/pickinter.c +923 −0
  570. vp8/encoder/pickinter.h +20 −0
  571. vp8/encoder/picklpf.c +435 −0
  572. vp8/encoder/ppc/csystemdependent.c +168 −0
  573. vp8/encoder/ppc/encodemb_altivec.asm +152 −0
  574. vp8/encoder/ppc/fdct_altivec.asm +204 −0
  575. vp8/encoder/ppc/rdopt_altivec.asm +50 −0
  576. vp8/encoder/ppc/sad_altivec.asm +276 −0
  577. vp8/encoder/ppc/variance_altivec.asm +374 −0
  578. vp8/encoder/ppc/variance_subpixel_altivec.asm +864 −0
  579. vp8/encoder/preproc.c +250 −0
  580. vp8/encoder/psnr.c +116 −0
  581. vp8/encoder/psnr.h +17 −0
  582. vp8/encoder/quantize.c +249 −0
  583. vp8/encoder/quantize.h +52 −0
  584. vp8/encoder/ratectrl.c +1552 −0
  585. vp8/encoder/ratectrl.h +26 −0
  586. vp8/encoder/rdopt.c +2212 −0
  587. vp8/encoder/rdopt.h +20 −0
  588. vp8/encoder/sad_c.c +248 −0
  589. vp8/encoder/ssim.c +521 −0
  590. vp8/encoder/tokenize.c +636 −0
  591. vp8/encoder/tokenize.h +38 −0
  592. vp8/encoder/treewriter.c +38 −0
  593. vp8/encoder/treewriter.h +121 −0
  594. vp8/encoder/variance.h +327 −0
  595. vp8/encoder/variance_c.c +527 −0
  596. vp8/encoder/x86/csystemdependent.c +289 −0
  597. vp8/encoder/x86/dct_mmx.asm +846 −0
  598. vp8/encoder/x86/dct_sse2.asm +260 −0
  599. vp8/encoder/x86/dct_x86.h +73 −0
  600. vp8/encoder/x86/encodemb_x86.h +73 −0
  601. vp8/encoder/x86/encodeopt.asm +393 −0
  602. vp8/encoder/x86/fwalsh_sse2.asm +117 −0
  603. vp8/encoder/x86/mcomp_x86.h +27 −0
  604. vp8/encoder/x86/preproc_mmx.c +297 −0
.gitattributes+18−0
@@ -0,0 +1,18 @@
1+*.[chs] filter=fixtabswsp
2+*.[ch]pp filter=fixtabswsp
3+*.[ch]xx filter=fixtabswsp
4+*.asm filter=fixtabswsp
5+*.php filter=fixtabswsp
6+*.pl filter=fixtabswsp
7+*.sh filter=fixtabswsp
8+*.txt filter=fixwsp
9+[Mm]akefile filter=fixwsp
10+*.mk filter=fixwsp
11+*.rc -crlf
12+*.ds[pw] -crlf
13+*.bat -crlf
14+*.mmp -crlf
15+*.dpj -crlf
16+*.pjt -crlf
17+*.vcp -crlf
18+*.inf -crlf
AUTHORS+4−0
@@ -0,0 +1,4 @@
1+# Names should be added to this file like so:
2+# Name or Organization <email address>
3+
4+Google Inc.
CHANGELOG+3−0
@@ -0,0 +1,3 @@
1+2010-05-18 v0.9.0
2+ - Initial open source release. Welcome to WebM and VP8!
3+
LICENSE+48−0
@@ -0,0 +1,48 @@
1+Copyright (c) 2010, Google, Inc.
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions
7+are met:
8+
9+- Redistributions of source code must retain the above copyright
10+ notice, this list of conditions and the following disclaimer.
11+
12+- Redistributions in binary form must reproduce the above
13+ copyright notice, this list of conditions and the following
14+ disclaimer in the documentation and/or other materials provided
15+ with the distribution.
16+
17+- Neither the name of Google nor the names of its contributors may
18+ be used to endorse or promote products derived from this software
19+ without specific prior written permission.
20+
21+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32+
33+Subject to the terms and conditions of the above License, Google
34+hereby grants to You a perpetual, worldwide, non-exclusive,
35+no-charge, royalty-free, irrevocable (except as stated in this
36+section) patent license to make, have made, use, offer to sell, sell,
37+import, and otherwise transfer this implementation of VP8, where such
38+license applies only to those patent claims, both currently owned by
39+Google and acquired in the future, licensable by Google that are
40+necessarily infringed by this implementation of VP8. If You or your
41+agent or exclusive licensee institute or order or agree to the
42+institution of patent litigation against any entity (including a
43+cross-claim or counterclaim in a lawsuit) alleging that this
44+implementation of VP8 or any code incorporated within this
45+implementation of VP8 constitutes direct or contributory patent
46+infringement, or inducement of patent infringement, then any rights
47+granted to You under this License for this implementation of VP8
48+shall terminate as of the date such litigation is filed.
README+106−0
@@ -0,0 +1,106 @@
1+vpx Multi-Format Codec SDK
2+README - 19 May 2010
3+
4+Welcome to the WebM VP8 Codec SDK!
5+
6+COMPILING THE APPLICATIONS/LIBRARIES:
7+ The build system used is similar to autotools. Building generally consists of
8+ "configuring" with your desired build options, then using GNU make to build
9+ the application.
10+
11+ 1. Prerequisites
12+
13+ * All x86 targets require the Yasm[1] assembler be installed.
14+ * All Windows builds require that Cygwin[2] be installed.
15+ * Building the documentation requires PHP[3] and Doxygen[4]. If you do not
16+ have these packages, you must pass --disable-install-docs to the
17+ configure script.
18+
19+ [1]: http://www.tortall.net/projects/yasm
20+ [2]: http://www.cygwin.com
21+ [3]: http://php.net
22+ [4]: http://www.doxygen.org
23+
24+ 2. Out-of-tree builds
25+ Out of tree builds are a supported method of building the application. For
26+ an out of tree build, the source tree is kept separate from the object
27+ files produced during compilation. For instance:
28+
29+ $ mkdir build
30+ $ cd build
31+ $ ../libvpx/configure <options>
32+ $ make
33+
34+ 3. Configuration options
35+ The 'configure' script supports a number of options. The --help option can be
36+ used to get a list of supported options:
37+ $ ../libvpx/configure --help
38+
39+ 4. Cross development
40+ For cross development, the most notable option is the --target option. The
41+ most up-to-date list of supported targets can be found at the bottom of the
42+ --help output of the configure script. As of this writing, the list of
43+ available targets is:
44+
45+ armv5te-linux-rvct
46+ armv5te-linux-gcc
47+ armv5te-symbian-gcc
48+ armv5te-wince-vs8
49+ armv6-darwin-gcc
50+ armv6-linux-rvct
51+ armv6-linux-gcc
52+ armv6-symbian-gcc
53+ armv6-wince-vs8
54+ iwmmxt-linux-rvct
55+ iwmmxt-linux-gcc
56+ iwmmxt-wince-vs8
57+ iwmmxt2-linux-rvct
58+ iwmmxt2-linux-gcc
59+ iwmmxt2-wince-vs8
60+ armv7-linux-rvct
61+ armv7-linux-gcc
62+ mips32-linux-gcc
63+ ppc32-darwin8-gcc
64+ ppc32-darwin9-gcc
65+ ppc64-darwin8-gcc
66+ ppc64-darwin9-gcc
67+ ppc64-linux-gcc
68+ x86-darwin8-gcc
69+ x86-darwin8-icc
70+ x86-darwin9-gcc
71+ x86-darwin9-icc
72+ x86-linux-gcc
73+ x86-linux-icc
74+ x86-solaris-gcc
75+ x86-win32-vs7
76+ x86-win32-vs8
77+ x86_64-darwin9-gcc
78+ x86_64-linux-gcc
79+ x86_64-solaris-gcc
80+ x86_64-win64-vs8
81+ universal-darwin8-gcc
82+ universal-darwin9-gcc
83+ generic-gnu
84+
85+ The generic-gnu target, in conjunction with the CROSS environment variable,
86+ can be used to cross compile architectures that aren't explicitly listed, if
87+ the toolchain is a cross GNU (gcc/binutils) toolchain. Other POSIX toolchains
88+ will likely work as well. For instance, to build using the mipsel-linux-uclibc
89+ toolchain, the following command could be used (note, POSIX SH syntax, adapt
90+ to your shell as necessary):
91+
92+ $ CROSS=mipsel-linux-uclibc- ../libvpx/src/configure
93+
94+ In addition, the executables to be invoked can be overridden by specifying the
95+ environment variables: CC, AR, LD, AS, STRIP, NM. Additional flags can be
96+ passed to these executables with CFLAGS, LDFLAGS, and ASFLAGS.
97+
98+ 5. Configuration errors
99+ If the configuration step fails, the first step is to look in the error log.
100+ This defaults to config.err. This should give a good indication of what went
101+ wrong. If not, contact us for support.
102+
103+SUPPORT
104+ This library is an open source project supported by its community. Please
105+ please email webm-users@webmproject.org for help.
106+
args.c+215−0
@@ -0,0 +1,215 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+#include <stdlib.h>
12+#include <string.h>
13+#include <limits.h>
14+#include "args.h"
15+
16+#ifdef _MSC_VER
17+#define snprintf _snprintf
18+#endif
19+
20+#if defined(__GNUC__) && __GNUC__
21+extern void die(const char *fmt, ...) __attribute__((noreturn));
22+#else
23+extern void die(const char *fmt, ...);
24+#endif
25+
26+
27+struct arg arg_init(char **argv)
28+{
29+ struct arg a;
30+
31+ a.argv = argv;
32+ a.argv_step = 1;
33+ a.name = NULL;
34+ a.val = NULL;
35+ a.def = NULL;
36+ return a;
37+}
38+
39+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv)
40+{
41+ struct arg arg;
42+
43+ if (!argv[0] || argv[0][0] != '-')
44+ return 0;
45+
46+ arg = arg_init(argv);
47+
48+ if (def->short_name
49+ && strlen(arg.argv[0]) == strlen(def->short_name) + 1
50+ && !strcmp(arg.argv[0] + 1, def->short_name))
51+ {
52+
53+ arg.name = arg.argv[0] + 1;
54+ arg.val = def->has_val ? arg.argv[1] : NULL;
55+ arg.argv_step = def->has_val ? 2 : 1;
56+ }
57+ else if (def->long_name)
58+ {
59+ int name_len = strlen(def->long_name);
60+
61+ if (strlen(arg.argv[0]) >= name_len + 2
62+ && arg.argv[0][1] == '-'
63+ && !strncmp(arg.argv[0] + 2, def->long_name, name_len)
64+ && (arg.argv[0][name_len+2] == '='
65+ || arg.argv[0][name_len+2] == '\0'))
66+ {
67+
68+ arg.name = arg.argv[0] + 2;
69+ arg.val = arg.name[name_len] == '=' ? arg.name + name_len + 1 : NULL;
70+ arg.argv_step = 1;
71+ }
72+ }
73+
74+ if (arg.name && !arg.val && def->has_val)
75+ die("Error: option %s requires argument.\n", arg.name);
76+
77+ if (arg.name && arg.val && !def->has_val)
78+ die("Error: option %s requires no argument.\n", arg.name);
79+
80+ if (arg.name
81+ && (arg.val || !def->has_val))
82+ {
83+ arg.def = def;
84+ *arg_ = arg;
85+ return 1;
86+ }
87+
88+ return 0;
89+}
90+
91+
92+const char *arg_next(struct arg *arg)
93+{
94+ if (arg->argv[0])
95+ arg->argv += arg->argv_step;
96+
97+ return *arg->argv;
98+}
99+
100+
101+char **argv_dup(int argc, const char **argv)
102+{
103+ char **new_argv = malloc((argc + 1) * sizeof(*argv));
104+
105+ memcpy(new_argv, argv, argc * sizeof(*argv));
106+ new_argv[argc] = NULL;
107+ return new_argv;
108+}
109+
110+
111+void arg_show_usage(FILE *fp, const struct arg_def *const *defs)
112+{
113+ char option_text[40] = {0};
114+
115+ for (; *defs; defs++)
116+ {
117+ const struct arg_def *def = *defs;
118+ char *short_val = def->has_val ? " <arg>" : "";
119+ char *long_val = def->has_val ? "=<arg>" : "";
120+
121+ if (def->short_name && def->long_name)
122+ snprintf(option_text, 37, "-%s%s, --%s%s",
123+ def->short_name, short_val,
124+ def->long_name, long_val);
125+ else if (def->short_name)
126+ snprintf(option_text, 37, "-%s%s",
127+ def->short_name, short_val);
128+ else if (def->long_name)
129+ snprintf(option_text, 37, " --%s%s",
130+ def->long_name, long_val);
131+
132+ fprintf(fp, " %-37s\t%s\n", option_text, def->desc);
133+ }
134+}
135+
136+
137+unsigned int arg_parse_uint(const struct arg *arg)
138+{
139+ long int rawval;
140+ char *endptr;
141+
142+ rawval = strtol(arg->val, &endptr, 10);
143+
144+ if (arg->val[0] != '\0' && endptr[0] == '\0')
145+ {
146+ if (rawval >= 0 && rawval <= UINT_MAX)
147+ return rawval;
148+
149+ die("Option %s: Value %ld out of range for unsigned int\n",
150+ arg->name, rawval);
151+ }
152+
153+ die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
154+ return 0;
155+}
156+
157+
158+int arg_parse_int(const struct arg *arg)
159+{
160+ long int rawval;
161+ char *endptr;
162+
163+ rawval = strtol(arg->val, &endptr, 10);
164+
165+ if (arg->val[0] != '\0' && endptr[0] == '\0')
166+ {
167+ if (rawval >= INT_MIN && rawval <= INT_MAX)
168+ return rawval;
169+
170+ die("Option %s: Value %ld out of range for signed int\n",
171+ arg->name, rawval);
172+ }
173+
174+ die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
175+ return 0;
176+}
177+
178+
179+struct vpx_rational
180+{
181+ int num; /**< fraction numerator */
182+ int den; /**< fraction denominator */
183+};
184+struct vpx_rational arg_parse_rational(const struct arg *arg)
185+{
186+ long int rawval;
187+ char *endptr;
188+ struct vpx_rational rat;
189+
190+ /* parse numerator */
191+ rawval = strtol(arg->val, &endptr, 10);
192+
193+ if (arg->val[0] != '\0' && endptr[0] == '/')
194+ {
195+ if (rawval >= INT_MIN && rawval <= INT_MAX)
196+ rat.num = rawval;
197+ else die("Option %s: Value %ld out of range for signed int\n",
198+ arg->name, rawval);
199+ }
200+ else die("Option %s: Expected / at '%c'\n", arg->name, *endptr);
201+
202+ /* parse denominator */
203+ rawval = strtol(endptr + 1, &endptr, 10);
204+
205+ if (arg->val[0] != '\0' && endptr[0] == '\0')
206+ {
207+ if (rawval >= INT_MIN && rawval <= INT_MAX)
208+ rat.den = rawval;
209+ else die("Option %s: Value %ld out of range for signed int\n",
210+ arg->name, rawval);
211+ }
212+ else die("Option %s: Invalid character '%c'\n", arg->name, *endptr);
213+
214+ return rat;
215+}
args.h+43−0
@@ -0,0 +1,43 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+#ifndef ARGS_H
12+#define ARGS_H
13+#include <stdio.h>
14+
15+struct arg
16+{
17+ char **argv;
18+ const char *name;
19+ const char *val;
20+ unsigned int argv_step;
21+ const struct arg_def *def;
22+};
23+
24+typedef struct arg_def
25+{
26+ const char *short_name;
27+ const char *long_name;
28+ int has_val;
29+ const char *desc;
30+} arg_def_t;
31+#define ARG_DEF(s,l,v,d) {s,l,v,d}
32+#define ARG_DEF_LIST_END {0}
33+
34+struct arg arg_init(char **argv);
35+int arg_match(struct arg *arg_, const struct arg_def *def, char **argv);
36+const char *arg_next(struct arg *arg);
37+void arg_show_usage(FILE *fp, const struct arg_def *const *defs);
38+char **argv_dup(int argc, const char **argv);
39+
40+unsigned int arg_parse_uint(const struct arg *arg);
41+int arg_parse_int(const struct arg *arg);
42+struct vpx_rational arg_parse_rational(const struct arg *arg);
43+#endif
build/.gitignore+1−0
@@ -0,0 +1 @@
1+x86*-win32-vs*
build/arm-wince-vs8/.gitattributes+1−0
@@ -0,0 +1 @@
1+*.rules -crlf
build/arm-wince-vs8/armasmv5.rules+20−0
@@ -0,0 +1,20 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<VisualStudioToolFile
3+ Name="armasm"
4+ Version="8.00"
5+ >
6+ <Rules>
7+ <CustomBuildRule
8+ Name="ARMASM"
9+ DisplayName="Armasm Assembler"
10+ CommandLine="armasm -o &quot;$(IntDir)\$(InputName).obj&quot; $(InputPath) -32 -ARCH 5&#x0D;&#x0A;"
11+ Outputs="$(IntDir)\$(InputName).obj"
12+ FileExtensions="*.asm"
13+ ExecutionDescription="Assembling $(InputName).asm"
14+ ShowOnlyRuleProperties="false"
15+ >
16+ <Properties>
17+ </Properties>
18+ </CustomBuildRule>
19+ </Rules>
20+</VisualStudioToolFile>
build/arm-wince-vs8/armasmv6.rules+20−0
@@ -0,0 +1,20 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<VisualStudioToolFile
3+ Name="armasm"
4+ Version="8.00"
5+ >
6+ <Rules>
7+ <CustomBuildRule
8+ Name="ARMASM"
9+ DisplayName="Armasm Assembler"
10+ CommandLine="armasm -o &quot;$(IntDir)\$(InputName).obj&quot; $(InputPath) -32 -ARCH 6&#x0D;&#x0A;"
11+ Outputs="$(IntDir)\$(InputName).obj"
12+ FileExtensions="*.asm"
13+ ExecutionDescription="Assembling $(InputName).asm"
14+ ShowOnlyRuleProperties="false"
15+ >
16+ <Properties>
17+ </Properties>
18+ </CustomBuildRule>
19+ </Rules>
20+</VisualStudioToolFile>
build/arm-wince-vs8/armasmxscale.rules+20−0
@@ -0,0 +1,20 @@
1+<?xml version="1.0" encoding="utf-8"?>
2+<VisualStudioToolFile
3+ Name="armasm"
4+ Version="8.00"
5+ >
6+ <Rules>
7+ <CustomBuildRule
8+ Name="ARMASM"
9+ DisplayName="Armasm Assembler"
10+ CommandLine="armasm -o &quot;$(IntDir)\$(InputName).obj&quot; $(InputPath) -32 -cpu XSCALE&#x0D;&#x0A;"
11+ Outputs="$(IntDir)\$(InputName).obj"
12+ FileExtensions="*.asm"
13+ ExecutionDescription="Assembling $(InputName).asm"
14+ ShowOnlyRuleProperties="false"
15+ >
16+ <Properties>
17+ </Properties>
18+ </CustomBuildRule>
19+ </Rules>
20+</VisualStudioToolFile>
build/arm-wince-vs8/obj_int_extract.bat+12−0
@@ -0,0 +1,12 @@
1+@echo off
2+REM Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+REM
4+REM Use of this source code is governed by a BSD-style license and patent
5+REM grant that can be found in the LICENSE file in the root of the source
6+REM tree. All contributing project authors may be found in the AUTHORS
7+REM file in the root of the source tree.
8+echo on
9+
10+
11+cl /I ".\\" /I "..\vp6_decoder_sdk" /I "..\vp6_decoder_sdk\vpx_ports" /D "NDEBUG" /D "_WIN32_WCE=0x420" /D "UNDER_CE" /D "WIN32_PLATFORM_PSPC" /D "WINCE" /D "_LIB" /D "ARM" /D "_ARM_" /D "_UNICODE" /D "UNICODE" /D "HAVE_CONFIG_H" /FD /EHsc /MT /GS- /fp:fast /GR- /Fo"Pocket_PC_2003__ARMV4_\%1/" /Fd"Pocket_PC_2003__ARMV4_\%1/vc80.pdb" /W3 /nologo /c /TC ..\vp6_decoder_sdk\vp6_decoder\algo\common\arm\dec_asm_offsets_arm.c
12+obj_int_extract.exe rvds "Pocket_PC_2003__ARMV4_\%1/dec_asm_offsets_arm.obj"
build/arm-wince-vs8/vpx_decoder.sln+88−0
@@ -0,0 +1,88 @@
1+Microsoft Visual Studio Solution File, Format Version 9.00
2+# Visual Studio 2005
3+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "example", "example.vcproj", "{BA5FE66F-38DD-E034-F542-B1578C5FB950}"
4+ ProjectSection(ProjectDependencies) = postProject
5+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74} = {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}
6+ {E1360C65-D375-4335-8057-7ED99CC3F9B2} = {E1360C65-D375-4335-8057-7ED99CC3F9B2}
7+ EndProjectSection
8+EndProject
9+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "obj_int_extract", "obj_int_extract.vcproj", "{E1360C65-D375-4335-8057-7ED99CC3F9B2}"
10+EndProject
11+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vpx_decoder", "vpx_decoder.vcproj", "{DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}"
12+ ProjectSection(ProjectDependencies) = postProject
13+ {E1360C65-D375-4335-8057-7ED99CC3F9B2} = {E1360C65-D375-4335-8057-7ED99CC3F9B2}
14+ EndProjectSection
15+EndProject
16+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "xma", "xma.vcproj", "{A955FC4A-73F1-44F7-135E-30D84D32F022}"
17+ ProjectSection(ProjectDependencies) = postProject
18+ {E1360C65-D375-4335-8057-7ED99CC3F9B2} = {E1360C65-D375-4335-8057-7ED99CC3F9B2}
19+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74} = {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}
20+ EndProjectSection
21+EndProject
22+Global
23+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
24+ Debug|Mixed Platforms = Debug|Mixed Platforms
25+ Debug|Pocket PC 2003 (ARMV4) = Debug|Pocket PC 2003 (ARMV4)
26+ Debug|Win32 = Debug|Win32
27+ Release|Mixed Platforms = Release|Mixed Platforms
28+ Release|Pocket PC 2003 (ARMV4) = Release|Pocket PC 2003 (ARMV4)
29+ Release|Win32 = Release|Win32
30+ EndGlobalSection
31+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
32+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
33+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
34+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Mixed Platforms.Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
35+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
36+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
37+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
38+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Debug|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
39+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
40+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
41+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Mixed Platforms.Deploy.0 = Release|Pocket PC 2003 (ARMV4)
42+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
43+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
44+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
45+ {BA5FE66F-38DD-E034-F542-B1578C5FB950}.Release|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
46+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Debug|Mixed Platforms.ActiveCfg = Release|Win32
47+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Debug|Mixed Platforms.Build.0 = Release|Win32
48+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Win32
49+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Debug|Win32.ActiveCfg = Release|Win32
50+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Debug|Win32.Build.0 = Release|Win32
51+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Release|Mixed Platforms.ActiveCfg = Release|Win32
52+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Release|Mixed Platforms.Build.0 = Release|Win32
53+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Win32
54+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Release|Win32.ActiveCfg = Release|Win32
55+ {E1360C65-D375-4335-8057-7ED99CC3F9B2}.Release|Win32.Build.0 = Release|Win32
56+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
57+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
58+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Mixed Platforms.Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
59+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
60+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
61+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
62+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Debug|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
63+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
64+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
65+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Mixed Platforms.Deploy.0 = Release|Pocket PC 2003 (ARMV4)
66+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
67+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
68+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
69+ {DCE19DAF-69AC-46DB-B14A-39F0FAA5DB74}.Release|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
70+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Mixed Platforms.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
71+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Mixed Platforms.Build.0 = Debug|Pocket PC 2003 (ARMV4)
72+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Mixed Platforms.Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
73+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Pocket PC 2003 (ARMV4).ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
74+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Pocket PC 2003 (ARMV4).Build.0 = Debug|Pocket PC 2003 (ARMV4)
75+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Pocket PC 2003 (ARMV4).Deploy.0 = Debug|Pocket PC 2003 (ARMV4)
76+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Debug|Win32.ActiveCfg = Debug|Pocket PC 2003 (ARMV4)
77+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Mixed Platforms.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
78+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Mixed Platforms.Build.0 = Release|Pocket PC 2003 (ARMV4)
79+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Mixed Platforms.Deploy.0 = Release|Pocket PC 2003 (ARMV4)
80+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Pocket PC 2003 (ARMV4).ActiveCfg = Release|Pocket PC 2003 (ARMV4)
81+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Pocket PC 2003 (ARMV4).Build.0 = Release|Pocket PC 2003 (ARMV4)
82+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Pocket PC 2003 (ARMV4).Deploy.0 = Release|Pocket PC 2003 (ARMV4)
83+ {A955FC4A-73F1-44F7-135E-30D84D32F022}.Release|Win32.ActiveCfg = Release|Pocket PC 2003 (ARMV4)
84+ EndGlobalSection
85+ GlobalSection(SolutionProperties) = preSolution
86+ HideSolutionNode = FALSE
87+ EndGlobalSection
88+EndGlobal
build/make/Makefile+341−0
@@ -0,0 +1,341 @@
1+##
2+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+##
4+## Use of this source code is governed by a BSD-style license and patent
5+## grant that can be found in the LICENSE file in the root of the source
6+## tree. All contributing project authors may be found in the AUTHORS
7+## file in the root of the source tree.
8+##
9+
10+
11+include config.mk
12+quiet?=true
13+ifeq ($(target),)
14+# If a target wasn't specified, invoke for all enabled targets.
15+.DEFAULT:
16+ @for t in $(ALL_TARGETS); do \
17+ $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
18+ done
19+all: .DEFAULT
20+clean:: .DEFAULT
21+
22+
23+# Note: md5sum is not installed on OS X, but openssl is. Openssl may not be
24+# installed on cygwin, so we need to autodetect here.
25+md5sum := $(firstword $(wildcard \
26+ $(foreach e,md5sum openssl,\
27+ $(foreach p,$(subst :, ,$(PATH)),$(p)/$(e)*))\
28+ ))
29+md5sum := $(if $(filter %openssl,$(md5sum)),$(md5sum) dgst -md5,$(md5sum))
30+
31+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
32+install:
33+ @for t in $(ALL_TARGETS); do \
34+ $(MAKE) --no-print-directory target=$$t $(MAKECMDGOALS) || exit $$?;\
35+ done
36+ # Run configure for the user with the current toolchain.
37+ @if [ -d "$(DIST_DIR)/src" ]; then \
38+ mkdir -p "$(DIST_DIR)/build"; \
39+ cd "$(DIST_DIR)/build"; \
40+ if [ $(TGT_CC) = "rvct" ] ; then \
41+ echo "../src/configure --target=$(TOOLCHAIN) --libc=$(ALT_LIBC)"; \
42+ ../src/configure --target=$(TOOLCHAIN) --libc=$(ALT_LIBC); \
43+ else \
44+ echo "../src/configure --target=$(TOOLCHAIN)"; \
45+ ../src/configure --target=$(TOOLCHAIN); \
46+ fi; \
47+ $(if $(filter vs%,$(TGT_CC)),make NO_LAUNCH_DEVENV=1;) \
48+ fi
49+ @if [ -d "$(DIST_DIR)" ]; then \
50+ echo " [MD5SUM] $(DIST_DIR)"; \
51+ cd $(DIST_DIR) && \
52+ $(md5sum) `find . -name md5sums.txt -prune -o -type f -print` \
53+ | sed -e 's/MD5(\(.*\))= \([0-9a-f]\{32\}\)/\2 \1/' \
54+ > md5sums.txt;\
55+ fi
56+
57+
58+svnstat: ALL_TARGETS:=$(firstword $(ALL_TARGETS))
59+endif
60+
61+ifneq ($(target),)
62+# Normally, we want to build the filename from the target and the toolchain.
63+# This disambiguates from the $(target).mk file that exists in the source tree.
64+# However, the toolchain is part of the target in universal builds, so we
65+# don't want to include TOOLCHAIN in that case. FAT_ARCHS is used to test
66+# if we're in the universal case.
67+include $(target)$(if $(FAT_ARCHS),,-$(TOOLCHAIN)).mk
68+endif
69+BUILD_ROOT?=.
70+VPATH=$(SRC_PATH_BARE)
71+CFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
72+ASFLAGS+=-I$(BUILD_PFX)$(BUILD_ROOT) -I$(SRC_PATH)
73+DIST_DIR?=dist
74+HOSTCC?=gcc
75+TGT_ISA:=$(word 1, $(subst -, ,$(TOOLCHAIN)))
76+TGT_OS:=$(word 2, $(subst -, ,$(TOOLCHAIN)))
77+TGT_CC:=$(word 3, $(subst -, ,$(TOOLCHAIN)))
78+quiet:=$(if $(verbose),,yes)
79+qexec=$(if $(quiet),@)
80+
81+# Cancel built-in implicit rules
82+%: %.o
83+%.asm:
84+%.a:
85+
86+#
87+# Common rules"
88+#
89+.PHONY: all-$(target)
90+all-$(target):
91+
92+.PHONY: clean
93+clean::
94+ rm -f $(OBJS-yes) $(OBJS-yes:.o=.d) $(OBJS-yes:.asm.s.o=.asm.s)
95+ rm -f $(CLEAN-OBJS)
96+
97+.PHONY: install
98+install:
99+.PHONY: install-helper
100+install-helper:
101+
102+$(BUILD_PFX)%.c.d: %.c
103+ $(if $(quiet),@echo " [DEP] $@")
104+ $(qexec)mkdir -p $(dir $@)
105+ $(qexec)$(CC) $(CFLAGS) -M $< | $(fmt_deps) > $@
106+
107+$(BUILD_PFX)%.c.o: %.c
108+ $(if $(quiet),@echo " [CC] $@")
109+ $(qexec)$(CC) $(CFLAGS) -c -o $@ $<
110+
111+$(BUILD_PFX)%.asm.d: %.asm
112+ $(if $(quiet),@echo " [DEP] $@")
113+ $(qexec)mkdir -p $(dir $@)
114+ $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
115+ --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
116+
117+$(BUILD_PFX)%.asm.o: %.asm
118+ $(if $(quiet),@echo " [AS] $@")
119+ $(qexec)$(AS) $(ASFLAGS) -o $@ $<
120+
121+$(BUILD_PFX)%.s.d: %.s
122+ $(if $(quiet),@echo " [DEP] $@")
123+ $(qexec)mkdir -p $(dir $@)
124+ $(qexec)$(SRC_PATH_BARE)/build/make/gen_asm_deps.sh \
125+ --build-pfx=$(BUILD_PFX) --depfile=$@ $(ASFLAGS) $< > $@
126+
127+$(BUILD_PFX)%.s.o: %.s
128+ $(if $(quiet),@echo " [AS] $@")
129+ $(qexec)$(AS) $(ASFLAGS) -o $@ $<
130+
131+.PRECIOUS: %.asm.s
132+$(BUILD_PFX)%.asm.s: %.asm
133+ $(if $(quiet),@echo " [ASM CONVERSION] $@")
134+ $(qexec)mkdir -p $(dir $@)
135+ $(qexec)$(ASM_CONVERSION) <$< >$@
136+
137+# If we're in debug mode, pretend we don't have GNU strip, to fall back to
138+# the copy implementation
139+HAVE_GNU_STRIP := $(if $(CONFIG_DEBUG),,$(HAVE_GNU_STRIP))
140+ifeq ($(HAVE_GNU_STRIP),yes)
141+# Older binutils strip global sybols not needed for relocation processing
142+# when given --strip-unneeded. Use nm and awk to identify globals and
143+# keep them.
144+%.a: %_g.a
145+ $(if $(quiet),@echo " [STRIP] $@ < $<")
146+ $(qexec)$(STRIP) --strip-unneeded \
147+ `$(NM) $< | grep ' [A-TV-Z] ' | awk '{print "-K"$$3'}`\
148+ -o $@ $<
149+else
150+%.a: %_g.a
151+ $(if $(quiet),@echo " [CP] $@ < $<")
152+ $(qexec)cp $< $@
153+endif
154+
155+#
156+# Rule to extract assembly constants from C sources
157+#
158+obj_int_extract: build/make/obj_int_extract.c
159+ $(if $(quiet),echo " [HOSTCC] $@")
160+ $(qexec)$(HOSTCC) -I. -o $@ $<
161+CLEAN-OBJS += obj_int_extract
162+
163+#
164+# Utility functions
165+#
166+pairmap=$(if $(strip $(2)),\
167+ $(call $(1),$(word 1,$(2)),$(word 2,$(2)))\
168+ $(call pairmap,$(1),$(wordlist 3,$(words $(2)),$(2)))\
169+)
170+
171+enabled=$(filter-out $($(1)-no),$($(1)-yes))
172+cond_enabled=$(if $(filter yes,$($(1))), $(call enabled,$(2)))
173+
174+find_file1=$(word 1,$(wildcard $(subst //,/,$(addsuffix /$(1),$(2)))))
175+find_file=$(foreach f,$(1),$(call find_file1,$(strip $(f)),$(strip $(2))) )
176+obj_pats=.c=.c.o $(AS_SFX)=$(AS_SFX).o
177+objs=$(addprefix $(BUILD_PFX),$(foreach p,$(obj_pats),$(filter %.o,$(1:$(p))) ))
178+
179+install_map_templates=$(eval $(call install_map_template,$(1),$(2)))
180+
181+not=$(subst yes,no,$(1))
182+
183+ifeq ($(CONFIG_MSVS),yes)
184+lib_file_name=$(1).lib
185+else
186+lib_file_name=lib$(1).a
187+endif
188+#
189+# Rule Templates
190+#
191+define linker_template
192+$(1): $(filter-out -%,$(2))
193+$(1):
194+ $(if $(quiet),@echo " [LD] $$@")
195+ $(qexec)$$(LD) $$(strip $$(LDFLAGS) -o $$@ $(2) $(3) $$(extralibs))
196+endef
197+# make-3.80 has a bug with expanding large input strings to the eval function,
198+# which was triggered in some cases by the following component of
199+# linker_template:
200+# $(1): $$(call find_file, $(patsubst -l%,lib%.a,$(filter -l%,$(2))),\
201+# $$(patsubst -L%,%,$$(filter -L%,$$(LDFLAGS) $(2))))
202+# This may be useful to revisit in the future (it tries to locate libraries
203+# in a search path and add them as prerequisites
204+
205+define install_map_template
206+$(DIST_DIR)/$(1): $(2)
207+ $(if $(quiet),@echo " [INSTALL] $$@")
208+ $(qexec)mkdir -p $$(dir $$@)
209+ $(qexec)cp -p $$< $$@
210+endef
211+
212+define archive_template
213+# Not using a pattern rule here because we don't want to generate empty
214+# archives when they are listed as a dependency in files not responsible
215+# for creating them.
216+$(1):
217+ $(if $(quiet),@echo " [AR] $$@")
218+ $(qexec)$$(AR) $$(ARFLAGS) $$@ $$?
219+endef
220+
221+define lipo_lib_template
222+$(1): $(addsuffix /$(1),$(FAT_ARCHS))
223+ $(if $(quiet),@echo " [LIPO] $$@")
224+ $(qexec)libtool -static -o $$@ $$?
225+endef
226+
227+define lipo_bin_template
228+$(1): $(addsuffix /$(1),$(FAT_ARCHS))
229+ $(if $(quiet),@echo " [LIPO] $$@")
230+ $(qexec)lipo -output $$@ -create $$?
231+endef
232+
233+
234+#
235+# Get current configuration
236+#
237+ifneq ($(target),)
238+include $(SRC_PATH_BARE)/$(target:-$(TOOLCHAIN)=).mk
239+endif
240+ifeq ($(filter clean,$(MAKECMDGOALS)),)
241+ # Older versions of make don't like -include directives with no arguments
242+ ifneq ($(filter %.d,$(OBJS-yes:.o=.d)),)
243+ -include $(filter %.d,$(OBJS-yes:.o=.d))
244+ endif
245+endif
246+
247+#
248+# Configuration dependant rules
249+#
250+$(call pairmap,install_map_templates,$(INSTALL_MAPS))
251+
252+DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,DOCS)
253+.docs: $(DOCS)
254+ @touch $@
255+
256+INSTALL-DOCS=$(call cond_enabled,CONFIG_INSTALL_DOCS,INSTALL-DOCS)
257+.install-docs: .docs $(addprefix $(DIST_DIR)/,$(INSTALL-DOCS))
258+ @touch $@
259+
260+clean::
261+ rm -f .docs .install-docs $(DOCS)
262+
263+BINS=$(call enabled,BINS)
264+.bins: $(BINS)
265+ @touch $@
266+
267+INSTALL-BINS=$(call cond_enabled,CONFIG_INSTALL_BINS,INSTALL-BINS)
268+.install-bins: .bins $(addprefix $(DIST_DIR)/,$(INSTALL-BINS))
269+ @touch $@
270+
271+clean::
272+ rm -f .bins .install-bins $(BINS)
273+
274+LIBS=$(call enabled,LIBS)
275+.libs: $(LIBS)
276+ @touch $@
277+$(foreach lib,$(filter %_g.a,$(LIBS)),$(eval $(call archive_template,$(lib))))
278+
279+INSTALL-LIBS=$(call cond_enabled,CONFIG_INSTALL_LIBS,INSTALL-LIBS)
280+.install-libs: .libs $(addprefix $(DIST_DIR)/,$(INSTALL-LIBS))
281+ @touch $@
282+
283+clean::
284+ rm -f .libs .install-libs $(LIBS)
285+
286+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
287+PROJECTS=$(call enabled,PROJECTS)
288+.projects: $(PROJECTS)
289+ @touch $@
290+
291+INSTALL-PROJECTS=$(call cond_enabled,CONFIG_INSTALL_PROJECTS,INSTALL-PROJECTS)
292+.install-projects: .projects $(addprefix $(DIST_DIR)/,$(INSTALL-PROJECTS))
293+ @touch $@
294+
295+clean::
296+ rm -f .projects .install-projects $(PROJECTS)
297+endif
298+
299+# If there are any source files to be installed, then include the build
300+# system too.
301+ifneq ($(call enabled,INSTALL-SRCS),)
302+ INSTALL-SRCS-yes += configure
303+ INSTALL-SRCS-yes += build/make/configure.sh
304+ INSTALL-SRCS-yes += build/make/gen_asm_deps.sh
305+ INSTALL-SRCS-yes += build/make/Makefile
306+ INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
307+ INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
308+ INSTALL-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
309+ INSTALL-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
310+ #
311+ # This isn't really ARCH_ARM dependent, it's dependant on whether we're
312+ # using assembly code or not (CONFIG_OPTIMIZATIONS maybe). Just use
313+ # this for now.
314+ INSTALL-SRCS-$(ARCH_ARM) += build/make/obj_int_extract.c
315+ INSTALL-SRCS-$(ARCH_ARM) += build/make/ads2gas.pl
316+ INSTALL-SRCS-yes += $(target:-$(TOOLCHAIN)=).mk
317+endif
318+INSTALL-SRCS := $(call cond_enabled,CONFIG_INSTALL_SRCS,INSTALL-SRCS)
319+.install-srcs: $(addprefix $(DIST_DIR)/src/,$(INSTALL-SRCS))
320+ @touch $@
321+
322+clean::
323+ rm -f .install-srcs
324+
325+ifeq ($(CONFIG_EXTERNAL_BUILD),yes)
326+ BUILD_TARGETS += .projects
327+ INSTALL_TARGETS += .install-projects
328+endif
329+BUILD_TARGETS += .docs .libs .bins
330+INSTALL_TARGETS += .install-docs .install-srcs .install-libs .install-bins
331+all-$(target): $(BUILD_TARGETS)
332+install: $(INSTALL_TARGETS)
333+
334+#
335+# Development helper targets
336+#
337+ifneq ($(SRC_PATH_BARE),)
338+.PHONY: svnstat
339+svnstat:
340+ svn stat $(SRC_PATH_BARE)
341+endif
build/make/ads2gas.pl+149−0
@@ -0,0 +1,149 @@
1+#!/usr/bin/perl
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+# ads2gas.pl
13+# Author: Eric Fung (efung (at) acm.org)
14+#
15+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
16+#
17+# Usage: cat inputfile | perl ads2gas.pl > outputfile
18+#
19+print "@ This file was created from a .asm file\n";
20+print "@ using the ads2gas.pl script.\n";
21+print "\t.equ DO1STROUNDING, 0\n";
22+
23+while (<STDIN>)
24+{
25+ # Comment character
26+ s/;/@/g;
27+
28+ # Hexadecimal constants prefaced by 0x
29+ s/#&/#0x/g;
30+
31+ # Convert :OR: to |
32+ s/:OR:/ | /g;
33+
34+ # Convert :AND: to &
35+ s/:AND:/ & /g;
36+
37+ # Convert :NOT: to ~
38+ s/:NOT:/ ~ /g;
39+
40+ # Convert :SHL: to <<
41+ s/:SHL:/ << /g;
42+
43+ # Convert :SHR: to >>
44+ s/:SHR:/ >> /g;
45+
46+ # Convert ELSE to .else
47+ s/ELSE/.else/g;
48+
49+ # Convert ENDIF to .endif
50+ s/ENDIF/.endif/g;
51+
52+ # Convert ELSEIF to .elseif
53+ s/ELSEIF/.elseif/g;
54+
55+ # Convert LTORG to .ltorg
56+ s/LTORG/.ltorg/g;
57+
58+ # Convert IF :DEF:to .if
59+ # gcc doesn't have the ability to do a conditional
60+ # if defined variable that is set by IF :DEF: on
61+ # armasm, so convert it to a normal .if and then
62+ # make sure to define a value elesewhere
63+ if (s/\bIF :DEF:\b/.if /g)
64+ {
65+ s/=/==/g;
66+ }
67+
68+ # Convert IF to .if
69+ if (s/\bIF\b/.if/g)
70+ {
71+ s/=+/==/g;
72+ }
73+
74+ # Convert INCLUDE to .INCLUDE "file"
75+ s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
76+
77+ # Code directive (ARM vs Thumb)
78+ s/CODE([0-9][0-9])/.code $1/;
79+
80+ # No AREA required
81+ s/^\s*AREA.*$/.text/;
82+
83+ # DCD to .word
84+ # This one is for incoming symbols
85+ s/DCD\s+\|(\w*)\|/.long $1/;
86+
87+ # DCW to .short
88+ s/DCW\s+\|(\w*)\|/.short $1/;
89+ s/DCW(.*)/.short $1/;
90+
91+ # Constants defined in scope
92+ s/DCD(.*)/.long $1/;
93+ s/DCB(.*)/.byte $1/;
94+
95+ # RN to .req
96+ if (s/RN\s+([Rr]\d+|lr)/.req $1/)
97+ {
98+ print;
99+ next;
100+ }
101+
102+ # Make function visible to linker, and make additional symbol with
103+ # prepended underscore
104+ s/EXPORT\s+\|([\$\w]*)\|/.global $1 \n\t.type $1, function/;
105+ s/IMPORT\s+\|([\$\w]*)\|/.global $1/;
106+
107+ # No vertical bars required; make additional symbol with prepended
108+ # underscore
109+ s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
110+
111+ # Labels need trailing colon
112+# s/^(\w+)/$1:/ if !/EQU/;
113+ # put the colon at the end of the line in the macro
114+ s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
115+
116+ # Strip ALIGN
117+ s/\sALIGN/@ ALIGN/g;
118+
119+ # Strip ARM
120+ s/\sARM/@ ARM/g;
121+
122+ # Strip REQUIRE8
123+ #s/\sREQUIRE8/@ REQUIRE8/g;
124+ s/\sREQUIRE8/@ /g; #EQU cause problem
125+
126+ # Strip PRESERVE8
127+ s/\sPRESERVE8/@ PRESERVE8/g;
128+
129+ # Strip PROC and ENDPROC
130+ s/\sPROC/@/g;
131+ s/\sENDP/@/g;
132+
133+ # EQU directive
134+ s/(.*)EQU(.*)/.equ $1, $2/;
135+
136+ # Begin macro definition
137+ if (/MACRO/) {
138+ $_ = <STDIN>;
139+ s/^/.macro/;
140+ s/\$//g; # remove formal param reference
141+ s/;/@/g; # change comment characters
142+ }
143+
144+ # For macros, use \ to reference formal params
145+ s/\$/\\/g; # End macro definition
146+ s/MEND/.endm/; # No need to tell it where to stop assembling
147+ next if /^\s*END\s*$/;
148+ print;
149+}
build/make/ads2gas_apple.pl+194−0
@@ -0,0 +1,194 @@
1+#!/usr/bin/env perl
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+# ads2gas.pl
13+# Author: Eric Fung (efung (at) acm.org)
14+#
15+# Convert ARM Developer Suite 1.0.1 syntax assembly source to GNU as format
16+#
17+# Usage: cat inputfile | perl ads2gas.pl > outputfile
18+#
19+print "@ This file was created from a .asm file\n";
20+print "@ using the ads2gas_apple.pl script.\n\n";
21+print "\t.set WIDE_REFERENCE, 0\n";
22+print "\t.set ARCHITECTURE, 5\n";
23+print "\t.set DO1STROUNDING, 0\n";
24+
25+my %register_aliases;
26+my %macro_aliases;
27+
28+my @mapping_list = ("\$0", "\$1", "\$2", "\$3", "\$4", "\$5", "\$6", "\$7", "\$8", "\$9");
29+
30+my @incoming_array;
31+
32+# Perl trim function to remove whitespace from the start and end of the string
33+sub trim($)
34+{
35+ my $string = shift;
36+ $string =~ s/^\s+//;
37+ $string =~ s/\s+$//;
38+ return $string;
39+}
40+
41+while (<STDIN>)
42+{
43+ # Comment character
44+ s/;/@/g;
45+
46+ # Hexadecimal constants prefaced by 0x
47+ s/#&/#0x/g;
48+
49+ # Convert :OR: to |
50+ s/:OR:/ | /g;
51+
52+ # Convert :AND: to &
53+ s/:AND:/ & /g;
54+
55+ # Convert :NOT: to ~
56+ s/:NOT:/ ~ /g;
57+
58+ # Convert :SHL: to <<
59+ s/:SHL:/ << /g;
60+
61+ # Convert :SHR: to >>
62+ s/:SHR:/ >> /g;
63+
64+ # Convert ELSE to .else
65+ s/ELSE/.else/g;
66+
67+ # Convert ENDIF to .endif
68+ s/ENDIF/.endif/g;
69+
70+ # Convert ELSEIF to .elseif
71+ s/ELSEIF/.elseif/g;
72+
73+ # Convert LTORG to .ltorg
74+ s/LTORG/.ltorg/g;
75+
76+ # Convert IF :DEF:to .if
77+ # gcc doesn't have the ability to do a conditional
78+ # if defined variable that is set by IF :DEF: on
79+ # armasm, so convert it to a normal .if and then
80+ # make sure to define a value elesewhere
81+ if (s/\bIF :DEF:\b/.if /g)
82+ {
83+ s/=/==/g;
84+ }
85+
86+ # Convert IF to .if
87+ if (s/\bIF\b/.if/g)
88+ {
89+ s/=/==/g;
90+ }
91+
92+ # Convert INCLUDE to .INCLUDE "file"
93+ s/INCLUDE(\s*)(.*)$/.include $1\"$2\"/;
94+
95+ # Code directive (ARM vs Thumb)
96+ s/CODE([0-9][0-9])/.code $1/;
97+
98+ # No AREA required
99+ s/^\s*AREA.*$/.text/;
100+
101+ # DCD to .word
102+ # This one is for incoming symbols
103+ s/DCD\s+\|(\w*)\|/.long $1/;
104+
105+ # DCW to .short
106+ s/DCW\s+\|(\w*)\|/.short $1/;
107+ s/DCW(.*)/.short $1/;
108+
109+ # Constants defined in scope
110+ s/DCD(.*)/.long $1/;
111+ s/DCB(.*)/.byte $1/;
112+
113+ # Build a hash of all the register - alias pairs.
114+ if (s/(.*)RN(.*)/$1 .req $2/g)
115+ {
116+ $register_aliases{trim($1)} = trim($2);
117+ next;
118+ }
119+
120+ while (($key, $value) = each(%register_aliases))
121+ {
122+ s/\b$key\b/$value/g;
123+ }
124+
125+ # Make function visible to linker, and make additional symbol with
126+ # prepended underscore
127+ s/EXPORT\s+\|([\$\w]*)\|/.globl _$1\n\t.globl $1/;
128+ s/IMPORT\s+\|([\$\w]*)\|/.globl $1/;
129+
130+ # No vertical bars required; make additional symbol with prepended
131+ # underscore
132+ s/^\|(\$?\w+)\|/_$1\n\t$1:/g;
133+
134+ # Labels need trailing colon
135+# s/^(\w+)/$1:/ if !/EQU/;
136+ # put the colon at the end of the line in the macro
137+ s/^([a-zA-Z_0-9\$]+)/$1:/ if !/EQU/;
138+
139+ # Strip ALIGN
140+ s/\sALIGN/@ ALIGN/g;
141+
142+ # Strip ARM
143+ s/\sARM/@ ARM/g;
144+
145+ # Strip REQUIRE8
146+ #s/\sREQUIRE8/@ REQUIRE8/g;
147+ s/\sREQUIRE8/@ /g;
148+
149+ # Strip PRESERVE8
150+ s/\sPRESERVE8/@ PRESERVE8/g;
151+
152+ # Strip PROC and ENDPROC
153+ s/PROC/@/g;
154+ s/ENDP/@/g;
155+
156+ # EQU directive
157+ s/(.*)EQU(.*)/.set $1, $2/;
158+
159+ # Begin macro definition
160+ if (/MACRO/)
161+ {
162+ # Process next line down, which will be the macro definition
163+ $_ = <STDIN>;
164+
165+ $trimmed = trim($_);
166+
167+ # remove commas that are separating list
168+ $trimmed =~ s/,//g;
169+
170+ # string to array
171+ @incoming_array = split(/ /, $trimmed);
172+
173+ print ".macro @incoming_array[0]\n";
174+
175+ # remove the first element, as that is the name of the macro
176+ shift (@incoming_array);
177+
178+ @macro_aliases{@incoming_array} = @mapping_list;
179+
180+ next;
181+ }
182+
183+ while (($key, $value) = each(%macro_aliases))
184+ {
185+ $key =~ s/\$/\\\$/;
186+ s/$key\b/$value/g;
187+ }
188+
189+ # For macros, use \ to reference formal params
190+# s/\$/\\/g; # End macro definition
191+ s/MEND/.endm/; # No need to tell it where to stop assembling
192+ next if /^\s*END\s*$/;
193+ print;
194+}
build/make/armlink_adapter.sh+51−0
@@ -0,0 +1,51 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+verbose=0
13+set -- $*
14+for i; do
15+ if [ "$i" == "-o" ]; then
16+ on_of=1
17+ elif [ "$i" == "-v" ]; then
18+ verbose=1
19+ elif [ "$on_of" == "1" ]; then
20+ outfile=$i
21+ on_of=0
22+ elif [ -f "$i" ]; then
23+ infiles="$infiles $i"
24+ elif [ "${i:0:2}" == "-l" ]; then
25+ libs="$libs ${i#-l}"
26+ elif [ "${i:0:2}" == "-L" ]; then
27+ libpaths="${libpaths} ${i#-L}"
28+ else
29+ args="${args} ${i}"
30+ fi
31+ shift
32+done
33+
34+# Absolutize library file names
35+for f in $libs; do
36+ found=0
37+ for d in $libpaths; do
38+ [ -f "$d/$f" ] && infiles="$infiles $d/$f" && found=1 && break
39+ [ -f "$d/lib${f}.so" ] && infiles="$infiles $d/lib${f}.so" && found=1 && break
40+ [ -f "$d/lib${f}.a" ] && infiles="$infiles $d/lib${f}.a" && found=1 && break
41+ done
42+ [ $found -eq 0 ] && infiles="$infiles $f"
43+done
44+for d in $libpaths; do
45+ [ -n "$libsearchpath" ] && libsearchpath="${libsearchpath},"
46+ libsearchpath="${libsearchpath}$d"
47+done
48+
49+cmd="armlink $args --userlibpath=$libsearchpath --output=$outfile $infiles"
50+[ $verbose -eq 1 ] && echo $cmd
51+$cmd
build/make/configure.sh+907−0
@@ -0,0 +1,907 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+
13+#
14+# Logging / Output Functions
15+#
16+die_unknown(){
17+ echo "Unknown option \"$1\"."
18+ echo "See $0 --help for available options."
19+ clean_temp_files
20+ exit 1
21+}
22+
23+
24+die() {
25+ echo "$@"
26+ echo
27+ echo "Configuration failed. This could reflect a misconfiguration of your"
28+ echo "toolchains, improper options selected, or another problem. If you"
29+ echo "don't see any useful error messages above, the next step is to look"
30+ echo "at the configure error log file ($logfile) to determine what"
31+ echo "configure was trying to do when it died."
32+ clean_temp_files
33+ exit 1
34+}
35+
36+
37+log(){
38+ echo "$@" >>$logfile
39+}
40+
41+
42+log_file(){
43+ log BEGIN $1
44+ pr -n -t $1 >>$logfile
45+ log END $1
46+}
47+
48+
49+log_echo() {
50+ echo "$@"
51+ log "$@"
52+}
53+
54+
55+fwrite () {
56+ outfile=$1
57+ shift
58+ echo "$@" >> ${outfile}
59+}
60+
61+
62+show_help_pre(){
63+ for opt in ${CMDLINE_SELECT}; do
64+ opt2=`echo $opt | sed -e 's;_;-;g'`
65+ if enabled $opt; then
66+ eval "toggle_${opt}=\"--disable-${opt2}\""
67+ else
68+ eval "toggle_${opt}=\"--enable-${opt2} \""
69+ fi
70+ done
71+
72+ cat <<EOF
73+Usage: configure [options]
74+Options:
75+
76+Build options:
77+ --help print this message
78+ --log=yes|no|FILE file configure log is written to [config.err]
79+ --target=TARGET target platform tuple [generic-gnu]
80+ --cpu=CPU optimize for a specific cpu rather than a family
81+ ${toggle_extra_warnings} emit harmless warnings (always non-fatal)
82+ ${toggle_werror} treat warnings as errors, if possible
83+ (not available with all compilers)
84+ ${toggle_optimizations} turn on/off compiler optimization flags
85+ ${toggle_pic} turn on/off Position Independant Code
86+ ${toggle_ccache} turn on/off compiler cache
87+ ${toggle_debug} enable/disable debug mode
88+ ${toggle_gprof} enable/disable gprof profiling instrumentation
89+ ${toggle_gcov} enable/disable gcov coverage instrumentation
90+
91+Install options:
92+ ${toggle_install_docs} control whether docs are installed
93+ ${toggle_install_bins} control whether binaries are installed
94+ ${toggle_install_libs} control whether libraries are installed
95+ ${toggle_install_srcs} control whether sources are installed
96+
97+
98+EOF
99+}
100+
101+
102+show_help_post(){
103+ cat <<EOF
104+
105+
106+NOTES:
107+ Object files are built at the place where configure is launched.
108+
109+ All boolean options can be negated. The default value is the opposite
110+ of that shown above. If the option --disable-foo is listed, then
111+ the default value for foo is enabled.
112+
113+Supported targets:
114+EOF
115+ show_targets ${all_platforms}
116+ echo
117+ exit 1
118+}
119+
120+
121+show_targets() {
122+ while [ -n "$*" ]; do
123+ if [ "${1%%-*}" == "${2%%-*}" ]; then
124+ if [ "${2%%-*}" == "${3%%-*}" ]; then
125+ printf " %-24s %-24s %-24s\n" "$1" "$2" "$3"
126+ shift; shift; shift
127+ else
128+ printf " %-24s %-24s\n" "$1" "$2"
129+ shift; shift
130+ fi
131+ else
132+ printf " %-24s\n" "$1"
133+ shift
134+ fi
135+ done
136+}
137+
138+
139+show_help() {
140+ show_help_pre
141+ show_help_post
142+}
143+
144+#
145+# List Processing Functions
146+#
147+set_all(){
148+ value=$1
149+ shift
150+ for var in $*; do
151+ eval $var=$value
152+ done
153+}
154+
155+
156+is_in(){
157+ value=$1
158+ shift
159+ for var in $*; do
160+ [ $var = $value ] && return 0
161+ done
162+ return 1
163+}
164+
165+
166+add_cflags() {
167+ CFLAGS="${CFLAGS} $@"
168+}
169+
170+
171+add_ldflags() {
172+ LDFLAGS="${LDFLAGS} $@"
173+}
174+
175+
176+add_asflags() {
177+ ASFLAGS="${ASFLAGS} $@"
178+}
179+
180+
181+add_extralibs() {
182+ extralibs="${extralibs} $@"
183+}
184+
185+#
186+# Boolean Manipulation Functions
187+#
188+enable(){
189+ set_all yes $*
190+}
191+
192+disable(){
193+ set_all no $*
194+}
195+
196+enabled(){
197+ eval test "x\$$1" = "xyes"
198+}
199+
200+disabled(){
201+ eval test "x\$$1" = "xno"
202+}
203+
204+
205+soft_enable() {
206+ for var in $*; do
207+ if ! disabled $var; then
208+ log_echo " enabling $var"
209+ enable $var
210+ fi
211+ done
212+}
213+
214+soft_disable() {
215+ for var in $*; do
216+ if ! enabled $var; then
217+ log_echo " disabling $var"
218+ disable $var
219+ fi
220+ done
221+}
222+
223+
224+#
225+# Text Processing Functions
226+#
227+toupper(){
228+ echo "$@" | tr abcdefghijklmnopqrstuvwxyz ABCDEFGHIJKLMNOPQRSTUVWXYZ
229+}
230+
231+
232+tolower(){
233+ echo "$@" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz
234+}
235+
236+
237+#
238+# Temporary File Functions
239+#
240+source_path=${0%/*}
241+enable source_path_used
242+if test -z "$source_path" -o "$source_path" = "." ; then
243+ source_path="`pwd`"
244+ disable source_path_used
245+fi
246+
247+if test ! -z "$TMPDIR" ; then
248+ TMPDIRx="${TMPDIR}"
249+elif test ! -z "$TEMPDIR" ; then
250+ TMPDIRx="${TEMPDIR}"
251+else
252+ TMPDIRx="/tmp"
253+fi
254+TMP_H="${TMPDIRx}/vpx-conf-$$-${RANDOM}.h"
255+TMP_C="${TMPDIRx}/vpx-conf-$$-${RANDOM}.c"
256+TMP_O="${TMPDIRx}/vpx-conf-$$-${RANDOM}.o"
257+TMP_X="${TMPDIRx}/vpx-conf-$$-${RANDOM}.x"
258+
259+clean_temp_files() {
260+ rm -f ${TMP_C} ${TMP_H} ${TMP_O} ${TMP_X}
261+}
262+
263+#
264+# Toolchain Check Functions
265+#
266+check_cmd() {
267+ log "$@"
268+ "$@" >>${logfile} 2>&1
269+}
270+
271+check_cc() {
272+ log check_cc "$@"
273+ cat >${TMP_C}
274+ log_file ${TMP_C}
275+ check_cmd ${CC} ${CFLAGS} "$@" -c -o ${TMP_O} ${TMP_C}
276+}
277+
278+check_cpp() {
279+ log check_cpp "$@"
280+ cat > ${TMP_C}
281+ log_file ${TMP_C}
282+ check_cmd ${CC} ${CFLAGS} "$@" -E -o ${TMP_O} ${TMP_C}
283+}
284+
285+check_ld() {
286+ log check_ld "$@"
287+ check_cc $@ \
288+ && check_cmd ${LD} ${LDFLAGS} "$@" -o ${TMP_X} ${TMP_O} ${extralibs}
289+}
290+
291+check_header(){
292+ log check_header "$@"
293+ header=$1
294+ shift
295+ var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
296+ disable $var
297+ check_cpp "$@" <<EOF && enable $var
298+#include "$header"
299+int x;
300+EOF
301+}
302+
303+
304+check_cflags() {
305+ log check_cflags "$@"
306+ check_cc "$@" <<EOF
307+int x;
308+EOF
309+}
310+
311+check_add_cflags() {
312+ check_cflags "$@" && add_cflags "$@"
313+}
314+
315+check_add_asflags() {
316+ log add_asflags "$@"
317+ add_asflags "$@"
318+}
319+
320+check_add_ldflags() {
321+ log add_ldflags "$@"
322+ add_ldflags "$@"
323+}
324+
325+write_common_config_banner() {
326+ echo '# This file automatically generated by configure. Do not edit!' > config.mk
327+ echo "TOOLCHAIN := ${toolchain}" >> config.mk
328+
329+ case ${toolchain} in
330+ *-linux-rvct)
331+ echo "ALT_LIBC := ${alt_libc}" >> config.mk
332+ ;;
333+ esac
334+}
335+
336+write_common_config_targets() {
337+ for t in ${all_targets}; do
338+ if enabled ${t}; then
339+ if enabled universal || enabled child; then
340+ fwrite config.mk "ALL_TARGETS += ${t}-${toolchain}"
341+ else
342+ fwrite config.mk "ALL_TARGETS += ${t}"
343+ fi
344+ fi
345+ true;
346+ done
347+true
348+}
349+
350+write_common_target_config_mk() {
351+ [ -n "$2" ] && local have_config_h="-DHAVE_CONFIG_H=\"${2##*/}\""
352+ local CC=${CC}
353+ enabled ccache && CC="ccache ${CC}"
354+
355+ cat > $1 << EOF
356+# This file automatically generated by configure. Do not edit!
357+SRC_PATH="$source_path"
358+SRC_PATH_BARE=$source_path
359+BUILD_PFX=${BUILD_PFX}
360+TOOLCHAIN=${toolchain}
361+ASM_CONVERSION=${asm_conversion_cmd:-${source_path}/build/make/ads2gas.pl}
362+
363+CC=${CC}
364+AR=${AR}
365+LD=${LD}
366+AS=${AS}
367+STRIP=${STRIP}
368+NM=${NM}
369+
370+CFLAGS = ${CFLAGS} ${have_config_h}
371+ARFLAGS = -rus\$(if \$(quiet),c,v)
372+LDFLAGS = ${LDFLAGS}
373+ASFLAGS = ${ASFLAGS}
374+extralibs = ${extralibs}
375+AS_SFX = ${AS_SFX:-.asm}
376+EOF
377+
378+ if enabled rvct; then cat >> $1 << EOF
379+fmt_deps = sed -e 's;^__image.axf;\$(dir \$@)\$(notdir \$<).o \$@;' #hide
380+EOF
381+ else cat >> $1 << EOF
382+fmt_deps = sed -e 's;^\(.*\)\.o;\$(dir \$@)\1\$(suffix \$<).o \$@;' #hide
383+EOF
384+ fi
385+
386+ print_config_mk ARCH "${1}" ${ARCH_LIST}
387+ print_config_mk HAVE "${1}" ${HAVE_LIST}
388+ print_config_mk CONFIG "${1}" ${CONFIG_LIST}
389+ print_config_mk HAVE "${1}" gnu_strip
390+
391+ enabled msvs && echo "CONFIG_VS_VERSION=${vs_version}" >> "${1}"
392+
393+}
394+
395+
396+write_common_target_config_h() {
397+ cat > ${TMP_H} << EOF
398+/* This file automatically generated by configure. Do not edit! */
399+#define INLINE ${INLINE}
400+#define FORCEINLINE ${FORCEINLINE:-${INLINE}}
401+#define RESTRICT ${RESTRICT}
402+EOF
403+ print_config_h ARCH "${TMP_H}" ${ARCH_LIST}
404+ print_config_h HAVE "${TMP_H}" ${HAVE_LIST}
405+ print_config_h CONFIG "${TMP_H}" ${CONFIG_LIST}
406+ mkdir -p `dirname "$1"`
407+ cmp "$1" ${TMP_H} >/dev/null 2>&1 || mv ${TMP_H} "$1"
408+}
409+
410+process_common_cmdline() {
411+ for opt in "$@"; do
412+ optval="${opt#*=}"
413+ case "$opt" in
414+ --child) enable child
415+ ;;
416+ --log*)
417+ logging="$optval"
418+ if ! disabled logging ; then
419+ enabled logging || logfile="$logging"
420+ else
421+ logfile=/dev/null
422+ fi
423+ ;;
424+ --target=*) toolchain="${toolchain:-${optval}}"
425+ ;;
426+ --force-target=*) toolchain="${toolchain:-${optval}}"; enable force_toolchain
427+ ;;
428+ --cpu)
429+ ;;
430+ --cpu=*) tune_cpu="$optval"
431+ ;;
432+ --enable-?*|--disable-?*)
433+ eval `echo "$opt" | sed 's/--/action=/;s/-/ option=/;s/-/_/g'`
434+ echo "${CMDLINE_SELECT} ${ARCH_EXT_LIST}" | grep "^ *$option\$" >/dev/null || die_unknown $opt
435+ $action $option
436+ ;;
437+ --force-enable-?*|--force-disable-?*)
438+ eval `echo "$opt" | sed 's/--force-/action=/;s/-/ option=/;s/-/_/g'`
439+ $action $option
440+ ;;
441+ --libc=*)
442+ [ -d "${optval}" ] || die "Not a directory: ${optval}"
443+ disable builtin_libc
444+ alt_libc="${optval}"
445+ ;;
446+ --libc)
447+ die "Option ${opt} requires argument"
448+ ;;
449+ --help|-h) show_help
450+ ;;
451+ *) die_unknown $opt
452+ ;;
453+ esac
454+ done
455+}
456+
457+process_cmdline() {
458+ for opt do
459+ optval="${opt#*=}"
460+ case "$opt" in
461+ *) process_common_cmdline $opt
462+ ;;
463+ esac
464+ done
465+}
466+
467+post_process_cmdline() {
468+ true;
469+}
470+
471+setup_gnu_toolchain() {
472+ CC=${CC:-${CROSS}gcc}
473+ AR=${AR:-${CROSS}ar}
474+ LD=${LD:-${CROSS}${link_with_cc:-ld}}
475+ AS=${AS:-${CROSS}as}
476+ STRIP=${STRIP:-${CROSS}strip}
477+ NM=${NM:-${CROSS}nm}
478+ AS_SFX=.s
479+}
480+
481+process_common_toolchain() {
482+ toolchain=${toolchain:-generic-gnu}
483+
484+ is_in ${toolchain} ${all_platforms} || enabled force_toolchain \
485+ || die "Unrecognized toolchain '${toolchain}'"
486+
487+ enabled child || log_echo "Configuring for target '${toolchain}'"
488+
489+ #
490+ # Set up toolchain variables
491+ #
492+ tgt_isa=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $1}')
493+ tgt_os=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $2}')
494+ tgt_cc=$(echo ${toolchain} | awk 'BEGIN{FS="-"}{print $3}')
495+
496+ # Mark the specific ISA requested as enabled
497+ soft_enable ${tgt_isa}
498+ enable ${tgt_os}
499+ enable ${tgt_cc}
500+
501+ # Enable the architecture family
502+ case ${tgt_isa} in
503+ arm*|iwmmxt*) enable arm;;
504+ mips*) enable mips;;
505+ esac
506+
507+ # Handle darwin variants
508+ case ${toolchain} in
509+ *-darwin8-gcc)
510+ add_cflags "-isysroot /Developer/SDKs/MacOSX10.4u.sdk"
511+ add_cflags "-mmacosx-version-min=10.4"
512+ add_ldflags "-isysroot /Developer/SDKs/MacOSX10.4u.sdk"
513+ add_ldflags "-mmacosx-version-min=10.4"
514+ ;;
515+ *-darwin9-gcc)
516+ add_cflags "-isysroot /Developer/SDKs/MacOSX10.5.sdk"
517+ add_cflags "-mmacosx-version-min=10.5"
518+ add_ldflags "-isysroot /Developer/SDKs/MacOSX10.5.sdk"
519+ add_ldflags "-mmacosx-version-min=10.5"
520+ ;;
521+ esac
522+
523+ # Process ARM architecture variants
524+ case ${toolchain} in
525+ arm*|iwmmxt*)
526+ # on arm, isa versions are supersets
527+ enabled armv7a && soft_enable armv7 ### DEBUG
528+ enabled armv7 && soft_enable armv6
529+ enabled armv6 && soft_enable armv5te
530+ enabled armv6 && soft_enable fast_unaligned
531+ enabled iwmmxt2 && soft_enable iwmmxt
532+ enabled iwmmxt && soft_enable armv5te
533+
534+ asm_conversion_cmd="cat"
535+
536+ case ${tgt_cc} in
537+ gcc)
538+ if enabled iwmmxt || enabled iwmmxt2
539+ then
540+ CROSS=${CROSS:-arm-iwmmxt-linux-gnueabi-}
541+ elif enabled symbian; then
542+ CROSS=${CROSS:-arm-none-symbianelf-}
543+ else
544+ CROSS=${CROSS:-arm-none-linux-gnueabi-}
545+ fi
546+ link_with_cc=gcc
547+ setup_gnu_toolchain
548+ arch_int=${tgt_isa##armv}
549+ arch_int=${arch_int%%te}
550+ check_add_asflags --defsym ARCHITECTURE=${arch_int}
551+ tune_cflags="-mtune="
552+ if enabled iwmmxt || enabled iwmmxt2
553+ then
554+ check_add_asflags -mcpu=${tgt_isa}
555+ elif enabled armv7
556+ then
557+ check_add_cflags -march=armv7-a -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp #-ftree-vectorize
558+ check_add_asflags -mcpu=cortex-a8 -mfpu=neon -mfloat-abi=softfp #-march=armv7-a
559+ else
560+ check_add_cflags -march=${tgt_isa}
561+ check_add_asflags -march=${tgt_isa}
562+ fi
563+
564+ asm_conversion_cmd="${source_path}/build/make/ads2gas.pl"
565+ ;;
566+ rvct)
567+ CC=armcc
568+ AR=armar
569+ AS=armasm
570+ LD=${source_path}/build/make/armlink_adapter.sh
571+ STRIP=arm-none-linux-gnueabi-strip
572+ NM=arm-none-linux-gnueabi-nm
573+ tune_cflags="--cpu="
574+ tune_asflags="--cpu="
575+ if [ -z "${tune_cpu}" ]; then
576+ if enabled armv7
577+ then
578+ check_add_cflags --cpu=Cortex-A8 --fpu=softvfp+vfpv3
579+ check_add_asflags --cpu=Cortex-A8 --fpu=none
580+ else
581+ check_add_cflags --cpu=${tgt_isa##armv}
582+ check_add_asflags --cpu=${tgt_isa##armv}
583+ fi
584+ fi
585+ arch_int=${tgt_isa##armv}
586+ arch_int=${arch_int%%te}
587+ check_add_asflags --pd "\"ARCHITECTURE SETA ${arch_int}\""
588+ ;;
589+ esac
590+
591+ case ${tgt_os} in
592+ darwin*)
593+ SDK_PATH=/Developer/Platforms/iPhoneOS.platform/Developer
594+ TOOLCHAIN_PATH=${SDK_PATH}/usr/bin
595+ CC=${TOOLCHAIN_PATH}/gcc
596+ AR=${TOOLCHAIN_PATH}/ar
597+ LD=${TOOLCHAIN_PATH}/arm-apple-darwin9-gcc-4.2.1
598+ AS=${TOOLCHAIN_PATH}/as
599+ STRIP=${TOOLCHAIN_PATH}/strip
600+ NM=${TOOLCHAIN_PATH}/nm
601+ AS_SFX=.s
602+
603+ # ASFLAGS is written here instead of using check_add_asflags
604+ # because we need to overwrite all of ASFLAGS and purge the
605+ # options that were put in above
606+ ASFLAGS="-version -arch ${tgt_isa} -g"
607+
608+ add_cflags -arch ${tgt_isa}
609+ add_ldflags -arch_only ${tgt_isa}
610+
611+ add_cflags "-isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.1.sdk"
612+
613+ # This should be overridable
614+ alt_libc=${SDK_PATH}/SDKs/iPhoneOS3.1.sdk
615+
616+ # Add the paths for the alternate libc
617+# for d in usr/include usr/include/gcc/darwin/4.0/; do
618+ for d in usr/include usr/include/gcc/darwin/4.0/ usr/lib/gcc/arm-apple-darwin9/4.0.1/include/; do
619+ try_dir="${alt_libc}/${d}"
620+ [ -d "${try_dir}" ] && add_cflags -I"${try_dir}"
621+ done
622+
623+ for d in lib usr/lib; do
624+ try_dir="${alt_libc}/${d}"
625+ [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
626+ done
627+
628+ asm_conversion_cmd="${source_path}/build/make/ads2gas_apple.pl"
629+ ;;
630+
631+ linux*)
632+ enable linux
633+ if enabled rvct; then
634+ # Compiling with RVCT requires an alternate libc (glibc) when
635+ # targetting linux.
636+ disabled builtin_libc \
637+ || die "Must supply --libc when targetting *-linux-rvct"
638+
639+ # Set up compiler
640+ add_cflags --gnu
641+ add_cflags --enum_is_int
642+ add_cflags --library_interface=aeabi_glibc
643+ add_cflags --no_hide_all
644+ add_cflags --wchar32
645+ add_cflags --dwarf2
646+ add_cflags --gnu
647+
648+ # Set up linker
649+ add_ldflags --sysv --no_startup --no_ref_cpp_init
650+ add_ldflags --entry=_start
651+ add_ldflags --keep '"*(.init)"' --keep '"*(.fini)"'
652+ add_ldflags --keep '"*(.init_array)"' --keep '"*(.fini_array)"'
653+ add_ldflags --dynamiclinker=/lib/ld-linux.so.3
654+ add_extralibs libc.so.6 -lc_nonshared crt1.o crti.o crtn.o
655+
656+ # Add the paths for the alternate libc
657+ for d in usr/include; do
658+ try_dir="${alt_libc}/${d}"
659+ [ -d "${try_dir}" ] && add_cflags -J"${try_dir}"
660+ done
661+ add_cflags -J"${RVCT31INC}"
662+ for d in lib usr/lib; do
663+ try_dir="${alt_libc}/${d}"
664+ [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
665+ done
666+
667+
668+ # glibc has some struct members named __align, which is a
669+ # storage modifier in RVCT. If we need to use this modifier,
670+ # we'll have to #undef it in our code. Note that this must
671+ # happen AFTER all libc inclues.
672+ add_cflags -D__align=x_align_x
673+ fi
674+ ;;
675+
676+ symbian*)
677+ enable symbian
678+ # Add the paths for the alternate libc
679+ for d in include/libc; do
680+ try_dir="${alt_libc}/${d}"
681+ [ -d "${try_dir}" ] && add_cflags -I"${try_dir}"
682+ done
683+ for d in release/armv5/urel; do
684+ try_dir="${alt_libc}/${d}"
685+ [ -d "${try_dir}" ] && add_ldflags -L"${try_dir}"
686+ done
687+ add_cflags -DIMPORT_C=
688+
689+ esac
690+ ;;
691+ mips*)
692+ CROSS=${CROSS:-mipsel-linux-uclibc-}
693+ link_with_cc=gcc
694+ setup_gnu_toolchain
695+ tune_cflags="-mtune="
696+ check_add_cflags -march=${tgt_isa}
697+ check_add_asflags -march=${tgt_isa}
698+ check_add_asflags -KPIC
699+ ;;
700+ ppc*)
701+ enable ppc
702+ bits=${tgt_isa##ppc}
703+ link_with_cc=gcc
704+ setup_gnu_toolchain
705+ add_asflags -force_cpusubtype_ALL -I"\$(dir \$<)darwin"
706+ add_cflags -maltivec -faltivec
707+ soft_enable altivec
708+
709+ case "$tgt_os" in
710+ linux*)
711+ add_asflags -maltivec -mregnames -I"\$(dir \$<)linux"
712+ ;;
713+ darwin*)
714+ darwin_arch="-arch ppc"
715+ enabled ppc64 && darwin_arch="${darwin_arch}64"
716+ add_cflags ${darwin_arch} -m${bits} -fasm-blocks
717+ add_asflags ${darwin_arch} -force_cpusubtype_ALL -I"\$(dir \$<)darwin"
718+ add_ldflags ${darwin_arch} -m${bits}
719+ ;;
720+ esac
721+ ;;
722+ x86*)
723+ bits=32
724+ enabled x86_64 && bits=64
725+ soft_enable runtime_cpu_detect
726+ soft_enable mmx
727+ soft_enable sse
728+ soft_enable sse2
729+ soft_enable sse3
730+ soft_enable ssse3
731+
732+ case ${tgt_os} in
733+ solaris*)
734+ CC=${CC:-${CROSS}gcc}
735+ LD=${LD:-${CROSS}gcc}
736+ CROSS=${CROSS:-g}
737+ ;;
738+ esac
739+
740+ case ${tgt_cc} in
741+ icc*)
742+ CC=${CC:-icc}
743+ LD=${LD:-icc}
744+ setup_gnu_toolchain
745+ add_cflags -use-msasm -use-asm
746+ add_ldflags -i-static
747+ ;;
748+ gcc*)
749+ add_cflags -m${bits}
750+ add_ldflags -m${bits}
751+ link_with_cc=gcc
752+ setup_gnu_toolchain
753+ ;;
754+ esac
755+
756+ AS=yasm
757+ AS_SFX=.asm
758+ case ${tgt_os} in
759+ win*)
760+ add_asflags -f win${bits}
761+ enabled debug && add_asflags -g dwarf2
762+ ;;
763+ linux*|solaris*)
764+ add_asflags -f elf${bits}
765+ enabled debug && add_asflags -g dwarf2
766+ ;;
767+ darwin*)
768+ add_asflags -f macho${bits}
769+ enabled x86 && darwin_arch="-arch i386" || darwin_arch="-arch x86_64"
770+ add_cflags ${darwin_arch}
771+ add_ldflags ${darwin_arch}
772+ # -mdynamic-no-pic is still a bit of voodoo -- it was required at
773+ # one time, but does not seem to be now, and it breaks some of the
774+ # code that still relies on inline assembly.
775+ # enabled icc && ! enabled pic && add_cflags -fno-pic -mdynamic-no-pic
776+ enabled icc && ! enabled pic && add_cflags -fno-pic
777+ ;;
778+ *) log "Warning: Unknown os $tgt_os while setting up yasm flags"
779+ ;;
780+ esac
781+ ;;
782+ universal*|*-gcc|generic-gnu)
783+ link_with_cc=gcc
784+ setup_gnu_toolchain
785+ ;;
786+ esac
787+
788+ # Try to enable CPU specific tuning
789+ if [ -n "${tune_cpu}" ]; then
790+ if [ -n "${tune_cflags}" ]; then
791+ check_add_cflags ${tune_cflags}${tune_cpu} || \
792+ die "Requested CPU '${tune_cpu}' not supported by compiler"
793+ fi
794+ if [ -n "${tune_asflags}" ]; then
795+ check_add_asflags ${tune_asflags}${tune_cpu} || \
796+ die "Requested CPU '${tune_cpu}' not supported by assembler"
797+ fi
798+ if [ -z "${tune_cflags}${tune_asflags}" ]; then
799+ log_echo "Warning: CPU tuning not supported by this toolchain"
800+ fi
801+ fi
802+
803+ enabled debug && check_add_cflags -g && check_add_ldflags -g
804+ enabled gprof && check_add_cflags -pg && check_add_ldflags -pg
805+ enabled gcov &&
806+ check_add_cflags -fprofile-arcs -ftest-coverage &&
807+ check_add_ldflags -fprofile-arcs -ftest-coverage
808+ enabled optimizations && check_add_cflags -O3
809+ if enabled rvct; then
810+ enabled optimizations && check_add_cflags -Otime
811+ fi
812+
813+ # Position Independant Code (PIC) support, for building relocatable
814+ # shared objects
815+ enabled gcc && enabled pic && check_add_cflags -fPIC
816+
817+ # Check for strip utility variant
818+ ${STRIP} -V 2>/dev/null | grep GNU >/dev/null && enable gnu_strip
819+
820+ # Try to determine target endianness
821+ check_cc <<EOF
822+ unsigned int e = 'O'<<24 | '2'<<16 | 'B'<<8 | 'E';
823+EOF
824+ [ -f "${TMP_O}" ] && od -A n -t x1 "${TMP_O}" | tr -d '\n' |
825+ grep '4f *32 *42 *45' >/dev/null 2>&1 && enable big_endian
826+
827+ # Almost every platform uses pthreads.
828+ if enabled multithread; then
829+ case ${toolchain} in
830+ *-win*);;
831+ *) check_header pthread.h && add_extralibs -lpthread
832+ esac
833+ fi
834+
835+ # glibc needs these
836+ if enabled linux; then
837+ add_cflags -D_LARGEFILE_SOURCE
838+ add_cflags -D_FILE_OFFSET_BITS=64
839+ fi
840+}
841+
842+process_toolchain() {
843+ process_common_toolchain
844+}
845+
846+print_config_mk() {
847+ prefix=$1
848+ makefile=$2
849+ shift 2
850+ for cfg; do
851+ upname="`toupper $cfg`"
852+ if enabled $cfg; then
853+ echo "${prefix}_${upname}=yes" >> $makefile
854+ fi
855+ done
856+}
857+
858+print_config_h() {
859+ prefix=$1
860+ header=$2
861+ shift 2
862+ for cfg; do
863+ upname="`toupper $cfg`"
864+ if enabled $cfg; then
865+ echo "#define ${prefix}_${upname} 1" >> $header
866+ else
867+ echo "#define ${prefix}_${upname} 0" >> $header
868+ fi
869+ done
870+}
871+
872+process_targets() {
873+ true;
874+}
875+
876+process_detect() {
877+ true;
878+}
879+
880+enable logging
881+logfile="config.err"
882+self=$0
883+process() {
884+ cmdline_args="$@"
885+ process_cmdline "$@"
886+ if enabled child; then
887+ echo "# ${self} $@" >> ${logfile}
888+ else
889+ echo "# ${self} $@" > ${logfile}
890+ fi
891+ post_process_cmdline
892+ process_toolchain
893+ process_detect
894+ process_targets
895+
896+ OOT_INSTALLS="${OOT_INSTALLS}"
897+ if enabled source_path_used; then
898+ # Prepare the PWD for building.
899+ for f in ${OOT_INSTALLS}; do
900+ install -D ${source_path}/$f $f
901+ done
902+ fi
903+ cp ${source_path}/build/make/Makefile .
904+
905+ clean_temp_files
906+ true
907+}
build/make/gen_asm_deps.sh+63−0
@@ -0,0 +1,63 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+self=$0
13+show_help() {
14+ echo "usage: $self [options] <srcfile>"
15+ echo
16+ echo "Generate Makefile dependency information from assembly code source"
17+ echo
18+ exit 1
19+}
20+die_unknown(){
21+ echo "Unknown option \"$1\"."
22+ echo "See $0 --help for available options."
23+ exit 1
24+}
25+for opt do
26+ optval="${opt#*=}"
27+ case "$opt" in
28+ --build-pfx=*) pfx="${optval}"
29+ ;;
30+ --depfile=*) out="${optval}"
31+ ;;
32+ -I*) raw_inc_paths="${raw_inc_paths} ${opt}"
33+ inc_path="${inc_path} ${opt#-I}"
34+ ;;
35+ -h|--help) show_help
36+ ;;
37+ *) [ -f "$opt" ] && srcfile="$opt"
38+ ;;
39+ esac
40+done
41+
42+[ -n "$srcfile" ] || show_help
43+sfx=${sfx:-asm}
44+includes=$(egrep -i "include +\"?+[a-z0-9_/]+\.${sfx}" $srcfile |
45+ perl -p -e "s;.*?([a-z0-9_/]+.${sfx}).*;\1;")
46+#" restore editor state
47+for inc in ${includes}; do
48+ found_inc_path=
49+ for idir in ${inc_path}; do
50+ [ -f "${idir}/${inc}" ] && found_inc_path="${idir}" && break
51+ done
52+ if [ -f `dirname $srcfile`/$inc ]; then
53+ # Handle include files in the same directory as the source
54+ $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} `dirname $srcfile`/$inc
55+ elif [ -n "${found_inc_path}" ]; then
56+ # Handle include files on the include path
57+ $self --build-pfx=$pfx --depfile=$out ${raw_inc_paths} "${found_inc_path}/$inc"
58+ else
59+ # Handle generated includes in the build root (which may not exist yet)
60+ echo ${out} ${out%d}o: "${pfx}${inc}"
61+ fi
62+done
63+echo ${out} ${out%d}o: $srcfile
build/make/gen_msvs_def.sh+82−0
@@ -0,0 +1,82 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+self=$0
13+self_basename=${self##*/}
14+EOL=$'\n'
15+
16+show_help() {
17+ cat <<EOF
18+Usage: ${self_basename} [options] file1 [file2 ...]
19+
20+This script generates a MSVC module definition file containing a list of symbols
21+to export from a DLL. Source files are technically bash scripts (and thus may
22+use #comment syntax) but in general, take the form of a list of symbols:
23+
24+ <kind> symbol1 [symbol2, symbol3, ...]
25+
26+where <kind> is either 'text' or 'data'
27+
28+
29+Options:
30+ --help Print this message
31+ --out=filename Write output to a file [stdout]
32+ --name=project_name Name of the library (required)
33+EOF
34+ exit 1
35+}
36+
37+die() {
38+ echo "${self_basename}: $@"
39+ exit 1
40+}
41+
42+die_unknown(){
43+ echo "Unknown option \"$1\"."
44+ echo "See ${self_basename} --help for available options."
45+ exit 1
46+}
47+
48+text() {
49+ for sym in "$@"; do
50+ echo " $sym" >> ${outfile}
51+ done
52+}
53+
54+data() {
55+ for sym in "$@"; do
56+ printf " %-40s DATA\n" "$sym" >> ${outfile}
57+ done
58+}
59+
60+# Process command line
61+for opt in "$@"; do
62+ optval="${opt#*=}"
63+ case "$opt" in
64+ --help|-h) show_help
65+ ;;
66+ --out=*) outfile="$optval"
67+ ;;
68+ --name=*) name="${optval}"
69+ ;;
70+ -*) die_unknown $opt
71+ ;;
72+ *) file_list[${#file_list[@]}]="$opt"
73+ esac
74+done
75+outfile=${outfile:-/dev/stdout}
76+[ -n "$name" ] || die "Library name (--name) must be specified!"
77+
78+echo "LIBRARY ${name}" > ${outfile}
79+echo "EXPORTS" >> ${outfile}
80+for f in "${file_list[@]}"; do
81+ . $f
82+done
build/make/gen_msvs_proj.sh+717−0
@@ -0,0 +1,717 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+self=$0
13+self_basename=${self##*/}
14+EOL=$'\n'
15+
16+show_help() {
17+ cat <<EOF
18+Usage: ${self_basename} --name=projname [options] file1 [file2 ...]
19+
20+This script generates a Visual Studio project file from a list of source
21+code files.
22+
23+Options:
24+ --help Print this message
25+ --exe Generate a project for building an Application
26+ --lib Generate a project for creating a static library
27+ --static-crt Use the static C runtime (/MT)
28+ --target=isa-os-cc Target specifier (required)
29+ --out=filename Write output to a file [stdout]
30+ --name=project_name Name of the project (required)
31+ --proj-guid=GUID GUID to use for the project
32+ --module-def=filename File containing export definitions (for DLLs)
33+ --ver=version Version (7,8) of visual studio to generate for
34+ -Ipath/to/include Additional include directories
35+ -DFLAG[=value] Preprocessor macros to define
36+ -Lpath/to/lib Additional library search paths
37+ -llibname Library to link against
38+EOF
39+ exit 1
40+}
41+
42+die() {
43+ echo "${self_basename}: $@" >&2
44+ exit 1
45+}
46+
47+die_unknown(){
48+ echo "Unknown option \"$1\"." >&2
49+ echo "See ${self_basename} --help for available options." >&2
50+ exit 1
51+}
52+
53+generate_uuid() {
54+ local hex="0123456789ABCDEF"
55+ local i
56+ local uuid=""
57+ local j
58+ #93995380-89BD-4b04-88EB-625FBE52EBFB
59+ for ((i=0; i<32; i++)); do
60+ (( j = $RANDOM % 16 ))
61+ uuid="${uuid}${hex:$j:1}"
62+ done
63+ echo "${uuid:0:8}-${uuid:8:4}-${uuid:12:4}-${uuid:16:4}-${uuid:20:12}"
64+}
65+
66+indent1=" "
67+indent=""
68+indent_push() {
69+ indent="${indent}${indent1}"
70+}
71+indent_pop() {
72+ indent="${indent%${indent1}}"
73+}
74+
75+tag_attributes() {
76+ for opt in "$@"; do
77+ optval="${opt#*=}"
78+ [ -n "${optval}" ] ||
79+ die "Missing attribute value in '$opt' while generating $tag tag"
80+ echo "${indent}${opt%%=*}=\"${optval}\""
81+ done
82+}
83+
84+open_tag() {
85+ local tag=$1
86+ shift
87+ if [ $# -ne 0 ]; then
88+ echo "${indent}<${tag}"
89+ indent_push
90+ tag_attributes "$@"
91+ echo "${indent}>"
92+ else
93+ echo "${indent}<${tag}>"
94+ indent_push
95+ fi
96+}
97+
98+close_tag() {
99+ local tag=$1
100+ indent_pop
101+ echo "${indent}</${tag}>"
102+}
103+
104+tag() {
105+ local tag=$1
106+ shift
107+ if [ $# -ne 0 ]; then
108+ echo "${indent}<${tag}"
109+ indent_push
110+ tag_attributes "$@"
111+ indent_pop
112+ echo "${indent}/>"
113+ else
114+ echo "${indent}<${tag}/>"
115+ fi
116+}
117+
118+generate_filter() {
119+ local var=$1
120+ local name=$2
121+ local pats=$3
122+ local file_list_sz
123+ local i
124+ local f
125+ local saveIFS="$IFS"
126+ local pack
127+ echo "generating filter '$name' from ${#file_list[@]} files" >&2
128+ IFS=*
129+
130+ open_tag Filter \
131+ Name=$name \
132+ Filter=$pats \
133+ UniqueIdentifier=`generate_uuid`
134+
135+ file_list_sz=${#file_list[@]}
136+ for i in ${!file_list[@]}; do
137+ f=${file_list[i]}
138+ for pat in ${pats//;/$IFS}; do
139+ if [ "${f##*.}" == "$pat" ]; then
140+ unset file_list[i]
141+
142+ open_tag File RelativePath="./$f"
143+ if [ "$pat" == "asm" ] && $asm_use_custom_step; then
144+ for plat in "${platforms[@]}"; do
145+ for cfg in Debug Release; do
146+ open_tag FileConfiguration \
147+ Name="${cfg}|${plat}"
148+ tag Tool \
149+ Name="VCCustomBuildTool" \
150+ Description="Assembling \$(InputFileName)" \
151+ CommandLine="$(eval echo \$asm_${cfg}_cmdline)"\
152+ Outputs="\$(InputName).obj"
153+ close_tag FileConfiguration
154+ done
155+ done
156+ fi
157+
158+ if [ "${f##*.}" == "cpp" ]; then
159+ for plat in "${platforms[@]}"; do
160+ for cfg in Debug Release; do
161+ open_tag FileConfiguration \
162+ Name="${cfg}|${plat}"
163+ tag Tool \
164+ Name="VCCLCompilerTool" \
165+ CompileAs="2"
166+ close_tag FileConfiguration
167+ done
168+ done
169+ fi
170+ close_tag File
171+
172+ break
173+ fi
174+ done
175+ done
176+
177+ close_tag Filter
178+ IFS="$saveIFS"
179+}
180+
181+# Process command line
182+unset target
183+for opt in "$@"; do
184+ optval="${opt#*=}"
185+ case "$opt" in
186+ --help|-h) show_help
187+ ;;
188+ --target=*) target="${optval}"
189+ ;;
190+ --out=*) outfile="$optval"
191+ ;;
192+ --name=*) name="${optval}"
193+ ;;
194+ --proj-guid=*) guid="${optval}"
195+ ;;
196+ --module-def=*)
197+ link_opts="${link_opts} ModuleDefinitionFile=${optval}"
198+ ;;
199+ --exe) proj_kind="exe"
200+ ;;
201+ --lib) proj_kind="lib"
202+ ;;
203+ --static-crt) use_static_runtime=true
204+ ;;
205+ --ver=*) vs_ver="$optval"
206+ case $optval in
207+ [78])
208+ ;;
209+ *) die Unrecognized Visual Studio Version in $opt
210+ ;;
211+ esac
212+ ;;
213+ -I*) opt="${opt%/}"
214+ incs="${incs}${incs:+;}&quot;${opt##-I}&quot;"
215+ yasmincs="${yasmincs} ${opt}"
216+ ;;
217+ -D*) defines="${defines}${defines:+;}${opt##-D}"
218+ ;;
219+ -L*) # fudge . to $(OutDir)
220+ if [ "${opt##-L}" == "." ]; then
221+ libdirs="${libdirs}${libdirs:+;}&quot;\$(OutDir)&quot;"
222+ else
223+ # Also try directories for this platform/configuration
224+ libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}&quot;"
225+ libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)/\$(ConfigurationName)&quot;"
226+ libdirs="${libdirs}${libdirs:+;}&quot;${opt##-L}/\$(PlatformName)&quot;"
227+ fi
228+ ;;
229+ -l*) libs="${libs}${libs:+ }${opt##-l}.lib"
230+ ;;
231+ -*) die_unknown $opt
232+ ;;
233+ *) file_list[${#file_list[@]}]="$opt"
234+ case "$opt" in
235+ *.asm) uses_asm=true;;
236+ esac
237+ esac
238+done
239+outfile=${outfile:-/dev/stdout}
240+guid=${guid:-`generate_uuid`}
241+asm_use_custom_step=false
242+uses_asm=${uses_asm:-false}
243+case "${vs_ver:-8}" in
244+ 7) vs_ver_id="7.10"
245+ asm_use_custom_step=$uses_asm
246+ ;;
247+ 8) vs_ver_id="8.00"
248+ ;;
249+esac
250+
251+[ -n "$name" ] || die "Project name (--name) must be specified!"
252+[ -n "$target" ] || die "Target (--target) must be specified!"
253+
254+if ${use_static_runtime:-false}; then
255+ release_runtime=0
256+ debug_runtime=1
257+ lib_sfx=mt
258+else
259+ release_runtime=2
260+ debug_runtime=3
261+ lib_sfx=md
262+fi
263+
264+# Calculate debug lib names: If a lib ends in ${lib_sfx}.lib, then rename
265+# it to ${lib_sfx}d.lib. This precludes linking to release libs from a
266+# debug exe, so this may need to be refactored later.
267+for lib in ${libs}; do
268+ if [ "$lib" != "${lib%${lib_sfx}.lib}" ]; then
269+ lib=${lib%.lib}d.lib
270+ fi
271+ debug_libs="${debug_libs}${debug_libs:+ }${lib}"
272+done
273+
274+
275+# List Keyword for this target
276+case "$target" in
277+ x86*)
278+ keyword="ManagedCProj"
279+ ;;
280+ arm*|iwmmx*)
281+ keyword="Win32Proj"
282+ ;;
283+ *) die "Unsupported target $target!"
284+esac
285+
286+# List of all platforms supported for this target
287+case "$target" in
288+ x86_64*)
289+ platforms[0]="x64"
290+ ;;
291+ x86*)
292+ platforms[0]="Win32"
293+ # these are only used by vs7
294+ asm_Debug_cmdline="yasm -Xvc -g cv8 -f \$(PlatformName) ${yasmincs} \$(InputPath)"
295+ asm_Release_cmdline="yasm -Xvc -f \$(PlatformName) ${yasmincs} \$(InputPath)"
296+ ;;
297+ arm*|iwmmx*)
298+ case "${name}" in
299+ obj_int_extract) platforms[0]="Win32"
300+ ;;
301+ *) platforms[0]="Pocket PC 2003 (ARMV4)"
302+ ;;
303+ esac
304+ ;;
305+ *) die "Unsupported target $target!"
306+esac
307+
308+# List Command-line Arguments for this target
309+case "$target" in
310+ arm*|iwmmx*)
311+ if [ "$name" == "example" ];then
312+ ARGU="--codec vp6 --flipuv --progress _bnd.vp6"
313+ fi
314+ if [ "$name" == "xma" ];then
315+ ARGU="--codec vp6 -h 240 -w 320 -v"
316+ fi
317+ ;;
318+esac
319+
320+generate_vcproj() {
321+ case "$proj_kind" in
322+ exe) vs_ConfigurationType=1
323+ ;;
324+ *) vs_ConfigurationType=4
325+ ;;
326+ esac
327+
328+ echo "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>"
329+ open_tag VisualStudioProject \
330+ ProjectType="Visual C++" \
331+ Version="${vs_ver_id}" \
332+ Name="${name}" \
333+ ProjectGUID="{${guid}}" \
334+ RootNamespace="${name}" \
335+ Keyword="${keyword}"
336+
337+ open_tag Platforms
338+ for plat in "${platforms[@]}"; do
339+ tag Platform Name="$plat"
340+ done
341+ close_tag Platforms
342+
343+ open_tag ToolFiles
344+ case "$target" in
345+ x86*) $uses_asm && tag DefaultToolFile FileName="yasm.rules"
346+ ;;
347+ arm*|iwmmx*)
348+ if [ "$name" == "vpx_decoder" ];then
349+ case "$target" in
350+ armv5*)
351+ tag DefaultToolFile FileName="armasmv5.rules"
352+ ;;
353+ armv6*)
354+ tag DefaultToolFile FileName="armasmv6.rules"
355+ ;;
356+ iwmmxt*)
357+ tag DefaultToolFile FileName="armasmxscale.rules"
358+ ;;
359+ esac
360+ fi
361+ ;;
362+ esac
363+ close_tag ToolFiles
364+
365+ open_tag Configurations
366+ for plat in "${platforms[@]}"; do
367+ plat_no_ws=`echo $plat | sed 's/[^A-Za-z0-9_]/_/g'`
368+ open_tag Configuration \
369+ Name="Debug|$plat" \
370+ OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
371+ IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
372+ ConfigurationType="$vs_ConfigurationType" \
373+ CharacterSet="1"
374+
375+ if [ "$target" == "armv6-wince-vs8" ] || [ "$target" == "armv5te-wince-vs8" ] || [ "$target" == "iwmmxt-wince-vs8" ] || [ "$target" == "iwmmxt2-wince-vs8" ];then
376+ case "$name" in
377+ vpx_decoder) tag Tool \
378+ Name="VCPreBuildEventTool" \
379+ CommandLine="call obj_int_extract.bat \$(ConfigurationName)"
380+ tag Tool \
381+ Name="VCMIDLTool" \
382+ TargetEnvironment="1"
383+ tag Tool \
384+ Name="VCCLCompilerTool" \
385+ ExecutionBucket="7" \
386+ Optimization="0" \
387+ AdditionalIncludeDirectories="$incs" \
388+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
389+ MinimalRebuild="true" \
390+ RuntimeLibrary="1" \
391+ BufferSecurityCheck="false" \
392+ UsePrecompiledHeader="0" \
393+ WarningLevel="3" \
394+ DebugInformationFormat="1" \
395+ CompileAs="1"
396+ tag Tool \
397+ Name="VCResourceCompilerTool" \
398+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES)" \
399+ Culture="1033" \
400+ AdditionalIncludeDirectories="\$(IntDir)" \
401+ ;;
402+ example|xma) tag Tool \
403+ Name="VCCLCompilerTool" \
404+ ExecutionBucket="7" \
405+ Optimization="0" \
406+ AdditionalIncludeDirectories="$incs" \
407+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;DEBUG;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
408+ MinimalRebuild="true" \
409+ RuntimeLibrary="1" \
410+ BufferSecurityCheck="false" \
411+ UsePrecompiledHeader="0" \
412+ WarningLevel="3" \
413+ DebugInformationFormat="1" \
414+ CompileAs="1"
415+ tag Tool \
416+ Name="VCResourceCompilerTool" \
417+ PreprocessorDefinitions="_DEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES)" \
418+ Culture="1033" \
419+ AdditionalIncludeDirectories="\$(IntDir)" \
420+ ;;
421+ obj_int_extract) tag Tool \
422+ Name="VCCLCompilerTool" \
423+ Optimization="0" \
424+ AdditionalIncludeDirectories="$incs" \
425+ PreprocessorDefinitions="WIN32;DEBUG;_CONSOLE" \
426+ RuntimeLibrary="1" \
427+ WarningLevel="3" \
428+ DebugInformationFormat="1" \
429+ ;;
430+ esac
431+ fi
432+
433+ case "$target" in
434+ x86*) tag Tool \
435+ Name="VCCLCompilerTool" \
436+ Optimization="0" \
437+ AdditionalIncludeDirectories="$incs" \
438+ PreprocessorDefinitions="WIN32;_DEBUG;_CRT_SECURE_NO_WARNINGS;$defines" \
439+ RuntimeLibrary="$debug_runtime" \
440+ UsePrecompiledHeader="0" \
441+ WarningLevel="3" \
442+ DebugInformationFormat="1" \
443+ Detect64BitPortabilityProblems="true" \
444+
445+ $uses_asm && tag Tool Name="YASM" IncludePaths="$incs" Debug="1"
446+ ;;
447+ esac
448+
449+ case "$proj_kind" in
450+ exe)
451+ case "$target" in
452+ x86*) tag Tool \
453+ Name="VCLinkerTool" \
454+ AdditionalDependencies="$debug_libs \$(NoInherit)" \
455+ AdditionalLibraryDirectories="$libdirs" \
456+ GenerateDebugInformation="true" \
457+ ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
458+
459+ ;;
460+ arm*|iwmmx*)
461+ case "$name" in
462+ obj_int_extract) tag Tool \
463+ Name="VCLinkerTool" \
464+ OutputFile="${name}.exe" \
465+ GenerateDebugInformation="true"
466+ ;;
467+ *) tag Tool \
468+ Name="VCLinkerTool" \
469+ AdditionalDependencies="$debug_libs" \
470+ OutputFile="\$(OutDir)/${name}.exe" \
471+ LinkIncremental="2" \
472+ AdditionalLibraryDirectories="${libdirs};&quot;..\lib/$plat_no_ws&quot;" \
473+ DelayLoadDLLs="\$(NOINHERIT)" \
474+ GenerateDebugInformation="true" \
475+ ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
476+ SubSystem="9" \
477+ StackReserveSize="65536" \
478+ StackCommitSize="4096" \
479+ EntryPointSymbol="mainWCRTStartup" \
480+ TargetMachine="3"
481+ ;;
482+ esac
483+ ;;
484+ esac
485+ ;;
486+ lib)
487+ case "$target" in
488+ arm*|iwmmx*) tag Tool \
489+ Name="VCLibrarianTool" \
490+ AdditionalOptions=" /subsystem:windowsce,4.20 /machine:ARM" \
491+ OutputFile="\$(OutDir)/${name}.lib" \
492+ ;;
493+ *) tag Tool \
494+ Name="VCLibrarianTool" \
495+ OutputFile="\$(OutDir)/${name}${lib_sfx}d.lib" \
496+ ;;
497+ esac
498+ ;;
499+ dll) tag Tool \
500+ Name="VCLinkerTool" \
501+ AdditionalDependencies="\$(NoInherit)" \
502+ LinkIncremental="2" \
503+ GenerateDebugInformation="true" \
504+ AssemblyDebug="1" \
505+ TargetMachine="1" \
506+ $link_opts
507+ esac
508+
509+ if [ "$target" == "armv6-wince-vs8" ] || [ "$target" == "armv5te-wince-vs8" ] || [ "$target" == "iwmmxt-wince-vs8" ] || [ "$target" == "iwmmxt2-wince-vs8" ];then
510+ case "$name" in
511+ vpx_decoder) tag DeploymentTool \
512+ ForceDirty="-1" \
513+ RegisterOutput="0"
514+ ;;
515+ example|xma) tag DeploymentTool \
516+ ForceDirty="-1" \
517+ RegisterOutput="0"
518+ tag DebuggerTool \
519+ Arguments="${ARGU}"
520+ ;;
521+ esac
522+ fi
523+ close_tag Configuration
524+
525+ open_tag Configuration \
526+ Name="Release|$plat" \
527+ OutputDirectory="\$(SolutionDir)$plat_no_ws/\$(ConfigurationName)" \
528+ IntermediateDirectory="$plat_no_ws/\$(ConfigurationName)/${name}" \
529+ ConfigurationType="$vs_ConfigurationType" \
530+ CharacterSet="1" \
531+ WholeProgramOptimization="0"
532+
533+ if [ "$target" == "armv6-wince-vs8" ] || [ "$target" == "armv5te-wince-vs8" ] || [ "$target" == "iwmmxt-wince-vs8" ] || [ "$target" == "iwmmxt2-wince-vs8" ];then
534+ case "$name" in
535+ vpx_decoder) tag Tool \
536+ Name="VCPreBuildEventTool" \
537+ CommandLine="call obj_int_extract.bat \$(ConfigurationName)"
538+ tag Tool \
539+ Name="VCMIDLTool" \
540+ TargetEnvironment="1"
541+ tag Tool \
542+ Name="VCCLCompilerTool" \
543+ ExecutionBucket="7" \
544+ Optimization="2" \
545+ FavorSizeOrSpeed="1" \
546+ AdditionalIncludeDirectories="$incs" \
547+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_LIB;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
548+ RuntimeLibrary="0" \
549+ BufferSecurityCheck="false" \
550+ UsePrecompiledHeader="0" \
551+ WarningLevel="3" \
552+ DebugInformationFormat="0" \
553+ CompileAs="1"
554+ tag Tool \
555+ Name="VCResourceCompilerTool" \
556+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES)" \
557+ Culture="1033" \
558+ AdditionalIncludeDirectories="\$(IntDir)" \
559+ ;;
560+ example|xma) tag Tool \
561+ Name="VCCLCompilerTool" \
562+ ExecutionBucket="7" \
563+ Optimization="2" \
564+ FavorSizeOrSpeed="1" \
565+ AdditionalIncludeDirectories="$incs" \
566+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES);WINCE;_CONSOLE;\$(ARCHFAM);\$(_ARCHFAM_);_UNICODE;UNICODE;HAVE_CONFIG_H" \
567+ RuntimeLibrary="0" \
568+ BufferSecurityCheck="false" \
569+ UsePrecompiledHeader="0" \
570+ WarningLevel="3" \
571+ DebugInformationFormat="0" \
572+ CompileAs="1"
573+ tag Tool \
574+ Name="VCResourceCompilerTool" \
575+ PreprocessorDefinitions="NDEBUG;_WIN32_WCE=\$(CEVER);UNDER_CE;\$(PLATFORMDEFINES)" \
576+ Culture="1033" \
577+ AdditionalIncludeDirectories="\$(IntDir)" \
578+ ;;
579+ obj_int_extract) tag Tool \
580+ Name="VCCLCompilerTool" \
581+ AdditionalIncludeDirectories="$incs" \
582+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE" \
583+ RuntimeLibrary="0" \
584+ UsePrecompiledHeader="0" \
585+ WarningLevel="3" \
586+ Detect64BitPortabilityProblems="true" \
587+ DebugInformationFormat="0" \
588+ ;;
589+ esac
590+ fi
591+
592+ case "$target" in
593+ x86*) tag Tool \
594+ Name="VCCLCompilerTool" \
595+ AdditionalIncludeDirectories="$incs" \
596+ PreprocessorDefinitions="WIN32;NDEBUG;_CRT_SECURE_NO_WARNINGS;$defines" \
597+ RuntimeLibrary="$release_runtime" \
598+ UsePrecompiledHeader="0" \
599+ WarningLevel="3" \
600+ DebugInformationFormat="0" \
601+ Detect64BitPortabilityProblems="true"
602+
603+ $uses_asm && tag Tool Name="YASM" IncludePaths="$incs"
604+ ;;
605+ esac
606+
607+ case "$proj_kind" in
608+ exe)
609+ case "$target" in
610+ x86*) tag Tool \
611+ Name="VCLinkerTool" \
612+ AdditionalDependencies="$libs \$(NoInherit)" \
613+ AdditionalLibraryDirectories="$libdirs" \
614+ ;;
615+ arm*|iwmmx*)
616+ case "$name" in
617+ obj_int_extract) tag Tool \
618+ Name="VCLinkerTool" \
619+ OutputFile="${name}.exe" \
620+ LinkIncremental="1" \
621+ GenerateDebugInformation="false" \
622+ SubSystem="0" \
623+ OptimizeReferences="0" \
624+ EnableCOMDATFolding="0" \
625+ TargetMachine="0"
626+ ;;
627+ *) tag Tool \
628+ Name="VCLinkerTool" \
629+ AdditionalDependencies="$libs" \
630+ OutputFile="\$(OutDir)/${name}.exe" \
631+ LinkIncremental="1" \
632+ AdditionalLibraryDirectories="${libdirs};&quot;..\lib/$plat_no_ws&quot;" \
633+ DelayLoadDLLs="\$(NOINHERIT)" \
634+ GenerateDebugInformation="true" \
635+ ProgramDatabaseFile="\$(OutDir)/${name}.pdb" \
636+ SubSystem="9" \
637+ StackReserveSize="65536" \
638+ StackCommitSize="4096" \
639+ OptimizeReferences="2" \
640+ EnableCOMDATFolding="2" \
641+ EntryPointSymbol="mainWCRTStartup" \
642+ TargetMachine="3"
643+ ;;
644+ esac
645+ ;;
646+ esac
647+ ;;
648+ lib)
649+ case "$target" in
650+ arm*|iwmmx*) tag Tool \
651+ Name="VCLibrarianTool" \
652+ AdditionalOptions=" /subsystem:windowsce,4.20 /machine:ARM" \
653+ OutputFile="\$(OutDir)/${name}.lib" \
654+ ;;
655+ *) tag Tool \
656+ Name="VCLibrarianTool" \
657+ OutputFile="\$(OutDir)/${name}${lib_sfx}.lib" \
658+ ;;
659+ esac
660+ ;;
661+ dll) # note differences to debug version: LinkIncremental, AssemblyDebug
662+ tag Tool \
663+ Name="VCLinkerTool" \
664+ AdditionalDependencies="\$(NoInherit)" \
665+ LinkIncremental="1" \
666+ GenerateDebugInformation="true" \
667+ TargetMachine="1" \
668+ $link_opts
669+ esac
670+
671+ if [ "$target" == "armv6-wince-vs8" ] || [ "$target" == "armv5te-wince-vs8" ] || [ "$target" == "iwmmxt-wince-vs8" ] || [ "$target" == "iwmmxt2-wince-vs8" ];then
672+ case "$name" in
673+ vpx_decoder) tag DeploymentTool \
674+ ForceDirty="-1" \
675+ RegisterOutput="0"
676+ ;;
677+ example|xma) tag DeploymentTool \
678+ ForceDirty="-1" \
679+ RegisterOutput="0"
680+ tag DebuggerTool \
681+ Arguments="${ARGU}"
682+ ;;
683+ esac
684+ fi
685+
686+ close_tag Configuration
687+ done
688+ close_tag Configurations
689+
690+ open_tag Files
691+ generate_filter srcs "Source Files" "cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
692+ generate_filter hdrs "Header Files" "h;hpp;hxx;hm;inl;inc;xsd"
693+ generate_filter resrcs "Resource Files" "rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
694+ generate_filter resrcs "Build Files" "mk"
695+ close_tag Files
696+
697+ tag Globals
698+ close_tag VisualStudioProject
699+
700+ # This must be done from within the {} subshell
701+ echo "Ignored files list (${#file_list[@]} items) is:" >&2
702+ for f in "${file_list[@]}"; do
703+ echo " $f" >&2
704+ done
705+}
706+
707+generate_vcproj |
708+ sed -e '/"/s;\([^ "]\)/;\1\\;g' > ${outfile}
709+
710+exit
711+<!--
712+TODO: Add any files not captured by filters.
713+ <File
714+ RelativePath=".\ReadMe.txt"
715+ >
716+ </File>
717+-->
build/make/gen_msvs_sln.sh+272−0
@@ -0,0 +1,272 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+self=$0
13+self_basename=${self##*/}
14+EOL=$'\n'
15+EOLDOS=$'\r'
16+
17+show_help() {
18+ cat <<EOF
19+Usage: ${self_basename} [options] file1 [file2 ...]
20+
21+This script generates a Visual Studio 2005 solution file from a list of project
22+files.
23+
24+Options:
25+ --help Print this message
26+ --out=outfile Redirect output to a file
27+ --ver=version Version (7,8) of visual studio to generate for
28+ --target=isa-os-cc Target specifier
29+EOF
30+ exit 1
31+}
32+
33+die() {
34+ echo "${self_basename}: $@" >&2
35+ [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
36+ exit 1
37+}
38+
39+die_unknown(){
40+ echo "Unknown option \"$1\"." >&2
41+ echo "See ${self_basename} --help for available options." >&2
42+ [ -f "${outfile}" ] && rm -f ${outfile}{,.mk}
43+ exit 1
44+}
45+
46+indent1=$'\t'
47+indent=""
48+indent_push() {
49+ indent="${indent}${indent1}"
50+}
51+indent_pop() {
52+ indent="${indent%${indent1}}"
53+}
54+
55+parse_project() {
56+ local file=$1
57+ local name=`grep Name "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
58+ local guid=`grep ProjectGUID "$file" | awk 'BEGIN {FS="\""}{if (NR==1) print $2}'`
59+
60+ # save the project GUID to a varaible, normalizing to the basename of the
61+ # vcproj file without the extension
62+ local var
63+ var=${file##*/}
64+ var=${var%%.vcproj}
65+ eval "${var}_file=\"$1\""
66+ eval "${var}_name=$name"
67+ eval "${var}_guid=$guid"
68+
69+ # assume that all projects have the same list of possible configurations,
70+ # so overwriting old config_lists is not a problem
71+ config_list=`grep -A1 '<Configuration' $file |
72+ grep Name | cut -d\" -f2`
73+ proj_list="${proj_list} ${var}"
74+}
75+
76+process_project() {
77+ eval "local file=\${$1_file}"
78+ eval "local name=\${$1_name}"
79+ eval "local guid=\${$1_guid}"
80+
81+ # save the project GUID to a varaible, normalizing to the basename of the
82+ # vcproj file without the extension
83+ local var
84+ var=${file##*/}
85+ var=${var%%.vcproj}
86+ eval "${var}_guid=$guid"
87+
88+ echo "Project(\"{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}\") = \"$name\", \"$file\", \"$guid\""
89+ indent_push
90+
91+ eval "local deps=\"\${${var}_deps}\""
92+ if [ -n "$deps" ]; then
93+ echo "${indent}ProjectSection(ProjectDependencies) = postProject"
94+ indent_push
95+
96+ for dep in $deps; do
97+ eval "local dep_guid=\${${dep}_guid}"
98+ [ -z "${dep_guid}" ] && die "Unknown GUID for $dep (dependency of $var)"
99+ echo "${indent}$dep_guid = $dep_guid"
100+ done
101+
102+ indent_pop
103+ echo "${indent}EndProjectSection"
104+
105+ fi
106+
107+ indent_pop
108+ echo "EndProject"
109+}
110+
111+process_global() {
112+ echo "Global"
113+ indent_push
114+
115+ #
116+ # Solution Configuration Platforms
117+ #
118+ echo "${indent}GlobalSection(SolutionConfigurationPlatforms) = preSolution"
119+ indent_push
120+ IFS_bak=${IFS}
121+ IFS=$'\r'$'\n'
122+ for config in ${config_list}; do
123+ echo "${indent}$config = $config"
124+ done
125+ IFS=${IFS_bak}
126+ indent_pop
127+ echo "${indent}EndGlobalSection"
128+
129+ #
130+ # Project Configuration Platforms
131+ #
132+ echo "${indent}GlobalSection(ProjectConfigurationPlatforms) = postSolution"
133+ indent_push
134+ for proj in ${proj_list}; do
135+ eval "local proj_guid=\${${proj}_guid}"
136+ IFS=$'\r'$'\n'
137+ for config in ${config_list}; do
138+ echo "${indent}${proj_guid}.${config}.ActiveCfg = ${config}"
139+ echo "${indent}${proj_guid}.${config}.Build.0 = ${config}"
140+
141+ if [ "$target" == "armv6-wince-vs8" ] || [ "$target" == "armv5te-wince-vs8" ] || [ "$target" == "iwmmxt-wince-vs8" ] || [ "$target" == "iwmmxt2-wince-vs8" ];then
142+ echo "${indent}${proj_guid}.${config}.Deploy.0 = ${config}"
143+ fi
144+ done
145+ IFS=${IFS_bak}
146+ done
147+ indent_pop
148+ echo "${indent}EndGlobalSection"
149+
150+ #
151+ # Solution Properties
152+ #
153+ echo "${indent}GlobalSection(SolutionProperties) = preSolution"
154+ indent_push
155+ echo "${indent}HideSolutionNode = FALSE"
156+ indent_pop
157+ echo "${indent}EndGlobalSection"
158+
159+ indent_pop
160+ echo "EndGlobal"
161+}
162+
163+process_makefile() {
164+ IFS_bak=${IFS}
165+ IFS=$'\r'$'\n'
166+ local TAB=$'\t'
167+ cat <<EOF
168+found_devenv := \$(shell which devenv.com >/dev/null 2>&1 && echo yes)
169+.nodevenv.once:
170+${TAB}@echo " * devenv.com not found in path."
171+${TAB}@echo " * "
172+${TAB}@echo " * You will have to build all configurations manually using the"
173+${TAB}@echo " * Visual Studio IDE. To allow make to build them automatically,"
174+${TAB}@echo " * add the Common7/IDE directory of your Visual Studio"
175+${TAB}@echo " * installation to your path, eg:"
176+${TAB}@echo " * C:\Program Files\Microsoft Visual Studio 8\Common7\IDE"
177+${TAB}@echo " * "
178+${TAB}@touch \$@
179+CLEAN-OBJS += \$(if \$(found_devenv),,.nodevenv.once)
180+
181+EOF
182+
183+ for sln_config in ${config_list}; do
184+ local config=${sln_config%%|*}
185+ local platform=${sln_config##*|}
186+ local nows_sln_config=`echo $sln_config | sed -e 's/[^a-zA-Z0-9]/_/g'`
187+ cat <<EOF
188+BUILD_TARGETS += \$(if \$(NO_LAUNCH_DEVENV),,$nows_sln_config)
189+clean::
190+${TAB}rm -rf "$platform"/"$config"
191+.PHONY: $nows_sln_config
192+ifneq (\$(found_devenv),)
193+ ifeq (\$(CONFIG_VS_VERSION),7)
194+$nows_sln_config: $outfile
195+${TAB}devenv.com $outfile /build "$config"
196+
197+ else
198+$nows_sln_config: $outfile
199+${TAB}devenv.com $outfile /build "$sln_config"
200+
201+ endif
202+else
203+$nows_sln_config: $outfile .nodevenv.once
204+${TAB}@echo " * Skipping build of $sln_config (devenv.com not in path)."
205+${TAB}@echo " * "
206+endif
207+
208+EOF
209+ done
210+ IFS=${IFS_bak}
211+}
212+
213+# Process command line
214+outfile=/dev/stdout
215+for opt in "$@"; do
216+ optval="${opt#*=}"
217+ case "$opt" in
218+ --help|-h) show_help
219+ ;;
220+ --out=*) outfile="${optval}"; mkoutfile="${optval}".mk
221+ ;;
222+ --dep=*) eval "${optval%%:*}_deps=\"\${${optval%%:*}_deps} ${optval##*:}\""
223+ ;;
224+ --ver=*) vs_ver="$optval"
225+ case $optval in
226+ [78])
227+ ;;
228+ *) die Unrecognized Visual Studio Version in $opt
229+ ;;
230+ esac
231+ ;;
232+ --ver=*) vs_ver="$optval"
233+ case $optval in
234+ 7) sln_vers="8.00"
235+ sln_vers_str="Visual Studio .NET 2003"
236+ ;;
237+ 8)
238+ ;;
239+ *) die "Unrecognized Visual Studio Version '$optval' in $opt"
240+ ;;
241+ esac
242+ ;;
243+ --target=*) target="${optval}"
244+ ;;
245+ -*) die_unknown $opt
246+ ;;
247+ *) file_list[${#file_list[@]}]="$opt"
248+ esac
249+done
250+outfile=${outfile:-/dev/stdout}
251+mkoutfile=${mkoutfile:-/dev/stdout}
252+case "${vs_ver:-8}" in
253+ 7) sln_vers="8.00"
254+ sln_vers_str="Visual Studio .NET 2003"
255+ ;;
256+ 8) sln_vers="9.00"
257+ sln_vers_str="Visual Studio 2005"
258+ ;;
259+esac
260+
261+for f in "${file_list[@]}"; do
262+ parse_project $f
263+done
264+cat >${outfile} <<EOF
265+Microsoft Visual Studio Solution File, Format Version $sln_vers${EOLDOS}
266+# $sln_vers_str${EOLDOS}
267+EOF
268+for proj in ${proj_list}; do
269+ process_project $proj >>${outfile}
270+done
271+process_global >>${outfile}
272+process_makefile >${mkoutfile}
build/make/obj_int_extract.c+755−0
@@ -0,0 +1,755 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+#include <stdio.h>
12+#include <stdlib.h>
13+
14+#include "vpx_config.h"
15+
16+#if defined(_MSC_VER)
17+#include <io.h>
18+#include <share.h>
19+#include "vpx_ports/vpx_integer.h"
20+#else
21+#include <stdint.h>
22+#include <unistd.h>
23+#endif
24+
25+#include <string.h>
26+#include <sys/types.h>
27+#include <sys/stat.h>
28+#include <fcntl.h>
29+#include <stdarg.h>
30+
31+typedef enum
32+{
33+ OUTPUT_FMT_PLAIN,
34+ OUTPUT_FMT_RVDS,
35+ OUTPUT_FMT_GAS,
36+} output_fmt_t;
37+
38+int log_msg(const char *fmt, ...)
39+{
40+ int res;
41+ va_list ap;
42+ va_start(ap, fmt);
43+ res = vfprintf(stderr, fmt, ap);
44+ va_end(ap);
45+ return res;
46+}
47+
48+#if defined(__GNUC__) && __GNUC__
49+
50+#if defined(__MACH__)
51+
52+#include <mach-o/loader.h>
53+#include <mach-o/nlist.h>
54+
55+int parse_macho(uint8_t *base_buf, size_t sz)
56+{
57+ int i, j;
58+ struct mach_header header;
59+ uint8_t *buf = base_buf;
60+ int base_data_section = 0;
61+
62+ memcpy(&header, buf, sizeof(struct mach_header));
63+ buf += sizeof(struct mach_header);
64+
65+ if (header.magic != MH_MAGIC)
66+ {
67+ log_msg("Bad magic number for object file. 0x%x expected, 0x%x found.\n",
68+ header.magic, MH_MAGIC);
69+ goto bail;
70+ }
71+
72+ if (header.cputype != CPU_TYPE_ARM)
73+ {
74+ log_msg("Bad cputype for object file. Currently only tested for CPU_TYPE_ARM.\n");
75+ goto bail;
76+ }
77+
78+ if (header.filetype != MH_OBJECT)
79+ {
80+ log_msg("Bad filetype for object file. Currently only tested for MH_OBJECT.\n");
81+ goto bail;
82+ }
83+
84+ for (i = 0; i < header.ncmds; i++)
85+ {
86+ struct load_command lc;
87+ struct symtab_command sc;
88+ struct segment_command seg_c;
89+
90+ memcpy(&lc, buf, sizeof(struct load_command));
91+
92+ if (lc.cmd == LC_SEGMENT)
93+ {
94+ uint8_t *seg_buf = buf;
95+ struct section s;
96+
97+ memcpy(&seg_c, buf, sizeof(struct segment_command));
98+
99+ seg_buf += sizeof(struct segment_command);
100+
101+ for (j = 0; j < seg_c.nsects; j++)
102+ {
103+ memcpy(&s, seg_buf + (j * sizeof(struct section)), sizeof(struct section));
104+
105+ // Need to get this offset which is the start of the symbol table
106+ // before matching the strings up with symbols.
107+ base_data_section = s.offset;
108+ }
109+ }
110+ else if (lc.cmd == LC_SYMTAB)
111+ {
112+ uint8_t *sym_buf = base_buf;
113+ uint8_t *str_buf = base_buf;
114+
115+ if (base_data_section != 0)
116+ {
117+ memcpy(&sc, buf, sizeof(struct symtab_command));
118+
119+ if (sc.cmdsize != sizeof(struct symtab_command))
120+ log_msg("Can't find symbol table!\n");
121+
122+ sym_buf += sc.symoff;
123+ str_buf += sc.stroff;
124+
125+ for (j = 0; j < sc.nsyms; j++)
126+ {
127+ struct nlist nl;
128+ int val;
129+
130+ memcpy(&nl, sym_buf + (j * sizeof(struct nlist)), sizeof(struct nlist));
131+
132+ val = *((int *)(base_buf + base_data_section + nl.n_value));
133+
134+ // Location of string is cacluated each time from the
135+ // start of the string buffer. On darwin the symbols
136+ // are prefixed by "_". On other platforms it is not
137+ // so it needs to be removed. That is the reason for
138+ // the +1.
139+ printf("%-40s EQU %5d\n", str_buf + nl.n_un.n_strx + 1, val);
140+ }
141+ }
142+ }
143+
144+ buf += lc.cmdsize;
145+ }
146+
147+ return 0;
148+bail:
149+ return 1;
150+
151+}
152+
153+int main(int argc, char **argv)
154+{
155+ int fd;
156+ char *f;
157+ struct stat stat_buf;
158+ uint8_t *file_buf;
159+ int res;
160+
161+ if (argc < 2 || argc > 3)
162+ {
163+ fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
164+ fprintf(stderr, " <obj file>\tMachO format object file to parse\n");
165+ fprintf(stderr, "Output Formats:\n");
166+ fprintf(stderr, " gas - compatible with GNU assembler\n");
167+ fprintf(stderr, " rvds - compatible with armasm\n");
168+ goto bail;
169+ }
170+
171+ f = argv[2];
172+
173+ if (!((!strcmp(argv[1], "rvds")) || (!strcmp(argv[1], "gas"))))
174+ f = argv[1];
175+
176+ fd = open(f, O_RDONLY);
177+
178+ if (fd < 0)
179+ {
180+ perror("Unable to open file");
181+ goto bail;
182+ }
183+
184+ if (fstat(fd, &stat_buf))
185+ {
186+ perror("stat");
187+ goto bail;
188+ }
189+
190+ file_buf = malloc(stat_buf.st_size);
191+
192+ if (!file_buf)
193+ {
194+ perror("malloc");
195+ goto bail;
196+ }
197+
198+ if (read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
199+ {
200+ perror("read");
201+ goto bail;
202+ }
203+
204+ if (close(fd))
205+ {
206+ perror("close");
207+ goto bail;
208+ }
209+
210+ res = parse_macho(file_buf, stat_buf.st_size);
211+ free(file_buf);
212+
213+ if (!res)
214+ return EXIT_SUCCESS;
215+
216+bail:
217+ return EXIT_FAILURE;
218+}
219+
220+#else
221+#include "elf.h"
222+
223+#define COPY_STRUCT(dst, buf, ofst, sz) do {\
224+ if(ofst + sizeof((*(dst))) > sz) goto bail;\
225+ memcpy(dst, buf+ofst, sizeof((*(dst))));\
226+ } while(0)
227+
228+#define ENDIAN_ASSIGN(val, memb) do {\
229+ if(!elf->le_data) {log_msg("Big Endian data not supported yet!\n");goto bail;}\
230+ (val) = (memb);\
231+ } while(0)
232+
233+#define ENDIAN_ASSIGN_IN_PLACE(memb) do {\
234+ ENDIAN_ASSIGN(memb, memb);\
235+ } while(0)
236+
237+typedef struct
238+{
239+ uint8_t *buf; /* Buffer containing ELF data */
240+ size_t sz; /* Buffer size */
241+ int le_data; /* Data is little-endian */
242+ Elf32_Ehdr hdr;
243+} elf_obj_t;
244+
245+int parse_elf32_header(elf_obj_t *elf)
246+{
247+ int res;
248+ /* Verify ELF32 header */
249+ COPY_STRUCT(&elf->hdr, elf->buf, 0, elf->sz);
250+ res = elf->hdr.e_ident[EI_MAG0] == ELFMAG0;
251+ res &= elf->hdr.e_ident[EI_MAG1] == ELFMAG1;
252+ res &= elf->hdr.e_ident[EI_MAG2] == ELFMAG2;
253+ res &= elf->hdr.e_ident[EI_MAG3] == ELFMAG3;
254+ res &= elf->hdr.e_ident[EI_CLASS] == ELFCLASS32;
255+ res &= elf->hdr.e_ident[EI_DATA] == ELFDATA2LSB
256+ || elf->hdr.e_ident[EI_DATA] == ELFDATA2MSB;
257+
258+ if (!res) goto bail;
259+
260+ elf->le_data = elf->hdr.e_ident[EI_DATA] == ELFDATA2LSB;
261+
262+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_type);
263+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_machine);
264+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_version);
265+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_entry);
266+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phoff);
267+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shoff);
268+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_flags);
269+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_ehsize);
270+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phentsize);
271+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_phnum);
272+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shentsize);
273+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shnum);
274+ ENDIAN_ASSIGN_IN_PLACE(elf->hdr.e_shstrndx);
275+ return 0;
276+bail:
277+ return 1;
278+}
279+
280+int parse_elf32_section(elf_obj_t *elf, int idx, Elf32_Shdr *hdr)
281+{
282+ if (idx >= elf->hdr.e_shnum)
283+ goto bail;
284+
285+ COPY_STRUCT(hdr, elf->buf, elf->hdr.e_shoff + idx * elf->hdr.e_shentsize,
286+ elf->sz);
287+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_name);
288+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_type);
289+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_flags);
290+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_addr);
291+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_offset);
292+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_size);
293+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_link);
294+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_info);
295+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_addralign);
296+ ENDIAN_ASSIGN_IN_PLACE(hdr->sh_entsize);
297+ return 0;
298+bail:
299+ return 1;
300+}
301+
302+char *parse_elf32_string_table(elf_obj_t *elf, int s_idx, int idx)
303+{
304+ Elf32_Shdr shdr;
305+
306+ if (parse_elf32_section(elf, s_idx, &shdr))
307+ {
308+ log_msg("Failed to parse ELF string table: section %d, index %d\n",
309+ s_idx, idx);
310+ return "";
311+ }
312+
313+ return (char *)(elf->buf + shdr.sh_offset + idx);
314+}
315+
316+int parse_elf32_symbol(elf_obj_t *elf, unsigned int ofst, Elf32_Sym *sym)
317+{
318+ COPY_STRUCT(sym, elf->buf, ofst, elf->sz);
319+ ENDIAN_ASSIGN_IN_PLACE(sym->st_name);
320+ ENDIAN_ASSIGN_IN_PLACE(sym->st_value);
321+ ENDIAN_ASSIGN_IN_PLACE(sym->st_size);
322+ ENDIAN_ASSIGN_IN_PLACE(sym->st_info);
323+ ENDIAN_ASSIGN_IN_PLACE(sym->st_other);
324+ ENDIAN_ASSIGN_IN_PLACE(sym->st_shndx);
325+ return 0;
326+bail:
327+ return 1;
328+}
329+
330+int parse_elf32(uint8_t *buf, size_t sz, output_fmt_t mode)
331+{
332+ elf_obj_t elf;
333+ Elf32_Shdr shdr;
334+ unsigned int ofst;
335+ int i;
336+ Elf32_Off strtab_off; /* save String Table offset for later use */
337+
338+ memset(&elf, 0, sizeof(elf));
339+ elf.buf = buf;
340+ elf.sz = sz;
341+
342+ /* Parse Header */
343+ if (parse_elf32_header(&elf))
344+ {
345+ log_msg("Parse error: File does not appear to be valid ELF32\n");
346+ return 1;
347+ }
348+
349+ for (i = 0; i < elf.hdr.e_shnum; i++)
350+ {
351+ parse_elf32_section(&elf, i, &shdr);
352+
353+ if (shdr.sh_type == SHT_STRTAB)
354+ {
355+ char strtsb_name[128];
356+
357+ strcpy(strtsb_name, (char *)(elf.buf + shdr.sh_offset + shdr.sh_name));
358+
359+ if (!(strcmp(strtsb_name, ".shstrtab")))
360+ {
361+ log_msg("found section: %s\n", strtsb_name);
362+ strtab_off = shdr.sh_offset;
363+ break;
364+ }
365+ }
366+ }
367+
368+ /* Parse all Symbol Tables */
369+ for (i = 0; i < elf.hdr.e_shnum; i++)
370+ {
371+
372+ parse_elf32_section(&elf, i, &shdr);
373+
374+ if (shdr.sh_type == SHT_SYMTAB)
375+ {
376+ for (ofst = shdr.sh_offset;
377+ ofst < shdr.sh_offset + shdr.sh_size;
378+ ofst += shdr.sh_entsize)
379+ {
380+ Elf32_Sym sym;
381+
382+ parse_elf32_symbol(&elf, ofst, &sym);
383+
384+ /* For all OBJECTS (data objects), extract the value from the
385+ * proper data segment.
386+ */
387+ if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT && sym.st_name)
388+ log_msg("found data object %s\n",
389+ parse_elf32_string_table(&elf,
390+ shdr.sh_link,
391+ sym.st_name));
392+
393+ if (ELF32_ST_TYPE(sym.st_info) == STT_OBJECT
394+ && sym.st_size == 4)
395+ {
396+ Elf32_Shdr dhdr;
397+ int32_t val;
398+ char section_name[128];
399+
400+ parse_elf32_section(&elf, sym.st_shndx, &dhdr);
401+
402+ /* For explanition - refer to _MSC_VER version of code */
403+ strcpy(section_name, (char *)(elf.buf + strtab_off + dhdr.sh_name));
404+ log_msg("Section_name: %s, Section_type: %d\n", section_name, dhdr.sh_type);
405+
406+ if (!(strcmp(section_name, ".bss")))
407+ {
408+ val = 0;
409+ }
410+ else
411+ {
412+ memcpy(&val,
413+ elf.buf + dhdr.sh_offset + sym.st_value,
414+ sizeof(val));
415+ }
416+
417+ if (!elf.le_data)
418+ {
419+ log_msg("Big Endian data not supported yet!\n");
420+ goto bail;
421+ }\
422+
423+ switch (mode)
424+ {
425+ case OUTPUT_FMT_RVDS:
426+ printf("%-40s EQU %5d\n",
427+ parse_elf32_string_table(&elf,
428+ shdr.sh_link,
429+ sym.st_name),
430+ val);
431+ break;
432+ case OUTPUT_FMT_GAS:
433+ printf(".equ %-40s, %5d\n",
434+ parse_elf32_string_table(&elf,
435+ shdr.sh_link,
436+ sym.st_name),
437+ val);
438+ break;
439+ default:
440+ printf("%s = %d\n",
441+ parse_elf32_string_table(&elf,
442+ shdr.sh_link,
443+ sym.st_name),
444+ val);
445+ }
446+ }
447+ }
448+ }
449+ }
450+
451+ if (mode == OUTPUT_FMT_RVDS)
452+ printf(" END\n");
453+
454+ return 0;
455+bail:
456+ log_msg("Parse error: File does not appear to be valid ELF32\n");
457+ return 1;
458+}
459+
460+int main(int argc, char **argv)
461+{
462+ int fd;
463+ output_fmt_t mode;
464+ char *f;
465+ struct stat stat_buf;
466+ uint8_t *file_buf;
467+ int res;
468+
469+ if (argc < 2 || argc > 3)
470+ {
471+ fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
472+ fprintf(stderr, " <obj file>\tELF format object file to parse\n");
473+ fprintf(stderr, "Output Formats:\n");
474+ fprintf(stderr, " gas - compatible with GNU assembler\n");
475+ fprintf(stderr, " rvds - compatible with armasm\n");
476+ goto bail;
477+ }
478+
479+ f = argv[2];
480+
481+ if (!strcmp(argv[1], "rvds"))
482+ mode = OUTPUT_FMT_RVDS;
483+ else if (!strcmp(argv[1], "gas"))
484+ mode = OUTPUT_FMT_GAS;
485+ else
486+ f = argv[1];
487+
488+
489+ fd = open(f, O_RDONLY);
490+
491+ if (fd < 0)
492+ {
493+ perror("Unable to open file");
494+ goto bail;
495+ }
496+
497+ if (fstat(fd, &stat_buf))
498+ {
499+ perror("stat");
500+ goto bail;
501+ }
502+
503+ file_buf = malloc(stat_buf.st_size);
504+
505+ if (!file_buf)
506+ {
507+ perror("malloc");
508+ goto bail;
509+ }
510+
511+ if (read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
512+ {
513+ perror("read");
514+ goto bail;
515+ }
516+
517+ if (close(fd))
518+ {
519+ perror("close");
520+ goto bail;
521+ }
522+
523+ res = parse_elf32(file_buf, stat_buf.st_size, mode);
524+ //res = parse_coff(file_buf, stat_buf.st_size);
525+ free(file_buf);
526+
527+ if (!res)
528+ return EXIT_SUCCESS;
529+
530+bail:
531+ return EXIT_FAILURE;
532+}
533+#endif
534+#endif
535+
536+
537+#if defined(_MSC_VER)
538+/* See "Microsoft Portable Executable and Common Object File Format Specification"
539+ for reference.
540+*/
541+#define get_le32(x) ((*(x)) | (*(x+1)) << 8 |(*(x+2)) << 16 | (*(x+3)) << 24 )
542+#define get_le16(x) ((*(x)) | (*(x+1)) << 8)
543+
544+int parse_coff(unsigned __int8 *buf, size_t sz)
545+{
546+ unsigned int nsections, symtab_ptr, symtab_sz, strtab_ptr;
547+ unsigned int sectionrawdata_ptr;
548+ unsigned int i;
549+ unsigned __int8 *ptr;
550+ unsigned __int32 symoffset;
551+ FILE *fp;
552+
553+ char **sectionlist; //this array holds all section names in their correct order.
554+ //it is used to check if the symbol is in .bss or .data section.
555+
556+ nsections = get_le16(buf + 2);
557+ symtab_ptr = get_le32(buf + 8);
558+ symtab_sz = get_le32(buf + 12);
559+ strtab_ptr = symtab_ptr + symtab_sz * 18;
560+
561+ if (nsections > 96)
562+ goto bail;
563+
564+ sectionlist = malloc(nsections * sizeof * sectionlist);
565+
566+ //log_msg("COFF: Found %u symbols in %u sections.\n", symtab_sz, nsections);
567+
568+ /*
569+ The size of optional header is always zero for an obj file. So, the section header
570+ follows the file header immediately.
571+ */
572+
573+ ptr = buf + 20; //section header
574+
575+ for (i = 0; i < nsections; i++)
576+ {
577+ char sectionname[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
578+ strncpy(sectionname, ptr, 8);
579+ //log_msg("COFF: Parsing section %s\n",sectionname);
580+
581+ sectionlist[i] = malloc(strlen(sectionname) + 1);
582+ strcpy(sectionlist[i], sectionname);
583+
584+ if (!strcmp(sectionname, ".data")) sectionrawdata_ptr = get_le32(ptr + 20);
585+
586+ ptr += 40;
587+ }
588+
589+ //log_msg("COFF: Symbol table at offset %u\n", symtab_ptr);
590+ //log_msg("COFF: raw data pointer ofset for section .data is %u\n", sectionrawdata_ptr);
591+
592+ fp = fopen("vpx_asm_offsets.asm", "w");
593+
594+ if (fp == NULL)
595+ {
596+ perror("open file");
597+ goto bail;
598+ }
599+
600+ /* The compiler puts the data with non-zero offset in .data section, but puts the data with
601+ zero offset in .bss section. So, if the data in in .bss section, set offset=0.
602+ Note from Wiki: In an object module compiled from C, the bss section contains
603+ the local variables (but not functions) that were declared with the static keyword,
604+ except for those with non-zero initial values. (In C, static variables are initialized
605+ to zero by default.) It also contains the non-local (both extern and static) variables
606+ that are also initialized to zero (either explicitly or by default).
607+ */
608+ //move to symbol table
609+ /* COFF symbol table:
610+ offset field
611+ 0 Name(*)
612+ 8 Value
613+ 12 SectionNumber
614+ 14 Type
615+ 16 StorageClass
616+ 17 NumberOfAuxSymbols
617+ */
618+ ptr = buf + symtab_ptr;
619+
620+ for (i = 0; i < symtab_sz; i++)
621+ {
622+ __int16 section = get_le16(ptr + 12); //section number
623+
624+ if (section > 0 && ptr[16] == 2)
625+ {
626+ //if(section > 0 && ptr[16] == 3 && get_le32(ptr+8)) {
627+
628+ if (get_le32(ptr))
629+ {
630+ char name[9] = {0, 0, 0, 0, 0, 0, 0, 0, 0};
631+ strncpy(name, ptr, 8);
632+ //log_msg("COFF: Parsing symbol %s\n",name);
633+ fprintf(fp, "%-40s EQU ", name);
634+ }
635+ else
636+ {
637+ //log_msg("COFF: Parsing symbol %s\n",
638+ // buf + strtab_ptr + get_le32(ptr+4));
639+ fprintf(fp, "%-40s EQU ", buf + strtab_ptr + get_le32(ptr + 4));
640+ }
641+
642+ if (!(strcmp(sectionlist[section-1], ".bss")))
643+ {
644+ symoffset = 0;
645+ }
646+ else
647+ {
648+ symoffset = get_le32(buf + sectionrawdata_ptr + get_le32(ptr + 8));
649+ }
650+
651+ //log_msg(" Section: %d\n",section);
652+ //log_msg(" Class: %d\n",ptr[16]);
653+ //log_msg(" Address: %u\n",get_le32(ptr+8));
654+ //log_msg(" Offset: %u\n", symoffset);
655+
656+ fprintf(fp, "%5d\n", symoffset);
657+ }
658+
659+ ptr += 18;
660+ }
661+
662+ fprintf(fp, " END\n");
663+ fclose(fp);
664+
665+ for (i = 0; i < nsections; i++)
666+ {
667+ free(sectionlist[i]);
668+ }
669+
670+ free(sectionlist);
671+
672+ return 0;
673+bail:
674+
675+ for (i = 0; i < nsections; i++)
676+ {
677+ free(sectionlist[i]);
678+ }
679+
680+ free(sectionlist);
681+
682+ return 1;
683+}
684+
685+int main(int argc, char **argv)
686+{
687+ int fd;
688+ output_fmt_t mode;
689+ const char *f;
690+ struct _stat stat_buf;
691+ unsigned __int8 *file_buf;
692+ int res;
693+
694+ if (argc < 2 || argc > 3)
695+ {
696+ fprintf(stderr, "Usage: %s [output format] <obj file>\n\n", argv[0]);
697+ fprintf(stderr, " <obj file>\tELF format object file to parse\n");
698+ fprintf(stderr, "Output Formats:\n");
699+ fprintf(stderr, " gas - compatible with GNU assembler\n");
700+ fprintf(stderr, " rvds - compatible with armasm\n");
701+ goto bail;
702+ }
703+
704+ f = argv[2];
705+
706+ if (!strcmp(argv[1], "rvds"))
707+ mode = OUTPUT_FMT_RVDS;
708+ else if (!strcmp(argv[1], "gas"))
709+ mode = OUTPUT_FMT_GAS;
710+ else
711+ f = argv[1];
712+
713+ if (_sopen_s(&fd, f, _O_BINARY, _SH_DENYNO, _S_IREAD | _S_IWRITE))
714+ {
715+ perror("Unable to open file");
716+ goto bail;
717+ }
718+
719+ if (_fstat(fd, &stat_buf))
720+ {
721+ perror("stat");
722+ goto bail;
723+ }
724+
725+ file_buf = malloc(stat_buf.st_size);
726+
727+ if (!file_buf)
728+ {
729+ perror("malloc");
730+ goto bail;
731+ }
732+
733+ if (_read(fd, file_buf, stat_buf.st_size) != stat_buf.st_size)
734+ {
735+ perror("read");
736+ goto bail;
737+ }
738+
739+ if (_close(fd))
740+ {
741+ perror("close");
742+ goto bail;
743+ }
744+
745+ res = parse_coff(file_buf, stat_buf.st_size);
746+
747+ free(file_buf);
748+
749+ if (!res)
750+ return EXIT_SUCCESS;
751+
752+bail:
753+ return EXIT_FAILURE;
754+}
755+#endif
build/make/version.sh+75−0
@@ -0,0 +1,75 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+
13+for opt in "$@"; do
14+ optval="${opt#*=}"
15+ case "$opt" in
16+ --bare) bare=true ;;
17+ *) break ;;
18+ esac
19+ shift
20+done
21+source_path=${1:-.}
22+out_file=${2}
23+id=${3:-VERSION_STRING}
24+
25+git_version_id=""
26+if [ -d ${source_path}/.git ]; then
27+ # Source Path is a git working copy. Check for local modifications.
28+ export GIT_DIR=${source_path}/.git
29+ git_version_id=`git describe --match=v[0-9]* 2>/dev/null`
30+fi
31+
32+changelog_version=""
33+for p in "${source_path}" "${source_path}/.."; do
34+ if [ -z "$git_version_id" -a -f "${p}/CHANGELOG" ]; then
35+ changelog_version=`head -n1 "${p}/CHANGELOG" | awk '{print $2}'`
36+ changelog_version="${changelog_version}"
37+ break
38+ fi
39+done
40+version_str="${changelog_version}${git_version_id}"
41+bare_version=${version_str#v}
42+major_version=${bare_version%%.*}
43+bare_version=${bare_version#*.}
44+minor_version=${bare_version%%.*}
45+bare_version=${bare_version#*.}
46+patch_version=${bare_version%%-*}
47+bare_version=${bare_version#${patch_version}}
48+extra_version=${bare_version##-}
49+
50+#since they'll be used as integers below make sure they are or force to 0
51+for v in major_version minor_version patch_version; do
52+ if eval echo \$$v |grep -E -q '[^[:digit:]]'; then
53+ eval $v=0
54+ fi
55+done
56+
57+if [ ${bare} ]; then
58+ echo "${changelog_version}${git_version_id}" > $$.tmp
59+else
60+ cat<<EOF>$$.tmp
61+#define VERSION_MAJOR $major_version
62+#define VERSION_MINOR $minor_version
63+#define VERSION_PATCH $patch_version
64+#define VERSION_EXTRA "$extra_version"
65+#define VERSION_PACKED ((VERSION_MAJOR<<16)|(VERSION_MINOR<<8)|(VERSION_PATCH))
66+#define ${id}_NOSP "${version_str}"
67+#define ${id} " ${version_str}"
68+EOF
69+fi
70+if [ -n "$out_file" ]; then
71+diff $$.tmp ${out_file} >/dev/null 2>&1 || cat $$.tmp > ${out_file}
72+else
73+cat $$.tmp
74+fi
75+rm $$.tmp
configure+515−0
@@ -0,0 +1,515 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+#source_path="`dirname \"$0\"`"
13+source_path=${0%/*}
14+. "${source_path}/build/make/configure.sh"
15+
16+show_help(){
17+ show_help_pre
18+ cat << EOF
19+Advanced options:
20+ ${toggle_libs} don't build libraries
21+ ${toggle_examples} don't build examples
22+ --libc=PATH path to alternate libc
23+ ${toggle_fast_unaligned} don't use unaligned accesses, even when
24+ supported by hardware [auto]
25+ ${toggle_codec_srcs} in/exclude codec library source code
26+ ${toggle_debug_libs} in/exclude debug version of libraries
27+ ${toggle_eval_limit} enable limited evaluation build
28+ ${toggle_md5} support for output of checksum data
29+ ${toggle_static_msvcrt} use static MSVCRT (VS builds only)
30+ ${toggle_vp8} VP8 codec support
31+ ${toggle_psnr} output of PSNR data, if supported (encoders)
32+ ${toggle_mem_tracker} track memory usage
33+ ${toggle_eval_limit} decoder limitted to 500 frames
34+ ${toggle_postproc} postprocessing
35+ ${toggle_multithread} multithreaded encoding and decoding.
36+ ${toggle_spatial_resampling} spatial sampling (scaling) support
37+ ${toggle_realtime_only} enable this option while building for real-time encoding
38+ ${toggle_runtime_cpu_detect} runtime cpu detection
39+
40+Codecs:
41+ Codecs can be selectively enabled or disabled individually, or by family:
42+ --disable-<codec>
43+ is equivalent to:
44+ --disable-<codec>-encoder
45+ --disable-<codec>-decoder
46+
47+ Codecs available in this distribution:
48+EOF
49+#restore editor state '
50+
51+ local family;
52+ local last_family;
53+ local c;
54+ local str;
55+ for c in ${CODECS}; do
56+ family=${c%_*}
57+ if [ "${family}" != "${last_family}" ]; then
58+ [ -z "${str}" ] || echo "${str}"
59+ str="$(printf ' %10s:' ${family})"
60+ fi
61+ str="${str} $(printf '%10s' ${c#*_})"
62+ last_family=${family}
63+ done
64+ echo "${str}"
65+ show_help_post
66+}
67+
68+##
69+## BEGIN APPLICATION SPECIFIC CONFIGURATION
70+##
71+
72+# all_platforms is a list of all supported target platforms. Maintain
73+# alphabetically by architecture, generic-gnu last.
74+all_platforms="${all_platforms} armv5te-linux-rvct"
75+all_platforms="${all_platforms} armv5te-linux-gcc"
76+all_platforms="${all_platforms} armv5te-symbian-gcc"
77+all_platforms="${all_platforms} armv5te-wince-vs8"
78+all_platforms="${all_platforms} armv6-darwin-gcc"
79+all_platforms="${all_platforms} armv6-linux-rvct"
80+all_platforms="${all_platforms} armv6-linux-gcc"
81+all_platforms="${all_platforms} armv6-symbian-gcc"
82+all_platforms="${all_platforms} armv6-wince-vs8"
83+all_platforms="${all_platforms} iwmmxt-linux-rvct"
84+all_platforms="${all_platforms} iwmmxt-linux-gcc"
85+all_platforms="${all_platforms} iwmmxt-wince-vs8"
86+all_platforms="${all_platforms} iwmmxt2-linux-rvct"
87+all_platforms="${all_platforms} iwmmxt2-linux-gcc"
88+all_platforms="${all_platforms} iwmmxt2-wince-vs8"
89+all_platforms="${all_platforms} armv7-darwin-gcc" #neon Cortex-A8
90+all_platforms="${all_platforms} armv7-linux-rvct" #neon Cortex-A8
91+all_platforms="${all_platforms} armv7-linux-gcc" #neon Cortex-A8
92+all_platforms="${all_platforms} mips32-linux-gcc"
93+all_platforms="${all_platforms} ppc32-darwin8-gcc"
94+all_platforms="${all_platforms} ppc32-darwin9-gcc"
95+all_platforms="${all_platforms} ppc64-darwin8-gcc"
96+all_platforms="${all_platforms} ppc64-darwin9-gcc"
97+all_platforms="${all_platforms} ppc64-linux-gcc"
98+all_platforms="${all_platforms} x86-darwin8-gcc"
99+all_platforms="${all_platforms} x86-darwin8-icc"
100+all_platforms="${all_platforms} x86-darwin9-gcc"
101+all_platforms="${all_platforms} x86-darwin9-icc"
102+all_platforms="${all_platforms} x86-linux-gcc"
103+all_platforms="${all_platforms} x86-linux-icc"
104+all_platforms="${all_platforms} x86-solaris-gcc"
105+all_platforms="${all_platforms} x86-win32-gcc"
106+all_platforms="${all_platforms} x86-win32-vs7"
107+all_platforms="${all_platforms} x86-win32-vs8"
108+all_platforms="${all_platforms} x86_64-darwin9-gcc"
109+all_platforms="${all_platforms} x86_64-linux-gcc"
110+all_platforms="${all_platforms} x86_64-solaris-gcc"
111+all_platforms="${all_platforms} x86_64-win64-vs8"
112+all_platforms="${all_platforms} universal-darwin8-gcc"
113+all_platforms="${all_platforms} universal-darwin9-gcc"
114+all_platforms="${all_platforms} generic-gnu"
115+
116+# all_targets is a list of all targets that can be configured
117+# note that these should be in dependency order for now.
118+all_targets="libs examples docs"
119+
120+# all targets available are enabled, by default.
121+for t in ${all_targets}; do
122+ [ -f ${source_path}/${t}.mk ] && enable ${t}
123+done
124+
125+# check installed doxygen version
126+doxy_version=$(doxygen --version 2>/dev/null)
127+doxy_major=${doxy_version%%.*}
128+if [ ${doxy_major:-0} -ge 1 ]; then
129+ doxy_version=${doxy_version#*.}
130+ doxy_minor=${doxy_version%%.*}
131+ doxy_patch=${doxy_version##*.}
132+
133+ [ $doxy_major -gt 1 ] && enable doxygen
134+ [ $doxy_minor -gt 5 ] && enable doxygen
135+ [ $doxy_minor -eq 5 ] && [ $doxy_patch -ge 3 ] && enable doxygen
136+fi
137+
138+# install everything, by default
139+enabled doxygen && php -v >/dev/null 2>&1 && enable install_docs
140+enable install_bins
141+enable install_libs
142+enable install_srcs
143+
144+enable optimizations
145+enable fast_unaligned #allow unaligned accesses, if supported by hw
146+enable md5
147+enable spatial_resampling
148+enable multithread
149+
150+[ -d ${source_path}/../include ] && enable alt_tree_layout
151+for d in vp8; do
152+ [ -d ${source_path}/${d} ] && disable alt_tree_layout;
153+done
154+
155+if ! enabled alt_tree_layout; then
156+# development environment
157+[ -d ${source_path}/vp8 ] && CODECS="${CODECS} vp8_encoder vp8_decoder"
158+else
159+# customer environment
160+[ -f ${source_path}/../include/vp8cx.h ] && CODECS="${CODECS} vp8_encoder"
161+[ -f ${source_path}/../include/vp8dx.h ] && CODECS="${CODECS} vp8_decoder"
162+
163+[ -f ${source_path}/../lib/*/*mt.lib ] && soft_enable static_msvcrt
164+fi
165+
166+CODECS="$(echo ${CODECS} | tr ' ' '\n')"
167+CODEC_FAMILIES="$(for c in ${CODECS}; do echo ${c%_*}; done | sort | uniq)"
168+
169+ARCH_LIST="
170+ arm
171+ mips
172+ x86
173+ x86_64
174+ ppc32
175+ ppc64
176+"
177+ARCH_EXT_LIST="
178+ armv5te
179+ armv6
180+ armv7
181+ iwmmxt
182+ iwmmxt2
183+
184+ mips32
185+
186+ mmx
187+ sse
188+ sse2
189+ sse3
190+ ssse3
191+
192+ altivec
193+"
194+HAVE_LIST="
195+ ${ARCH_EXT_LIST}
196+ vpx_ports
197+ stdint_h
198+ alt_tree_layout
199+ pthread_h
200+ sys_mman_h
201+"
202+CONFIG_LIST="
203+ external_build
204+ install_docs
205+ install_bins
206+ install_libs
207+ install_srcs
208+ debug
209+ gprof
210+ gcov
211+ rvct
212+ gcc
213+ msvs
214+ pic
215+ big_endian
216+
217+ codec_srcs
218+ debug_libs
219+ fast_unaligned
220+ mem_manager
221+ mem_tracker
222+ mem_checks
223+ md5
224+
225+ dequant_tokens
226+ dc_recon
227+ new_tokens
228+ eval_limit
229+ runtime_cpu_detect
230+ postproc
231+ postproc_generic
232+ multithread
233+ psnr
234+ ${CODECS}
235+ ${CODEC_FAMILIES}
236+ encoders
237+ decoders
238+ static_msvcrt
239+ spatial_resampling
240+ realtime_only
241+"
242+CMDLINE_SELECT="
243+ extra_warnings
244+ werror
245+ install_docs
246+ install_bins
247+ install_libs
248+ install_srcs
249+ debug
250+ gprof
251+ gcov
252+ pic
253+ optimizations
254+ ccache
255+ runtime_cpu_detect
256+
257+ libs
258+ examples
259+ libc
260+ fast_unaligned
261+ codec_srcs
262+ debug_libs
263+ md5
264+
265+ dequant_tokens
266+ dc_recon
267+ new_tokens
268+ eval_limit
269+ postproc
270+ postproc_generic
271+ multithread
272+ psnr
273+ ${CODECS}
274+ ${CODEC_FAMILIES}
275+ static_msvcrt
276+ mem_tracker
277+ spatial_resampling
278+ realtime_only
279+"
280+
281+process_cmdline() {
282+ for opt do
283+ optval="${opt#*=}"
284+ case "$opt" in
285+ --disable-codecs) for c in ${CODECS}; do disable $c; done ;;
286+ *) process_common_cmdline $opt
287+ ;;
288+ esac
289+ done
290+}
291+
292+post_process_cmdline() {
293+ local c
294+
295+ # If the codec family is disabled, disable all components of that family.
296+ # If the codec family is enabled, enable all components of that family.
297+ log_echo "Configuring selected codecs"
298+ for c in ${CODECS}; do
299+ disabled ${c%%_*} && disable ${c}
300+ enabled ${c%%_*} && enable ${c}
301+ done
302+
303+ # Enable all detected codecs, if they haven't been disabled
304+ for c in ${CODECS}; do soft_enable $c; done
305+
306+ # Enable the codec family if any component of that family is enabled
307+ for c in ${CODECS}; do
308+ enabled $c && enable ${c%_*}
309+ done
310+
311+ # Set the {en,de}coders variable if any algorithm in that class is enabled
312+ for c in ${CODECS}; do
313+ enabled ${c} && enable ${c##*_}s
314+ done
315+
316+
317+}
318+
319+
320+process_targets() {
321+ enabled child || write_common_config_banner
322+ enabled universal || write_common_target_config_h ${BUILD_PFX}vpx_config.h
323+
324+ # TODO: add host tools target (obj_int_extract, etc)
325+
326+ # For fat binaries, call configure recursively to configure for each
327+ # binary architecture to be included.
328+ if enabled universal; then
329+ # Call configure (ourselves) for each subarchitecture
330+ for arch in $fat_bin_archs; do
331+ BUILD_PFX=${arch}/ toolchain=${arch} $self --child $cmdline_args || exit $?
332+ done
333+ fi
334+
335+ # The write_common_config (config.mk) logic is deferred until after the
336+ # recursive calls to configure complete, becuase we want our universal
337+ # targets to be executed last.
338+ write_common_config_targets
339+ enabled universal && echo "FAT_ARCHS=${fat_bin_archs}" >> config.mk
340+
341+ # Calculate the default distribution name, based on the enabled features
342+ local cf
343+ local DIST_DIR=vpx
344+ for cf in $CODEC_FAMILIES; do
345+ if enabled ${cf}_encoder && enabled ${cf}_decoder; then
346+ DIST_DIR="${DIST_DIR}-${cf}"
347+ elif enabled ${cf}_encoder; then
348+ DIST_DIR="${DIST_DIR}-${cf}cx"
349+ elif enabled ${cf}_decoder; then
350+ DIST_DIR="${DIST_DIR}-${cf}dx"
351+ fi
352+ done
353+ enabled debug_libs && DIST_DIR="${DIST_DIR}-debug"
354+ enabled codec_srcs && DIST_DIR="${DIST_DIR}-src"
355+ ! enabled postproc && DIST_DIR="${DIST_DIR}-nopost"
356+ ! enabled multithread && DIST_DIR="${DIST_DIR}-nomt"
357+ enabled eval_limit && DIST_DIR="${DIST_DIR}-eval"
358+ ! enabled install_docs && DIST_DIR="${DIST_DIR}-nodocs"
359+ DIST_DIR="${DIST_DIR}-${tgt_isa}-${tgt_os}"
360+ case "${tgt_os}" in
361+ win*) enabled static_msvcrt && DIST_DIR="${DIST_DIR}mt" || DIST_DIR="${DIST_DIR}md"
362+ DIST_DIR="${DIST_DIR}-${tgt_cc}"
363+ ;;
364+ esac
365+ if [ -f "${source_path}/build/make/version.sh" ]; then
366+ local ver=`"$source_path/build/make/version.sh" --bare $source_path`
367+ DIST_DIR="${DIST_DIR}-${ver}"
368+ fi
369+ enabled child || echo "DIST_DIR?=${DIST_DIR}" >> config.mk
370+ enabled child || echo "CONFIGURE_ARGS?=${CONFIGURE_ARGS}" >> config.mk
371+
372+ #
373+ # Write makefiles for all enabled targets
374+ #
375+ for tgt in libs examples docs solution; do
376+ local tgt_fn="$tgt-$toolchain.mk"
377+
378+ if enabled $tgt; then
379+ echo "Creating makefiles for ${toolchain} ${tgt}"
380+ write_common_target_config_mk $tgt_fn ${BUILD_PFX}vpx_config.h
381+ #write_${tgt}_config
382+ fi
383+ done
384+
385+}
386+
387+process_detect() {
388+ if [ -z "$CC" ]; then
389+ echo "Bypassing toolchain for environment detection."
390+ enable external_build
391+ check_header() {
392+ log fake_check_header "$@"
393+ header=$1
394+ shift
395+ var=`echo $header | sed 's/[^A-Za-z0-9_]/_/g'`
396+ disable $var
397+ case $header in
398+ stdio.h)
399+ true;
400+ ;;
401+ *)
402+ local result=false
403+ for d in "$@"; do
404+ [ -f "${d##-I}/$header" ] && result=true && break
405+ done
406+ ${result:-true}
407+ esac && enable $var
408+ }
409+ check_ld() {
410+ true
411+ }
412+ fi
413+ check_header stdio.h || die "Unable to invoke compiler: ${CC} ${CFLAGS}"
414+ check_ld <<EOF || die "Toolchain is unable to link executables"
415+int main(void) {return 0;}
416+EOF
417+ # check system headers
418+ check_header stdint.h
419+ check_header pthread.h
420+ check_header sys/mman.h
421+
422+ check_header vpx_ports/vpx_integer.h -I${source_path} && enable vpx_ports
423+}
424+
425+process_toolchain() {
426+ process_common_toolchain
427+
428+ # Handle universal binaries for this architecture
429+ case $toolchain in
430+ universal-darwin*)
431+ local darwin_ver=${tgt_os##darwin}
432+ fat_bin_archs="$fat_bin_archs ppc32-${tgt_os}-gcc"
433+
434+ # Intel
435+ fat_bin_archs="$fat_bin_archs x86-${tgt_os}-${tgt_cc}"
436+ if [ $darwin_ver -gt 8 ]; then
437+ fat_bin_archs="$fat_bin_archs x86_64-${tgt_os}-${tgt_cc}"
438+ fi
439+ ;;
440+ esac
441+
442+
443+ # Enable some useful compiler flags
444+ if enabled gcc; then
445+ enabled werror && check_add_cflags -Werror
446+ check_add_cflags -Wall
447+ check_add_cflags -Wdeclaration-after-statement
448+ check_add_cflags -Wdisabled-optimization
449+ check_add_cflags -Wpointer-arith
450+ check_add_cflags -Wtype-limits
451+ check_add_cflags -Wcast-qual
452+ enabled extra_warnings || check_add_cflags -Wno-unused
453+ fi
454+
455+ if enabled icc; then
456+ enabled werror && check_add_cflags -Werror
457+ check_add_cflags -Wall
458+ check_add_cflags -Wpointer-arith
459+
460+ # ICC has a number of floating point optimizations that we disable
461+ # in favor of deterministic output WRT to other compilers
462+ add_cflags -fp-model precise
463+ fi
464+
465+ # Enable extra, harmless warnings. These might provide additional insight
466+ # to what the compiler is doing and why, but in general, but they shouldn't
467+ # be treated as fatal, even if we're treating warnings as errors.
468+ GCC_EXTRA_WARNINGS="
469+ -Wdisabled-optimization
470+ -Winline
471+ "
472+ enabled gcc && EXTRA_WARNINGS="${GCC_EXTRA_WARNINGS}"
473+ RVCT_EXTRA_WARNINGS="
474+ --remarks
475+ "
476+ enabled rvct && EXTRA_WARNINGS="${RVCT_EXTRA_WARNINGS}"
477+ if enabled extra_warnings; then
478+ for w in ${EXTRA_WARNINGS}; do
479+ check_add_cflags ${w}
480+ enabled gcc && enabled werror && check_add_cflags -Wno-error=${w}
481+ done
482+ fi
483+
484+ # ccache only really works on gcc toolchains
485+ enabled gcc || soft_disable ccache
486+ if enabled mips; then
487+ enable dequant_tokens
488+ enable dc_recon
489+ fi
490+
491+ # Enable the postbuild target if building for visual studio.
492+ case "$tgt_cc" in
493+ vs*) enable msvs
494+ enable solution
495+ vs_version=${tgt_cc##vs}
496+ all_targets="${all_targets} solution"
497+ INLINE=__inline
498+ FORCEINLINE=__forceinline
499+ ;;
500+ esac
501+
502+ # Other toolchain specific defaults
503+ case $toolchain in x86*|ppc*|universal*) soft_enable postproc;; esac
504+}
505+
506+
507+##
508+## END APPLICATION SPECIFIC CONFIGURATION
509+##
510+CONFIGURE_ARGS="$@"
511+process "$@"
512+cat <<EOF > ${BUILD_PFX}vpx_config.c
513+static const char* const cfg = "$CONFIGURE_ARGS";
514+const char *vpx_codec_build_config(void) {return cfg;}
515+EOF
docs.mk+54−0
@@ -0,0 +1,54 @@
1+##
2+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+##
4+## Use of this source code is governed by a BSD-style license and patent
5+## grant that can be found in the LICENSE file in the root of the source
6+## tree. All contributing project authors may be found in the AUTHORS
7+## file in the root of the source tree.
8+##
9+
10+
11+INSTALL_MAPS += docs/% docs/%
12+INSTALL_MAPS += src/% %
13+INSTALL_MAPS += % %
14+
15+# Static documentation authored in doxygen
16+CODEC_DOX := mainpage.dox \
17+ keywords.dox \
18+ usage.dox \
19+ usage_cx.dox \
20+ usage_dx.dox \
21+
22+# Other doxy files sourced in Markdown
23+TXT_DOX-$(CONFIG_VP8) += vp8_api1_migration.dox
24+vp8_api1_migration.dox.DESC = VP8 API 1.x Migration
25+
26+TXT_DOX = $(call enabled,TXT_DOX)
27+
28+%.dox: %.txt
29+ @echo " [DOXY] $@"
30+ @$(SRC_PATH_BARE)/examples/gen_example_doxy.php \
31+ $(@:.dox=) "$($@.DESC)" > $@ < $<
32+
33+
34+EXAMPLE_PATH += $(SRC_PATH_BARE) #for CHANGELOG, README, etc
35+
36+doxyfile: libs.doxy_template libs.doxy examples.doxy
37+ @echo " [CREATE] $@"
38+ @cat $^ > $@
39+ @echo "STRIP_FROM_PATH += $(SRC_PATH_BARE) $(BUILD_ROOT)" >> $@
40+ @echo "INPUT += $(addprefix $(SRC_PATH_BARE)/,$(CODEC_DOX))" >> $@;
41+ @echo "INPUT += $(TXT_DOX)" >> $@;
42+ @echo "EXAMPLE_PATH += $(EXAMPLE_PATH)" >> $@
43+
44+CLEAN-OBJS += doxyfile $(wildcard docs/html/*)
45+docs/html/index.html: doxyfile $(CODEC_DOX) $(TXT_DOX)
46+ @echo " [DOXYGEN] $<"
47+ @doxygen $<
48+DOCS-yes += docs/html/index.html
49+
50+INSTALL-DOCS-yes = $(wildcard docs/html/*)
51+INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += $(addprefix src/,$(CODEC_DOX))
52+INSTALL-DOCS-$(CONFIG_CODEC_SRCS) += src/libs.doxy_template
53+INSTALL-DOCS-yes += CHANGELOG
54+INSTALL-DOCS-yes += README
example_xma.c+213−0
@@ -0,0 +1,213 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+/* This is a simple program showing how to initialize the decoder in XMA mode */
12+#include <stdio.h>
13+#include <stdlib.h>
14+#include <stdarg.h>
15+#include <string.h>
16+#define VPX_CODEC_DISABLE_COMPAT 1
17+#include "vpx_config.h"
18+#include "vpx_decoder.h"
19+#include "vpx_integer.h"
20+#if CONFIG_VP8_DECODER
21+#include "vp8dx.h"
22+#endif
23+
24+static char *exec_name;
25+static int verbose = 0;
26+
27+static const struct
28+{
29+ const char *name;
30+ const vpx_codec_iface_t *iface;
31+} ifaces[] =
32+{
33+#if CONFIG_VP8_DECODER
34+ {"vp8", &vpx_codec_vp8_dx_algo},
35+#endif
36+};
37+
38+static void usage_exit(void)
39+{
40+ int i;
41+
42+ printf("Usage: %s <options>\n\n"
43+ "Options:\n"
44+ "\t--codec <name>\tCodec to use (default=%s)\n"
45+ "\t-h <height>\tHeight of the simulated video frame, in pixels\n"
46+ "\t-w <width> \tWidth of the simulated video frame, in pixels\n"
47+ "\t-v \tVerbose mode (show individual segment sizes)\n"
48+ "\t--help \tShow this message\n"
49+ "\n"
50+ "Included decoders:\n"
51+ "\n",
52+ exec_name,
53+ ifaces[0].name);
54+
55+ for (i = 0; i < sizeof(ifaces) / sizeof(ifaces[0]); i++)
56+ printf(" %-6s - %s\n",
57+ ifaces[i].name,
58+ vpx_codec_iface_name(ifaces[i].iface));
59+
60+ exit(EXIT_FAILURE);
61+}
62+
63+static void usage_error(const char *fmt, ...)
64+{
65+ va_list ap;
66+ va_start(ap, fmt);
67+ vprintf(fmt, ap);
68+ printf("\n");
69+ usage_exit();
70+}
71+
72+void my_mem_dtor(vpx_codec_mmap_t *mmap)
73+{
74+ if (verbose)
75+ printf("freeing segment %d\n", mmap->id);
76+
77+ free(mmap->priv);
78+}
79+
80+int main(int argc, char **argv)
81+{
82+ vpx_codec_ctx_t decoder;
83+ vpx_codec_iface_t *iface = ifaces[0].iface;
84+ vpx_codec_iter_t iter;
85+ vpx_codec_dec_cfg_t cfg;
86+ vpx_codec_err_t res = VPX_CODEC_OK;
87+ unsigned int alloc_sz = 0;
88+ unsigned int w = 352;
89+ unsigned int h = 288;
90+ int i;
91+
92+ exec_name = argv[0];
93+
94+ for (i = 1; i < argc; i++)
95+ {
96+ if (!strcmp(argv[i], "--codec"))
97+ {
98+ if (i + 1 < argc)
99+ {
100+ int j, k = -1;
101+
102+ i++;
103+
104+ for (j = 0; j < sizeof(ifaces) / sizeof(ifaces[0]); j++)
105+ if (!strcmp(ifaces[j].name, argv[i]))
106+ k = j;
107+
108+ if (k >= 0)
109+ iface = ifaces[k].iface;
110+ else
111+ usage_error("Error: Unrecognized argument (%s) to --codec\n",
112+ argv[i]);
113+ }
114+ else
115+ usage_error("Error: Option --codec requires argument.\n");
116+ }
117+ else if (!strcmp(argv[i], "-v"))
118+ verbose = 1;
119+ else if (!strcmp(argv[i], "-h"))
120+ if (i + 1 < argc)
121+ {
122+ h = atoi(argv[++i]);
123+ }
124+ else
125+ usage_error("Error: Option -h requires argument.\n");
126+ else if (!strcmp(argv[i], "-w"))
127+ if (i + 1 < argc)
128+ {
129+ w = atoi(argv[++i]);
130+ }
131+ else
132+ usage_error("Error: Option -w requires argument.\n");
133+ else if (!strcmp(argv[i], "--help"))
134+ usage_exit();
135+ else
136+ usage_error("Error: Unrecognized option %s\n\n", argv[i]);
137+ }
138+
139+ if (argc == 1)
140+ printf("Using built-in defaults. For options, rerun with --help\n\n");
141+
142+ /* XMA mode is not supported on all decoders! */
143+ if (!(vpx_codec_get_caps(iface) & VPX_CODEC_CAP_XMA))
144+ {
145+ printf("%s does not support XMA mode!\n", vpx_codec_iface_name(iface));
146+ return EXIT_FAILURE;
147+ }
148+
149+ /* The codec knows how much memory to allocate based on the size of the
150+ * encoded frames. This data can be parsed from the bitstream with
151+ * vpx_codec_peek_stream_info() if a bitstream is available. Otherwise,
152+ * a fixed size can be used that will be the upper limit on the frame
153+ * size the decoder can decode.
154+ */
155+ cfg.w = w;
156+ cfg.h = h;
157+
158+ /* Initialize the decoder in XMA mode. */
159+ if (vpx_codec_dec_init(&decoder, iface, &cfg, VPX_CODEC_USE_XMA))
160+ {
161+ printf("Failed to initialize decoder in XMA mode: %s\n", vpx_codec_error(&decoder));
162+ return EXIT_FAILURE;
163+ }
164+
165+ /* Iterate through the list of memory maps, allocating them with the
166+ * requested alignment.
167+ */
168+ iter = NULL;
169+
170+ do
171+ {
172+ vpx_codec_mmap_t mmap;
173+ unsigned int align;
174+
175+ res = vpx_codec_get_mem_map(&decoder, &mmap, &iter);
176+ align = mmap.align ? mmap.align - 1 : 0;
177+
178+ if (!res)
179+ {
180+ if (verbose)
181+ printf("Allocating segment %u, size %lu, align %u %s\n",
182+ mmap.id, mmap.sz, mmap.align,
183+ mmap.flags & VPX_CODEC_MEM_ZERO ? "(ZEROED)" : "");
184+
185+ if (mmap.flags & VPX_CODEC_MEM_ZERO)
186+ mmap.priv = calloc(1, mmap.sz + align);
187+ else
188+ mmap.priv = malloc(mmap.sz + align);
189+
190+ mmap.base = (void *)((((uintptr_t)mmap.priv) + align) & ~(uintptr_t)align);
191+ mmap.dtor = my_mem_dtor;
192+ alloc_sz += mmap.sz + align;
193+
194+ if (vpx_codec_set_mem_map(&decoder, &mmap, 1))
195+ {
196+ printf("Failed to set mmap: %s\n", vpx_codec_error(&decoder));
197+ return EXIT_FAILURE;
198+ }
199+ }
200+ else if (res != VPX_CODEC_LIST_END)
201+ {
202+ printf("Failed to get mmap: %s\n", vpx_codec_error(&decoder));
203+ return EXIT_FAILURE;
204+ }
205+ }
206+ while (res != VPX_CODEC_LIST_END);
207+
208+ printf("%s\n %d bytes external memory required for %dx%d.\n",
209+ decoder.name, alloc_sz, cfg.w, cfg.h);
210+ vpx_codec_destroy(&decoder);
211+ return EXIT_SUCCESS;
212+
213+}
examples.mk+231−0
@@ -0,0 +1,231 @@
1+##
2+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+##
4+## Use of this source code is governed by a BSD-style license and patent
5+## grant that can be found in the LICENSE file in the root of the source
6+## tree. All contributing project authors may be found in the AUTHORS
7+## file in the root of the source tree.
8+##
9+
10+
11+# List of examples to build. UTILS are files that are taken from the source
12+# tree directly, and GEN_EXAMPLES are files that are created from the
13+# examples folder.
14+UTILS-$(CONFIG_DECODERS) += ivfdec.c
15+ivfdec.SRCS += md5_utils.c md5_utils.h
16+ivfdec.SRCS += vpx_ports/vpx_timer.h
17+ivfdec.SRCS += vpx_ports/vpx_integer.h
18+ivfdec.SRCS += args.c args.h vpx_ports/config.h
19+ivfdec.GUID = BA5FE66F-38DD-E034-F542-B1578C5FB950
20+ivfdec.DESCRIPTION = Full featured decoder
21+UTILS-$(CONFIG_ENCODERS) += ivfenc.c
22+ivfenc.SRCS += args.c args.h vpx_ports/config.h
23+ivfenc.SRCS += vpx_ports/mem_ops.h vpx_ports/mem_ops_aligned.h
24+ivfenc.GUID = 548DEC74-7A15-4B2B-AFC3-AA102E7C25C1
25+ivfenc.DESCRIPTION = Full featured encoder
26+UTILS-$(CONFIG_DECODERS) += example_xma.c
27+example_xma.GUID = A955FC4A-73F1-44F7-135E-30D84D32F022
28+example_xma.DESCRIPTION = External Memory Allocation mode usage
29+
30+GEN_EXAMPLES-$(CONFIG_DECODERS) += simple_decoder.c
31+simple_decoder.GUID = D3BBF1E9-2427-450D-BBFF-B2843C1D44CC
32+simple_decoder.DESCRIPTION = Simplified decoder loop
33+GEN_EXAMPLES-$(CONFIG_DECODERS) += postproc.c
34+postproc.GUID = 65E33355-F35E-4088-884D-3FD4905881D7
35+postproc.DESCRIPTION = Decoder postprocessor control
36+GEN_EXAMPLES-$(CONFIG_DECODERS) += decode_to_md5.c
37+decode_to_md5.SRCS += md5_utils.h md5_utils.c
38+decode_to_md5.GUID = 59120B9B-2735-4BFE-B022-146CA340FE42
39+decode_to_md5.DESCRIPTION = Frame by frame MD5 checksum
40+
41+GEN_EXAMPLES-$(CONFIG_ENCODERS) += simple_encoder.c
42+simple_encoder.GUID = 4607D299-8A71-4D2C-9B1D-071899B6FBFD
43+simple_encoder.DESCRIPTION = Simplified encoder loop
44+GEN_EXAMPLES-$(CONFIG_ENCODERS) += twopass_encoder.c
45+twopass_encoder.GUID = 73494FA6-4AF9-4763-8FBB-265C92402FD8
46+twopass_encoder.DESCRIPTION = Two-pass encoder loop
47+GEN_EXAMPLES-$(CONFIG_ENCODERS) += force_keyframe.c
48+force_keyframe.GUID = 3C67CADF-029F-4C86-81F5-D6D4F51177F0
49+force_keyframe.DESCRIPTION = Force generation of keyframes
50+ifeq ($(CONFIG_DECODERS),yes)
51+GEN_EXAMPLES-$(CONFIG_ENCODERS) += decode_with_drops.c
52+endif
53+decode_with_drops.GUID = CE5C53C4-8DDA-438A-86ED-0DDD3CDB8D26
54+decode_with_drops.DESCRIPTION = Drops frames while decoding
55+GEN_EXAMPLES-$(CONFIG_ENCODERS) += error_resilient.c
56+error_resilient.GUID = DF5837B9-4145-4F92-A031-44E4F832E00C
57+error_resilient.DESCRIPTION = Error Resiliency Feature
58+
59+GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_scalable_patterns.c
60+vp8_scalable_patterns.GUID = 0D6A210B-F482-4D6F-8570-4A9C01ACC88C
61+vp8_scalable_patterns.DESCRIPTION = VP8 Scalable Bitstream Patterns
62+GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8_set_maps.c
63+vp8_set_maps.GUID = ECB2D24D-98B8-4015-A465-A4AF3DCC145F
64+vp8_set_maps.DESCRIPTION = VP8 set active and ROI maps
65+GEN_EXAMPLES-$(CONFIG_VP8_ENCODER) += vp8cx_set_ref.c
66+vp8cx_set_ref.GUID = C5E31F7F-96F6-48BD-BD3E-10EBF6E8057A
67+vp8cx_set_ref.DESCRIPTION = VP8 set encoder reference frame
68+
69+
70+# Handle extra library flags depending on codec configuration
71+CODEC_EXTRA_LIBS-$(CONFIG_VP8) += m
72+
73+#
74+# End of specified files. The rest of the build rules should happen
75+# automagically from here.
76+#
77+
78+
79+# Examples need different flags based on whether we're building
80+# from an installed tree or a version controlled tree. Determine
81+# the proper paths.
82+ifeq ($(HAVE_ALT_TREE_LAYOUT),yes)
83+ LIB_PATH := $(SRC_PATH_BARE)/../lib
84+ INC_PATH := $(SRC_PATH_BARE)/../include
85+else
86+ LIB_PATH-yes += $(if $(BUILD_PFX),$(BUILD_PFX),.)
87+ INC_PATH-yes += $(SRC_PATH_BARE)/vpx_codec
88+ INC_PATH-yes += $(SRC_PATH_BARE)/vpx_ports
89+ INC_PATH-$(CONFIG_VP8_DECODER) += $(SRC_PATH_BARE)/vp8
90+ INC_PATH-$(CONFIG_VP8_ENCODER) += $(SRC_PATH_BARE)/vp8
91+ LIB_PATH := $(call enabled,LIB_PATH)
92+ INC_PATH := $(call enabled,INC_PATH)
93+endif
94+CFLAGS += $(addprefix -I,$(INC_PATH))
95+LDFLAGS += $(addprefix -L,$(LIB_PATH))
96+
97+
98+# Expand list of selected examples to build (as specified above)
99+UTILS = $(call enabled,UTILS)
100+GEN_EXAMPLES = $(call enabled,GEN_EXAMPLES)
101+ALL_EXAMPLES = $(UTILS) $(GEN_EXAMPLES)
102+ALL_SRCS = $(foreach ex,$(ALL_EXAMPLES),$($(ex:.c=).SRCS))
103+CODEC_EXTRA_LIBS=$(sort $(call enabled,CODEC_EXTRA_LIBS))
104+
105+
106+# Expand all example sources into a variable containing all sources
107+# for that example (not just them main one specified in UTILS/GEN_EXAMPLES)
108+# and add this file to the list (for MSVS workspace generation)
109+$(foreach ex,$(ALL_EXAMPLES),$(eval $(ex:.c=).SRCS += $(ex) examples.mk))
110+
111+
112+# If this is a universal (fat) binary, then all the subarchitectures have
113+# already been built and our job is to stitch them together. The
114+# BUILD_OBJS variable indicates whether we should be building
115+# (compiling, linking) the library. The LIPO_OBJS variable indicates
116+# that we're stitching.
117+$(eval $(if $(filter universal%,$(TOOLCHAIN)),LIPO_OBJS,BUILD_OBJS):=yes)
118+
119+
120+# Create build/install dependencies for all examples. The common case
121+# is handled here. The MSVS case is handled below.
122+NOT_MSVS = $(if $(CONFIG_MSVS),,yes)
123+INSTALL-BINS-$(NOT_MSVS) += $(addprefix bin/,$(ALL_EXAMPLES:.c=))
124+INSTALL-SRCS-yes += $(ALL_SRCS)
125+OBJS-$(NOT_MSVS) += $(if $(BUILD_OBJS),$(call objs,$(ALL_SRCS)))
126+BINS-$(NOT_MSVS) += $(addprefix $(BUILD_PFX),$(ALL_EXAMPLES:.c=))
127+
128+
129+# Instantiate linker template for all examples.
130+CODEC_LIB=$(if $(CONFIG_DEBUG_LIBS),vpx_g,vpx)
131+$(foreach bin,$(BINS-yes),\
132+ $(if $(BUILD_OBJS),$(eval $(bin): $(LIB_PATH)/lib$(CODEC_LIB).a))\
133+ $(if $(BUILD_OBJS),$(eval $(call linker_template,$(bin),\
134+ $(call objs,$($(notdir $(bin)).SRCS)) \
135+ -l$(CODEC_LIB) $(addprefix -l,$(CODEC_EXTRA_LIBS))\
136+ )))\
137+ $(if $(LIPO_OBJS),$(eval $(call lipo_bin_template,$(bin))))\
138+ )
139+
140+
141+# Rules to generate the GEN_EXAMPLES sources
142+.PRECIOUS: %.c
143+CLEAN-OBJS += $(GEN_EXAMPLES)
144+%.c: examples/%.txt
145+ @echo " [EXAMPLE] $@"
146+ @$(SRC_PATH_BARE)/examples/gen_example_code.sh $< > $@
147+
148+
149+# The following pairs define a mapping of locations in the distribution
150+# tree to locations in the source/build trees.
151+INSTALL_MAPS += src/%.c %.c
152+INSTALL_MAPS += src/% $(SRC_PATH_BARE)/%
153+INSTALL_MAPS += bin/% %
154+INSTALL_MAPS += % %
155+
156+
157+# Set up additional MSVS environment
158+ifeq ($(CONFIG_MSVS),yes)
159+CODEC_LIB=$(if $(CONFIG_STATIC_MSVCRT),vpxmt,vpxmd)
160+# This variable uses deferred expansion intentionally, since the results of
161+# $(wildcard) may change during the course of the Make.
162+VS_PLATFORMS = $(foreach d,$(wildcard */Release/$(CODEC_LIB).lib),$(word 1,$(subst /, ,$(d))))
163+INSTALL_MAPS += $(foreach p,$(VS_PLATFORMS),bin/$(p)/% $(p)/Release/%)
164+endif
165+
166+# Build Visual Studio Projects. We use a template here to instantiate
167+# explicit rules rather than using an implicit rule because we want to
168+# leverage make's VPATH searching rather than specifying the paths on
169+# each file in ALL_EXAMPLES. This has the unfortunate side effect that
170+# touching the source files trigger a rebuild of the project files
171+# even though there is no real dependency there (the dependency is on
172+# the makefiles). We may want to revisit this.
173+define vcproj_template
174+$(1): $($(1:.vcproj=).SRCS)
175+ @echo " [vcproj] $$@"
176+ $$(SRC_PATH_BARE)/build/make/gen_msvs_proj.sh\
177+ --exe\
178+ --target=$$(TOOLCHAIN)\
179+ --name=$$(@:.vcproj=)\
180+ --ver=$$(CONFIG_VS_VERSION)\
181+ --proj-guid=$$($$(@:.vcproj=).GUID)\
182+ $$(if $$(CONFIG_STATIC_MSVCRT),--static-crt) \
183+ --out=$$@ $$(CFLAGS) $$(LDFLAGS) -l$$(CODEC_LIB) -lwinmm $$^
184+endef
185+PROJECTS-$(CONFIG_MSVS) += $(ALL_EXAMPLES:.c=.vcproj)
186+INSTALL-BINS-$(CONFIG_MSVS) += $(foreach p,$(VS_PLATFORMS),\
187+ $(addprefix bin/$(p)/,$(ALL_EXAMPLES:.c=.exe)))
188+$(foreach proj,$(call enabled,PROJECTS),\
189+ $(eval $(call vcproj_template,$(proj))))
190+
191+
192+
193+#
194+# Documentation Rules
195+#
196+%.dox: examples/%.txt
197+ @echo " [DOXY] $@"
198+ @$(SRC_PATH_BARE)/examples/gen_example_text.sh $< | \
199+ $(SRC_PATH_BARE)/examples/gen_example_doxy.php \
200+ example_$(@:.dox=) $(@:.dox=.c) > $@
201+
202+%.dox: %.c
203+ @echo " [DOXY] $@"
204+ @echo "/*!\page example_$(@:.dox=) $(@:.dox=)" > $@
205+ @echo " \includelineno $(notdir $<)" >> $@
206+ @echo "*/" >> $@
207+
208+samples.dox: examples.mk
209+ @echo " [DOXY] $@"
210+ @echo "/*!\page samples Sample Code" > $@
211+ @echo " This SDK includes a number of sample applications."\
212+ "each sample documents a feature of the SDK in both prose"\
213+ "and the associated C code. In general, later samples"\
214+ "build upon prior samples, so it is best to work through the"\
215+ "list in order. The following samples are included: ">>$@
216+ @$(foreach ex,$(GEN_EXAMPLES:.c=),\
217+ echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
218+ @echo >> $@
219+ @echo " In addition, the SDK contains a number of utilities."\
220+ "Since these utilities are built upon the concepts described"\
221+ "in the sample code listed above, they are not documented in"\
222+ "pieces like the samples are. Thir sourcre is included here"\
223+ "for reference. The following utilities are included:" >> $@
224+ @$(foreach ex,$(UTILS:.c=),\
225+ echo " - \subpage example_$(ex) $($(ex).DESCRIPTION)" >> $@;)
226+ @echo "*/" >> $@
227+
228+CLEAN-OBJS += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
229+DOCS-yes += examples.doxy samples.dox $(ALL_EXAMPLES:.c=.dox)
230+examples.doxy: samples.dox $(ALL_EXAMPLES:.c=.dox)
231+ @echo "INPUT += $^" > $@
examples/decode_to_md5.txt+48−0
@@ -0,0 +1,48 @@
1+@TEMPLATE decoder_tmpl.c
2+Frame-by-frame MD5 Checksum
3+===========================
4+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5+This example builds upon the simple decoder loop to show how checksums
6+of the decoded output can be generated. These are used for validating
7+decoder implementations against the reference implementation, for example.
8+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
9+
10+MD5 algorithm
11+-------------
12+The Message-Digest 5 (MD5) is a well known hash function. We have provided
13+an implementation derived from the RSA Data Security, Inc. MD5 Message-Digest
14+Algorithm for your use. Our implmentation only changes the interface of this
15+reference code. You must include the `md5_utils.h` header for access to these
16+functions.
17+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
18+#include "md5_utils.h"
19+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_INCLUDES
20+
21+
22+Processing The Decoded Data
23+---------------------------
24+Each row of the image is passed to the MD5 accumulator. First the Y plane
25+is processed, then U, then V. It is important to honor the image's `stride`
26+values.
27+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
28+unsigned char md5_sum[16];
29+md5_ctx_t md5;
30+int i;
31+
32+md5_init(&md5);
33+
34+for(plane=0; plane < 3; plane++) {
35+ unsigned char *buf =img->planes[plane];
36+
37+ for(y=0; y<img->d_h >> (plane?1:0); y++) {
38+ md5_update(&md5, buf, img->d_w >> (plane?1:0));
39+ buf += img->stride[plane];
40+ }
41+}
42+
43+md5_finalize(&md5, md5_sum);
44+for(i=0; i<16; i++)
45+ fprintf(outfile, "%02x",md5_sum[i]);
46+fprintf(outfile, " img-%dx%d-%04d.i420\n", img->d_w, img->d_h,
47+ frame_cnt);
48+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
examples/decode_with_drops.txt+73−0
@@ -0,0 +1,73 @@
1+@TEMPLATE decoder_tmpl.c
2+Decode With Drops Example
3+=========================
4+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5+This is an example utility which drops a series of frames, as specified
6+on the command line. This is useful for observing the error recovery
7+features of the codec.
8+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
9+
10+Usage
11+-----
12+This example adds a single argument to the `simple_decoder` example,
13+which specifies the range or pattern of frames to drop. The parameter is
14+parsed as follows:
15+
16+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
17+if(argc!=4)
18+ die("Usage: %s <infile> <outfile> <N-M|N/M>\n", argv[0]);
19+{
20+ char *nptr;
21+ n = strtol(argv[3], &nptr, 0);
22+ m = strtol(nptr+1, NULL, 0);
23+ is_range = *nptr == '-';
24+ if(!n || !m || (*nptr != '-' && *nptr != '/'))
25+ die("Couldn't parse pattern %s\n", argv[3]);
26+}
27+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
28+
29+
30+Dropping A Range Of Frames
31+--------------------------
32+To drop a range of frames, specify the starting frame and the ending
33+frame to drop, separated by a dash. The following command will drop
34+frames 5 through 10 (base 1).
35+
36+ $ ./decode_with_drops in.ivf out.i420 5-10
37+
38+
39+Dropping A Pattern Of Frames
40+----------------------------
41+To drop a pattern of frames, specify the number of frames to drop and
42+the number of frames after which to repeat the pattern, separated by
43+a forward-slash. The following command will drop 3 of 7 frames.
44+Specifically, it will decode 4 frames, then drop 3 frames, and then
45+repeat.
46+
47+ $ ./decode_with_drops in.ivf out.i420 3/7
48+
49+
50+Extra Variables
51+---------------
52+This example maintains the pattern passed on the command line in the
53+`n`, `m`, and `is_range` variables:
54+
55+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
56+int n, m, is_range;
57+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EXTRA_VARS
58+
59+
60+Making The Drop Decision
61+------------------------
62+The example decides whether to drop the frame based on the current
63+frame number, immediately before decoding the frame.
64+
65+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
66+if((is_range && frame_cnt >= n && frame_cnt <= m)
67+ ||(!is_range && m - (frame_cnt-1)%m <= n)) {
68+ putc('X', stdout);
69+ continue;
70+}
71+putc('.', stdout);
72+fflush(stdout);
73+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PRE_DECODE
examples/decoder_tmpl.c+102−0
@@ -0,0 +1,102 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+/*
12+@*INTRODUCTION
13+ */
14+#include <stdio.h>
15+#include <stdlib.h>
16+#include <stdarg.h>
17+#include <string.h>
18+#define VPX_CODEC_DISABLE_COMPAT 1
19+#include "vpx_decoder.h"
20+#if CONFIG_VP8_DECODER && !defined(interface)
21+#include "vp8dx.h"
22+#define interface (&vpx_codec_vp8_dx_algo)
23+#endif
24+@EXTRA_INCLUDES
25+
26+
27+#define IVF_FILE_HDR_SZ (32)
28+#define IVF_FRAME_HDR_SZ (12)
29+
30+static unsigned int mem_get_le32(const unsigned char *mem) {
31+ return (mem[3] << 24)|(mem[2] << 16)|(mem[1] << 8)|(mem[0]);
32+}
33+
34+static void die(const char *fmt, ...) {
35+ va_list ap;
36+
37+ va_start(ap, fmt);
38+ vprintf(fmt, ap);
39+ if(fmt[strlen(fmt)-1] != '\n')
40+ printf("\n");
41+ exit(EXIT_FAILURE);
42+}
43+
44+@DIE_CODEC
45+
46+int main(int argc, char **argv) {
47+ FILE *infile, *outfile;
48+ vpx_codec_ctx_t codec;
49+ int flags = 0, frame_cnt = 0;
50+ unsigned char file_hdr[IVF_FILE_HDR_SZ];
51+ unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
52+ unsigned char frame[256*1024];
53+ vpx_codec_err_t res;
54+@@@@EXTRA_VARS
55+
56+ (void)res;
57+ /* Open files */
58+@@@@USAGE
59+ if(!(infile = fopen(argv[1], "rb")))
60+ die("Failed to open %s for reading", argv[1]);
61+ if(!(outfile = fopen(argv[2], "wb")))
62+ die("Failed to open %s for writing", argv[2]);
63+
64+ /* Read file header */
65+ fread(file_hdr, 1, IVF_FILE_HDR_SZ, infile);
66+ if(!(file_hdr[0]=='D' && file_hdr[1]=='K' && file_hdr[2]=='I'
67+ && file_hdr[3]=='F'))
68+ die("%s is not an IVF file.", argv[1]);
69+
70+ printf("Using %s\n",vpx_codec_iface_name(interface));
71+@@@@DEC_INIT
72+
73+ /* Read each frame */
74+ while(fread(frame_hdr, 1, IVF_FRAME_HDR_SZ, infile) == IVF_FRAME_HDR_SZ) {
75+ int frame_sz = mem_get_le32(frame_hdr);
76+ vpx_codec_iter_t iter = NULL;
77+ vpx_image_t *img;
78+
79+
80+ frame_cnt++;
81+ if(frame_sz > sizeof(frame))
82+ die("Frame %d data too big for example code buffer", frame_sz);
83+ if(fread(frame, 1, frame_sz, infile) != frame_sz)
84+ die("Frame %d failed to read complete frame", frame_cnt);
85+
86+@@@@@@@@PRE_DECODE
87+@@@@@@@@DECODE
88+
89+ /* Write decoded data to disk */
90+@@@@@@@@GET_FRAME
91+ unsigned int plane, y;
92+
93+@@@@@@@@@@@@PROCESS_DX
94+ }
95+ }
96+ printf("Processed %d frames.\n",frame_cnt);
97+@@@@DESTROY
98+
99+ fclose(outfile);
100+ fclose(infile);
101+ return EXIT_SUCCESS;
102+}
examples/decoder_tmpl.txt+61−0
@@ -0,0 +1,61 @@
1+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
2+#define VPX_CODEC_DISABLE_COMPAT 1
3+#include "vpx_decoder.h"
4+#include "vp8dx.h"
5+#define interface (&vpx_codec_vp8_dx_algo)
6+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INCLUDES
7+
8+
9+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
10+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
11+ const char *detail = vpx_codec_error_detail(ctx);
12+
13+ printf("%s: %s\n", s, vpx_codec_error(ctx));
14+ if(detail)
15+ printf(" %s\n",detail);
16+ exit(EXIT_FAILURE);
17+}
18+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
19+
20+
21+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
22+if(argc!=3)
23+ die("Usage: %s <infile> <outfile>\n", argv[0]);
24+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
25+
26+
27+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
28+/* Initialize codec */
29+if(vpx_codec_dec_init(&codec, interface, NULL, flags))
30+ die_codec(&codec, "Failed to initialize decoder");
31+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DEC_INIT
32+
33+
34+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
35+/* Decode the frame */
36+if(vpx_codec_decode(&codec, frame, frame_sz, NULL, 0))
37+ die_codec(&codec, "Failed to decode frame");
38+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DECODE
39+
40+
41+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
42+while((img = vpx_codec_get_frame(&codec, &iter))) {
43+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GET_FRAME
44+
45+
46+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
47+for(plane=0; plane < 3; plane++) {
48+ unsigned char *buf =img->planes[plane];
49+
50+ for(y=0; y<img->d_h >> (plane?1:0); y++) {
51+ fwrite(buf, 1, img->d_w >> (plane?1:0), outfile);
52+ buf += img->stride[plane];
53+ }
54+}
55+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_DX
56+
57+
58+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
59+if(vpx_codec_destroy(&codec))
60+ die_codec(&codec, "Failed to destroy codec");
61+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
examples/encoder_tmpl.c+189−0
@@ -0,0 +1,189 @@
1+/*
2+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
3+ *
4+ * Use of this source code is governed by a BSD-style license and patent
5+ * grant that can be found in the LICENSE file in the root of the source
6+ * tree. All contributing project authors may be found in the AUTHORS
7+ * file in the root of the source tree.
8+ */
9+
10+
11+/*
12+@*INTRODUCTION
13+ */
14+#include <stdio.h>
15+#include <stdlib.h>
16+#include <stdarg.h>
17+#include <string.h>
18+#define VPX_CODEC_DISABLE_COMPAT 1
19+#include "vpx_encoder.h"
20+#if CONFIG_VP8_ENCODER && !defined(interface)
21+#include "vp8cx.h"
22+#define interface (&vpx_codec_vp8_cx_algo)
23+#define fourcc 0x30385056
24+#endif
25+@EXTRA_INCLUDES
26+
27+#define IVF_FILE_HDR_SZ (32)
28+#define IVF_FRAME_HDR_SZ (12)
29+
30+static void mem_put_le16(char *mem, unsigned int val) {
31+ mem[0] = val;
32+ mem[1] = val>>8;
33+}
34+
35+static void mem_put_le32(char *mem, unsigned int val) {
36+ mem[0] = val;
37+ mem[1] = val>>8;
38+ mem[2] = val>>16;
39+ mem[3] = val>>24;
40+}
41+
42+static void die(const char *fmt, ...) {
43+ va_list ap;
44+
45+ va_start(ap, fmt);
46+ vprintf(fmt, ap);
47+ if(fmt[strlen(fmt)-1] != '\n')
48+ printf("\n");
49+ exit(EXIT_FAILURE);
50+}
51+
52+@DIE_CODEC
53+
54+static int read_frame(FILE *f, vpx_image_t *img) {
55+ size_t nbytes, to_read;
56+ int res = 1;
57+
58+ to_read = img->w*img->h*3/2;
59+ nbytes = fread(img->planes[0], 1, to_read, f);
60+ if(nbytes != to_read) {
61+ res = 0;
62+ if(nbytes > 0)
63+ printf("Warning: Read partial frame. Check your width & height!\n");
64+ }
65+ return res;
66+}
67+
68+static void write_ivf_file_header(FILE *outfile,
69+ const vpx_codec_enc_cfg_t *cfg,
70+ int frame_cnt) {
71+ char header[32];
72+
73+ if(cfg->g_pass != VPX_RC_ONE_PASS && cfg->g_pass != VPX_RC_LAST_PASS)
74+ return;
75+ header[0] = 'D';
76+ header[1] = 'K';
77+ header[2] = 'I';
78+ header[3] = 'F';
79+ mem_put_le16(header+4, 0); /* version */
80+ mem_put_le16(header+6, 32); /* headersize */
81+ mem_put_le32(header+8, fourcc); /* headersize */
82+ mem_put_le16(header+12, cfg->g_w); /* width */
83+ mem_put_le16(header+14, cfg->g_h); /* height */
84+ mem_put_le32(header+16, cfg->g_timebase.den); /* rate */
85+ mem_put_le32(header+20, cfg->g_timebase.num); /* scale */
86+ mem_put_le32(header+24, frame_cnt); /* length */
87+ mem_put_le32(header+28, 0); /* unused */
88+
89+ fwrite(header, 1, 32, outfile);
90+}
91+
92+
93+static void write_ivf_frame_header(FILE *outfile,
94+ const vpx_codec_cx_pkt_t *pkt)
95+{
96+ char header[12];
97+ vpx_codec_pts_t pts;
98+
99+ if(pkt->kind != VPX_CODEC_CX_FRAME_PKT)
100+ return;
101+
102+ pts = pkt->data.frame.pts;
103+ mem_put_le32(header, pkt->data.frame.sz);
104+ mem_put_le32(header+4, pts&0xFFFFFFFF);
105+ mem_put_le32(header+8, pts >> 32);
106+
107+ fwrite(header, 1, 12, outfile);
108+}
109+
110+int main(int argc, char **argv) {
111+ FILE *infile, *outfile;
112+ vpx_codec_ctx_t codec;
113+ vpx_codec_enc_cfg_t cfg;
114+ int frame_cnt = 0;
115+ unsigned char file_hdr[IVF_FILE_HDR_SZ];
116+ unsigned char frame_hdr[IVF_FRAME_HDR_SZ];
117+ vpx_image_t raw;
118+ vpx_codec_err_t res;
119+ long width;
120+ long height;
121+ int frame_avail;
122+ int got_data;
123+ int flags = 0;
124+@@@@TWOPASS_VARS
125+
126+ /* Open files */
127+@@@@USAGE
128+ width = strtol(argv[1], NULL, 0);
129+ height = strtol(argv[2], NULL, 0);
130+ if(width < 16 || width%2 || height <16 || height%2)
131+ die("Invalid resolution: %ldx%ld", width, height);
132+ if(!vpx_img_alloc(&raw, IMG_FMT_YV12, width, height, 1))
133+ die("Faile to allocate image", width, height);
134+ if(!(outfile = fopen(argv[4], "wb")))
135+ die("Failed to open %s for writing", argv[4]);
136+
137+ printf("Using %s\n",vpx_codec_iface_name(interface));
138+
139+@@@@ENC_DEF_CFG
140+
141+@@@@ENC_SET_CFG
142+@@@@ENC_SET_CFG2
143+
144+ write_ivf_file_header(outfile, &cfg, 0);
145+
146+@@@@TWOPASS_LOOP_BEGIN
147+
148+ /* Open input file for this encoding pass */
149+ if(!(infile = fopen(argv[3], "rb")))
150+ die("Failed to open %s for reading", argv[3]);
151+
152+@@@@@@@@ENC_INIT
153+
154+ frame_avail = 1;
155+ got_data = 0;
156+ while(frame_avail || got_data) {
157+ vpx_codec_iter_t iter = NULL;
158+ const vpx_codec_cx_pkt_t *pkt;
159+
160+@@@@@@@@@@@@PER_FRAME_CFG
161+@@@@@@@@@@@@ENCODE_FRAME
162+ got_data = 0;
163+ while( (pkt = vpx_codec_get_cx_data(&codec, &iter)) ) {
164+ got_data = 1;
165+ switch(pkt->kind) {
166+@@@@@@@@@@@@@@@@PROCESS_FRAME
167+@@@@@@@@@@@@@@@@PROCESS_STATS
168+ default:
169+ break;
170+ }
171+ printf(pkt->kind == VPX_CODEC_CX_FRAME_PKT
172+ && (pkt->data.frame.flags & VPX_FRAME_IS_KEY)? "K":".");
173+ fflush(stdout);
174+ }
175+ frame_cnt++;
176+ }
177+ printf("\n");
178+ fclose(infile);
179+@@@@TWOPASS_LOOP_END
180+
181+ printf("Processed %d frames.\n",frame_cnt-1);
182+@@@@DESTROY
183+
184+ /* Try to rewrite the file header with the actual frame count */
185+ if(!fseek(outfile, 0, SEEK_SET))
186+ write_ivf_file_header(outfile, &cfg, frame_cnt-1);
187+ fclose(outfile);
188+ return EXIT_SUCCESS;
189+}
examples/encoder_tmpl.txt+73−0
@@ -0,0 +1,73 @@
1+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
2+#define VPX_CODEC_DISABLE_COMPAT 1
3+#include "vpx_encoder.h"
4+#include "vp8cx.h"
5+#define interface (&vpx_codec_vp8_cx_algo)
6+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INCLUDES
7+
8+
9+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
10+static void die_codec(vpx_codec_ctx_t *ctx, const char *s) {
11+ const char *detail = vpx_codec_error_detail(ctx);
12+
13+ printf("%s: %s\n", s, vpx_codec_error(ctx));
14+ if(detail)
15+ printf(" %s\n",detail);
16+ exit(EXIT_FAILURE);
17+}
18+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DIE_CODEC
19+
20+
21+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
22+if(argc!=5)
23+ die("Usage: %s <width> <height> <infile> <outfile>\n", argv[0]);
24+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ USAGE
25+
26+
27+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
28+/* Populate encoder configuration */
29+res = vpx_codec_enc_config_default(interface, &cfg, 0);
30+if(res) {
31+ printf("Failed to get config: %s\n", vpx_codec_err_to_string(res));
32+ return EXIT_FAILURE;
33+}
34+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_DEF_CFG
35+
36+
37+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
38+/* Update the default configuration with our settings */
39+cfg.rc_target_bitrate = width * height * cfg.rc_target_bitrate
40+ / cfg.g_w / cfg.g_h;
41+cfg.g_w = width;
42+cfg.g_h = height;
43+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG
44+
45+
46+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
47+/* Initialize codec */
48+if(vpx_codec_enc_init(&codec, interface, &cfg, 0))
49+ die_codec(&codec, "Failed to initialize encoder");
50+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_INIT
51+
52+
53+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
54+frame_avail = read_frame(infile, &raw);
55+if(vpx_codec_encode(&codec, frame_avail? &raw : NULL, frame_cnt,
56+ 1, flags, VPX_DL_REALTIME))
57+ die_codec(&codec, "Failed to encode frame");
58+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENCODE_FRAME
59+
60+
61+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
62+case VPX_CODEC_CX_FRAME_PKT:
63+ write_ivf_frame_header(outfile, pkt);
64+ fwrite(pkt->data.frame.buf, 1, pkt->data.frame.sz,
65+ outfile);
66+ break;
67+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PROCESS_FRAME
68+
69+
70+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
71+if(vpx_codec_destroy(&codec))
72+ die_codec(&codec, "Failed to destroy codec");
73+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ DESTROY
examples/error_resilient.txt+25−0
@@ -0,0 +1,25 @@
1+@TEMPLATE encoder_tmpl.c
2+Error Resiliency Features
3+=========================
4+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5+This is an example demonstrating how to enable the error resiliency
6+features of the codec.
7+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
8+
9+
10+Configuration
11+-------------
12+Error resiliency is controlled by the g_error_resilient member of the
13+configuration structure.
14+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
15+
16+/* Enable error resilient mode */
17+cfg.g_error_resilient = 1;
18+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ENC_SET_CFG2
19+
20+
21+Observing The Effects
22+---------------------
23+Use the `decode_with_drops` example to decode with frames 5-10 dropped.
24+Compare the output for a file encoded with this example versus one
25+encoded with the `simple_encoder` example.
examples/force_keyframe.txt+28−0
@@ -0,0 +1,28 @@
1+@TEMPLATE encoder_tmpl.c
2+Forcing A Keyframe
3+==================
4+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
5+This is an example demonstrating how to control placement of keyframes
6+on a frame-by-frame basis.
7+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ INTRODUCTION
8+
9+
10+Configuration
11+-------------
12+Keyframes can be forced by setting the VPX_EFLAG_FORCE_KF bit of the
13+flags passed to `vpx_codec_control()`. In this example, we force a
14+keyframe every 8 frames.
15+
16+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
17+if(!(frame_cnt & 7))
18+ flags |= VPX_EFLAG_FORCE_KF;
19+else
20+ flags &= ~VPX_EFLAG_FORCE_KF;
21+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PER_FRAME_CFG
22+
23+
24+Observing The Effects
25+---------------------
26+The output of the encoder examples shows a 'K' rather than a dot '.'
27+when the encoder generates a keyframe. Note that every 8 frames a 'K'
28+is output.
examples/gen_example_code.sh+84−0
@@ -0,0 +1,84 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+# gen_example_code.sh
13+
14+self=$0
15+
16+die_usage() {
17+ echo "Usage: $self <example.txt>"
18+ exit 1
19+}
20+
21+die() {
22+ echo "$@"
23+ exit 1
24+}
25+
26+include_block() {
27+ show_bar=$1
28+ block_name=${line##*@}
29+ indent=${line%%${block_name}}
30+ indent=${#indent}
31+ [ $indent -eq 1 ] && indent=0
32+ local on_block
33+ while IFS=$'\n' read -r t_line; do
34+ case "$t_line" in
35+ \~*\ ${block_name})
36+ if [ "x$on_block" == "xyes" ]; then
37+ return 0;
38+ else
39+ on_block=yes
40+ fi
41+ ;;
42+ @DEFAULT)
43+ if [ "x$on_block" == "xyes" ]; then
44+ include_block $show_bar < "${template%.c}.txt"
45+ return 0
46+ fi
47+ ;;
48+ *)
49+ if [ "x$on_block" == "xyes" ]; then
50+ local rem
51+ (( rem = 78 - indent ))
52+ case "$block_name" in
53+ \**) printf "%${indent}s * %s\n" "" "$t_line" ;;
54+ *)
55+ if [ "$show_bar" == "yes" ]; then
56+ printf "%${indent}s%-${rem}s//\n" "" "$t_line"
57+ else
58+ printf "%${indent}s%s\n" "" "$t_line"
59+ fi
60+ ;;
61+ esac
62+ fi
63+ esac
64+ done
65+ return 1
66+}
67+
68+txt=$1
69+[ -f "$txt" ] || die_usage
70+read -r template < "$txt"
71+case "$template" in
72+ @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
73+ *) die "Failed to parse template name from '$template'" ;;
74+esac
75+
76+while IFS=$'\n' read -r line; do
77+ case "$line" in
78+ @*) include_block yes < "$txt" \
79+ || include_block < "${template%.c}.txt" \
80+ #|| echo "WARNING: failed to find text for block $block_name" >&2
81+ ;;
82+ *) echo "$line" ;;
83+ esac
84+done < "$template"
examples/gen_example_doxy.php+223−0
@@ -0,0 +1,223 @@
1+#!/usr/bin/env php
2+/*
3+ * Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+ *
5+ * Use of this source code is governed by a BSD-style license and patent
6+ * grant that can be found in the LICENSE file in the root of the source
7+ * tree. All contributing project authors may be found in the AUTHORS
8+ * file in the root of the source tree.
9+ */
10+
11+
12+<?php
13+
14+/* This script converts markdown to doxygen htmlonly syntax, nesting the
15+ * content inside a \page. It expects input on stdin and outputs on stdout.
16+ *
17+ * Usage: gen_example_doxy.php <page_identifier> "<page description>"
18+ */
19+
20+
21+$geshi_path = dirname($argv[0])."/includes/geshi/geshi/"; // Language files
22+$tmp_token = '<!-- I wanna rock you, Chaka Khan -->';
23+
24+// Include prerequisites or exit
25+if(!include_once('includes/PHP-Markdown-Extra-1.2.3/markdown.php'))
26+ die("Cannot load Markdown transformer.\n");
27+if(!include_once('includes/PHP-SmartyPants-1.5.1e/smartypants.php'))
28+ die("Cannot load SmartyPants transformer.\n");
29+if(!include_once('includes/geshi/geshi.php'))
30+ die("Cannot load GeSHi transformer.\n");
31+// ASCIIMathPHP?
32+// HTML::Toc?
33+// Tidy?
34+// Prince?
35+
36+/**
37+ * Generate XHTML body
38+ *
39+ */
40+
41+$page_body = file_get_contents('php://stdin');
42+
43+// Transform any MathML expressions in the body text
44+$regexp = '/\[\[(.*?)\]\]/'; // Double square bracket delimiters
45+$page_body = preg_replace_callback($regexp, 'ASCIIMathPHPCallback', $page_body);
46+
47+// Fix ASCIIMathPHP's output
48+$page_body = fix_asciiMath($page_body);
49+
50+// Wrap block-style <math> elements in <p>, since Markdown doesn't.
51+$page_body = preg_replace('/\n(<math.*<\/math>)\n/', '<p class="eq_para">$1</p>', $page_body);
52+
53+// Transform the body text to HTML
54+$page_body = Markdown($page_body);
55+
56+// Preprocess code blocks
57+// Decode XML entities. GeSHi doesn't anticipate that
58+// Markdown has already done this.
59+$regexp = '|<pre><code>(.*?)<\/code><\/pre>|si';
60+while (preg_match($regexp, $page_body, $matches) > 0)
61+{
62+ // Replace 1st match with token
63+ $page_body = preg_replace($regexp, $tmp_token, $page_body, 1);
64+ $block_new = $matches[1];
65+ // Un-encode ampersand entities
66+ $block_new = decode_markdown($block_new);
67+ // Replace token with revised string
68+ $page_body = preg_replace("|$tmp_token|", '<div class="codeblock">'.$block_new.'</div>', $page_body);
69+}
70+
71+// Run GeSHi over code blocks
72+$regexp = '|<div class="codeblock">(.*?)<\/div>|si';
73+$language = 'c';
74+
75+while (preg_match($regexp, $page_body, $matches))
76+{
77+ $geshi = new GeSHi($matches[1], $language);
78+ $geshi->set_language_path($geshi_path);
79+ $block_new = $geshi->parse_code();
80+ // Strip annoying final newline
81+ $block_new = preg_replace('|\n&nbsp;<\/pre>|', '</pre>' , $block_new);
82+ // Remove style attribute (TODO: Research this in GeSHi)
83+ $block_new = preg_replace('| style="font-family:monospace;"|', '' , $block_new);
84+ $page_body = preg_replace($regexp, $block_new, $page_body, 1);
85+ unset($geshi); // Clean up
86+}
87+unset($block_new); // Clean up
88+
89+// Apply typographic flourishes
90+$page_body = SmartyPants($page_body);
91+
92+
93+/**
94+ * Generate Doxygen Body
95+ *
96+ */
97+$page_id=(isset($argv[1]))?$argv[1]:"";
98+$page_desc=(isset($argv[2]))?$argv[2]:"";
99+print "/*!\\page ".$page_id." ".$page_desc."\n\\htmlonly\n";
100+print $page_body;
101+print "\\endhtmlonly\n*/\n";
102+
103+// ---------------------------------------------------------
104+
105+/**
106+ * decode_markdown()
107+ *
108+ * Markdown encodes '&', '<' and '>' in detected code
109+ * blocks, as a convenience. This will restore the
110+ * encoded entities to ordinary characters, since a
111+ * downstream transformer (like GeSHi) may not
112+ * anticipate this.
113+ *
114+ **********************************************************/
115+
116+function decode_markdown($input)
117+{
118+ $out = FALSE;
119+
120+ $entities = array ('|&amp;|'
121+ ,'|&lt;|'
122+ ,'|&gt;|'
123+ );
124+ $characters = array ('&'
125+ ,'<'
126+ ,'>'
127+ );
128+ $input = preg_replace($entities, $characters, $input);
129+ $out = $input;
130+
131+ return $out;
132+}
133+
134+
135+/**
136+ * ASCIIMathML parser
137+ * http://tinyurl.com/ASCIIMathPHP
138+ *
139+ * @PARAM mtch_arr array - Array of ASCIIMath expressions
140+ * as returned by preg_replace_callback([pattern]). First
141+ * dimension is the full matched string (with delimiter);
142+ * 2nd dimension is the undelimited contents (typically
143+ * a capture group).
144+ *
145+ **********************************************************/
146+
147+function ASCIIMathPHPCallback($mtch_arr)
148+{
149+ $txt = trim($mtch_arr[1]);
150+
151+ include('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php');
152+ require_once('includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php');
153+
154+ static $asciimath;
155+
156+ if (!isset($asciimath)) $asciimath = new ASCIIMathPHP($symbol_arr);
157+
158+ $math_attr_arr = array('displaystyle' => 'true');
159+
160+ $asciimath->setExpr($txt);
161+ $asciimath->genMathML($math_attr_arr);
162+
163+ return($asciimath->getMathML());
164+}
165+
166+/**
167+ * fix_asciiMath()
168+ *
169+ * ASCIIMath pretty-prints its output, with linefeeds
170+ * and tabs. Causes unexpected behavior in some renderers.
171+ * This flattens <math> blocks.
172+ *
173+ * @PARAM page_body str - The <body> element of an
174+ * XHTML page to transform.
175+ *
176+ **********************************************************/
177+
178+function fix_asciiMath($page_body)
179+{
180+ $out = FALSE;
181+
182+ // Remove linefeeds and whitespace in <math> elements
183+ $tags_bad = array('/(<math.*?>)\n*\s*/'
184+ , '/(<mstyle.*?>)\n*\s*/'
185+ , '/(<\/mstyle>)\n*\s*/'
186+ , '/(<mrow.*?>)\n*\s*/'
187+ , '/(<\/mrow>)\n*\s*/'
188+ , '/(<mo.*?>)\n*\s*/'
189+ , '/(<\/mo>)\n*\s*/'
190+ , '/(<mi.*?>)\n*\s*/'
191+ , '/(<\/mi>)\n*\s*/'
192+ , '/(<mn.*?>)\n*\s*/'
193+ , '/(<\/mn>)\n*\s*/'
194+ , '/(<mtext.*?>)\n*\s*/'
195+ , '/(<\/mtext>)\n*\s*/'
196+ , '/(<msqrt.*?>)\n*\s*/'
197+ , '/(<\/msqrt>)\n*\s*/'
198+ , '/(<mfrac.*?>)\n*\s*/'
199+ , '/(<\/mfrac>)\n*\s*/'
200+ );
201+ $tags_good = array( '$1'
202+ , '$1'
203+ , '$1'
204+ , '$1'
205+ , '$1'
206+ , '$1'
207+ , '$1'
208+ , '$1'
209+ , '$1'
210+ , '$1'
211+ , '$1'
212+ , '$1'
213+ , '$1'
214+ , '$1'
215+ , '$1'
216+ , '$1'
217+ , '$1'
218+ );
219+ $out = preg_replace($tags_bad, $tags_good, $page_body);
220+
221+ return $out;
222+
223+}
examples/gen_example_text.sh+83−0
@@ -0,0 +1,83 @@
1+#!/bin/bash
2+##
3+## Copyright (c) 2010 The VP8 project authors. All Rights Reserved.
4+##
5+## Use of this source code is governed by a BSD-style license and patent
6+## grant that can be found in the LICENSE file in the root of the source
7+## tree. All contributing project authors may be found in the AUTHORS
8+## file in the root of the source tree.
9+##
10+
11+
12+# gen_example_text.sh
13+
14+self=$0
15+
16+die_usage() {
17+ echo "Usage: $self <example.txt>"
18+ exit 1
19+}
20+
21+die() {
22+ echo "$@"
23+ exit 1
24+}
25+
26+include_block() {
27+ local on_block
28+ while IFS=$'\n' read -r t_line; do
29+ case "$t_line" in
30+ \~*\ ${block_name})
31+ if [ "x$on_block" == "xyes" ]; then
32+ return 0;
33+ else
34+ on_block=yes
35+ fi
36+ ;;
37+ *)
38+ if [ "x$on_block" == "xyes" ]; then
39+ echo "$t_line"
40+ fi
41+ ;;
42+ esac
43+ done
44+ echo "WARNING: failed to find text for block $block_name" >&2
45+ return 1
46+}
47+
48+txt=$1
49+[ -f "$txt" ] || die_usage
50+read -r template < "$txt"
51+case "$template" in
52+ @TEMPLATE*) template=${txt%/*}/${template##@TEMPLATE } ;;
53+ *) die "Failed to parse template name from '$template'" ;;
54+esac
55+
56+fence="~~~~~~~~~"
57+fence="${fence}${fence}"
58+fence="${fence}${fence}"
59+fence="${fence}${fence}"
60+while IFS=$'\n' read -r line; do
61+ case "$line" in
62+ @TEMPLATE*)
63+ template=${template##@TEMPLATE }
64+ template=${template%.c}.txt
65+ ;;
66+ @DEFAULT)
67+ include_block < "$template"
68+ ;;
69+ ~~~*)
70+ block_name=${line##~* }
71+ [ "$block_name" == "INTRODUCTION" ] || echo "$fence"
72+ ;;
73+ *) echo "$line"
74+ ;;
75+ esac
76+done < "$txt"
77+
78+echo
79+echo "Putting It All Together"
80+echo "======================="
81+echo "${fence}"
82+${self%/*}/gen_example_code.sh "${txt}"
83+echo "${fence}"
examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.cfg.php+218−0
@@ -0,0 +1,218 @@
1+<?php
2+
3+$symbol_arr = array(
4+
5+// Greek symbols
6+'alpha' => array( 'input'=>'alpha','tag'=>'mi', 'output'=>'&#' . hexdec('03B1') . ';'),
7+'beta' => array( 'input'=>'beta','tag'=>'mi', 'output'=>'&#' . hexdec('03B2') . ';'),
8+'chi' => array( 'input'=>'chi','tag'=>'mi', 'output'=>'&#' . hexdec('03C7') . ';'),
9+'delta' => array( 'input'=>'delta','tag'=>'mi', 'output'=>'&#' . hexdec('03B4') . ';'),
10+'Delta' => array( 'input'=>'Delta','tag'=>'mo', 'output'=>'&#' . hexdec('0394') . ';'),
11+'epsi' => array( 'input'=>'epsi','tag'=>'mi', 'output'=>'&#' . hexdec('03B5') . ';'),
12+'varepsilon' => array( 'input'=>'varepsilon','tag'=>'mi', 'output'=>'&#' . hexdec('025B') . ';'),
13+'eta' => array( 'input'=>'eta','tag'=>'mi', 'output'=>'&#' . hexdec('03B7') . ';'),
14+'gamma' => array( 'input'=>'gamma','tag'=>'mi', 'output'=>'&#' . hexdec('03B3') . ';'),
15+'Gamma' => array( 'input'=>'Gamma','tag'=>'mi', 'output'=>'&#' . hexdec('0393') . ';'),
16+'iota' => array( 'input'=>'iota','tag'=>'mi', 'output'=>'&#' . hexdec('03B9') . ';'),
17+'kappa' => array( 'input'=>'kappa','tag'=>'mi', 'output'=>'&#' . hexdec('03BA') . ';'),
18+'lambda' => array( 'input'=>'lambda','tag'=>'mi', 'output'=>'&#' . hexdec('03BB') . ';'),
19+'Lambda' => array( 'input'=>'Lambda','tag'=>'mo', 'output'=>'&#' . hexdec('039B') . ';'),
20+'mu' => array( 'input'=>'mu','tag'=>'mi', 'output'=>'&#' . hexdec('03BC') . ';'),
21+'nu' => array( 'input'=>'nu','tag'=>'mi', 'output'=>'&#' . hexdec('03BD') . ';'),
22+'omega' => array( 'input'=>'omega','tag'=>'mi', 'output'=>'&#' . hexdec('03C9') . ';'),
23+'Omega' => array( 'input'=>'Omega','tag'=>'mo', 'output'=>'&#' . hexdec('03A9') . ';'),
24+'phi' => array( 'input'=>'phi','tag'=>'mi', 'output'=>'&#' . hexdec('03C6') . ';'),
25+'varphi' => array( 'input'=>'varphi','tag'=>'mi', 'output'=>'&#' . hexdec('03D5') . ';'),
26+'Phi' => array( 'input'=>'Phi','tag'=>'mo', 'output'=>'&#' . hexdec('03A6') . ';'),
27+'pi' => array( 'input'=>'pi','tag'=>'mi', 'output'=>'&#' . hexdec('03C0') . ';'),
28+'Pi' => array( 'input'=>'Pi','tag'=>'mo', 'output'=>'&#' . hexdec('03A0') . ';'),
29+'psi' => array( 'input'=>'psi','tag'=>'mi', 'output'=>'&#' . hexdec('03C8') . ';'),
30+'rho' => array( 'input'=>'rho','tag'=>'mi', 'output'=>'&#' . hexdec('03C1') . ';'),
31+'sigma' => array( 'input'=>'sigma','tag'=>'mi', 'output'=>'&#' . hexdec('03C3') . ';'),
32+'Sigma' => array( 'input'=>'Sigma','tag'=>'mo', 'output'=>'&#' . hexdec('03A3') . ';'),
33+'tau' => array( 'input'=>'tau','tag'=>'mi', 'output'=>'&#' . hexdec('03C4') . ';'),
34+'theta' => array( 'input'=>'theta','tag'=>'mi', 'output'=>'&#' . hexdec('03B8') . ';'),
35+'vartheta' => array( 'input'=>'vartheta','tag'=>'mi', 'output'=>'&#' . hexdec('03D1') . ';'),
36+'Theta' => array( 'input'=>'Theta','tag'=>'mo', 'output'=>'&#' . hexdec('0398') . ';'),
37+'upsilon' => array( 'input'=>'upsilon','tag'=>'mi', 'output'=>'&#' . hexdec('03C5') . ';'),
38+'xi' => array( 'input'=>'xi','tag'=>'mi', 'output'=>'&#' . hexdec('03BE') . ';'),
39+'Xi' => array( 'input'=>'alpha','tag'=>'mo', 'output'=>'&#' . hexdec('039E') . ';'),
40+'zeta' => array( 'input'=>'zeta','tag'=>'mi', 'output'=>'&#' . hexdec('03B6') . ';'),
41+
42+// Binary operation symbols
43+'*' => array( 'input'=>'*','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';'),
44+'**' => array( 'input'=>'**','tag'=>'mo', 'output'=>'&#' . hexdec('22C6') . ';'),
45+'//' => array( 'input'=>'//','tag'=>'mo', 'output'=>'/'),
46+'\\\\' => array( 'input'=>'\\\\','tag'=>'mo', 'output'=>'\\'),
47+'xx' => array( 'input'=>'xx','tag'=>'mo', 'output'=>'&#' . hexdec('00D7') . ';'),
48+'-:' => array( 'input'=>'-:','tag'=>'mo', 'output'=>'&#' . hexdec('00F7') . ';'),
49+'@' => array( 'input'=>'@','tag'=>'mo', 'output'=>'&#' . hexdec('2218') . ';'),
50+'o+' => array( 'input'=>'o+','tag'=>'mo', 'output'=>'&#' . hexdec('2295') . ';'),
51+'ox' => array( 'input'=>'ox','tag'=>'mo', 'output'=>'&#' . hexdec('2297') . ';'),
52+'sum' => array( 'input'=>'sum','tag'=>'mo', 'output'=>'&#' . hexdec('2211') . ';', 'underover'=>TRUE),
53+'prod' => array( 'input'=>'prod','tag'=>'mo', 'output'=>'&#' . hexdec('220F') . ';', 'underover'=>TRUE),
54+'^^' => array( 'input'=>'^^','tag'=>'mo', 'output'=>'&#' . hexdec('2227') . ';'),
55+'^^^' => array( 'input'=>'^^^','tag'=>'mo', 'output'=>'&#' . hexdec('22C0') . ';', 'underover'=>TRUE),
56+'vv' => array( 'input'=>'vv','tag'=>'mo', 'output'=>'&#' . hexdec('2228') . ';'),
57+'vvv' => array( 'input'=>'vvv','tag'=>'mo', 'output'=>'&#' . hexdec('22C1') . ';', 'underover'=>TRUE),
58+'nn' => array( 'input'=>'nn','tag'=>'mo', 'output'=>'&#' . hexdec('2229') . ';'),
59+'nnn' => array( 'input'=>'nnn','tag'=>'mo', 'output'=>'&#' . hexdec('22C5') . ';', 'underover'=>TRUE),
60+'uu' => array( 'input'=>'uu','tag'=>'mo', 'output'=>'&#' . hexdec('222A') . ';'),
61+'uuu' => array( 'input'=>'uuu','tag'=>'mo', 'output'=>'&#' . hexdec('22C3') . ';', 'underover'=>TRUE),
62+
63+// Binary relation symbols
64+'!=' => array( 'input'=>'!=','tag'=>'mo', 'output'=>'&#' . hexdec('2260') . ';'),
65+':=' => array( 'input'=>':=','tag'=>'mo', 'output'=>':=' ), /* 2005-06-05 wes */
66+'<' => array( 'input'=>'<','tag'=>'mo', 'output'=>'&lt;'),
67+'lt' => array( 'input'=>'lt','tag'=>'mo', 'output'=>'&lt;'), /* 2005-06-05 wes */
68+'<=' => array( 'input'=>'<=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
69+'lt=' => array( 'input'=>'lt=','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'),
70+'le' => array( 'input'=>'le','tag'=>'mo', 'output'=>'&#' . hexdec('2264') . ';'), /* 2005-06-05 wes */
71+'>' => array( 'input'=>'>','tag'=>'mo', 'output'=>'&gt;'),
72+'>=' => array( 'input'=>'>=','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
73+'qeq' => array( 'input'=>'geq','tag'=>'mo', 'output'=>'&#' . hexdec('2265') . ';'),
74+'-<' => array( 'input'=>'-<','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
75+'-lt' => array( 'input'=>'-lt','tag'=>'mo', 'output'=>'&#' . hexdec('227A') . ';'),
76+'>-' => array( 'input'=>'>-','tag'=>'mo', 'output'=>'&#' . hexdec('227B') . ';'),
77+'in' => array( 'input'=>'in','tag'=>'mo', 'output'=>'&#' . hexdec('2208') . ';'),
78+'!in' => array( 'input'=>'!in','tag'=>'mo', 'output'=>'&#' . hexdec('2209') . ';'),
79+'sub' => array( 'input'=>'sub','tag'=>'mo', 'output'=>'&#' . hexdec('2282') . ';'),
80+'sup' => array( 'input'=>'sup','tag'=>'mo', 'output'=>'&#' . hexdec('2283') . ';'),
81+'sube' => array( 'input'=>'sube','tag'=>'mo', 'output'=>'&#' . hexdec('2286') . ';'),
82+'supe' => array( 'input'=>'supe','tag'=>'mo', 'output'=>'&#' . hexdec('2287') . ';'),
83+'-=' => array( 'input'=>'-=','tag'=>'mo', 'output'=>'&#' . hexdec('2261') . ';'),
84+'~=' => array( 'input'=>'~=','tag'=>'mo', 'output'=>'&#' . hexdec('2245') . ';'),
85+'~~' => array( 'input'=>'~~','tag'=>'mo', 'output'=>'&#' . hexdec('2248') . ';'),
86+'prop' => array( 'input'=>'prop','tag'=>'mo', 'output'=>'&#' . hexdec('221D') . ';'),
87+
88+// Logical symbols
89+'and' => array( 'input'=>'and','tag'=>'mtext', 'output'=>'and', 'space'=>'1ex'),
90+'or' => array( 'input'=>'or','tag'=>'mtext', 'output'=>'or', 'space'=>'1ex'),
91+'not' => array( 'input'=>'not','tag'=>'mo', 'output'=>'&#' . hexdec('00AC') . ';'),
92+'=>' => array( 'input'=>'=>','tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
93+'if' => array( 'input'=>'if','tag'=>'mo', 'output'=>'if', 'space'=>'1ex'),
94+'iff' => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
95+'<=>' => array( 'input'=>'iff','tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'), /* 2005-06-07 wes */
96+'AA' => array( 'input'=>'AA','tag'=>'mo', 'output'=>'&#' . hexdec('2200') . ';'),
97+'EE' => array( 'input'=>'EE','tag'=>'mo', 'output'=>'&#' . hexdec('2203') . ';'),
98+'_|_' => array( 'input'=>'_|_','tag'=>'mo', 'output'=>'&#' . hexdec('22A5') . ';'),
99+'TT' => array( 'input'=>'TT','tag'=>'mo', 'output'=>'&#' . hexdec('22A4') . ';'),
100+'|-' => array( 'input'=>'|-','tag'=>'mo', 'output'=>'&#' . hexdec('22A2') . ';'),
101+'|=' => array( 'input'=>'|=','tag'=>'mo', 'output'=>'&#' . hexdec('22A8') . ';'),
102+
103+// Miscellaneous symbols
104+'ang' => array('input'=>'ang','tag'=>'mo','output'=>'&#' . hexdec('2220') . ';'),
105+'deg' => array('input'=>'deg','tag'=>'mo','output'=>'&#' . hexdec('00B0') . ';'),
106+'int' => array( 'input'=>'int','tag'=>'mo', 'output'=>'&#' . hexdec('222B') . ';'),
107+'dx' => array( 'input'=>'dx','tag'=>'mi', 'output'=>'{:d x:}', 'definition'=>TRUE), /* 2005-06-11 wes */
108+'dy' => array( 'input'=>'dy','tag'=>'mi', 'output'=>'{:d y:}', 'definition'=>TRUE), /* 2005-06-11 wes */
109+'dz' => array( 'input'=>'dz','tag'=>'mi', 'output'=>'{:d z:}', 'definition'=>TRUE), /* 2005-06-11 wes */
110+'dt' => array( 'input'=>'dt','tag'=>'mi', 'output'=>'{:d t:}', 'definition'=>TRUE), /* 2005-06-11 wes */
111+'oint' => array( 'input'=>'oint','tag'=>'mo', 'output'=>'&#' . hexdec('222E') . ';'),
112+'del' => array( 'input'=>'del','tag'=>'mo', 'output'=>'&#' . hexdec('2202') . ';'),
113+'grad' => array( 'input'=>'grad','tag'=>'mo', 'output'=>'&#' . hexdec('2207') . ';'),
114+'+-' => array( 'input'=>'+-','tag'=>'mo', 'output'=>'&#' . hexdec('00B1') . ';'),
115+'O/' => array( 'input'=>'0/','tag'=>'mo', 'output'=>'&#' . hexdec('2205') . ';'),
116+'oo' => array( 'input'=>'oo','tag'=>'mo', 'output'=>'&#' . hexdec('221E') . ';'),
117+'aleph' => array( 'input'=>'aleph','tag'=>'mo', 'output'=>'&#' . hexdec('2135') . ';'),
118+'...' => array( 'input'=>'int','tag'=>'mo', 'output'=>'...'),
119+'~' => array( 'input'=>'!~','tag'=>'mo', 'output'=>'&#' . hexdec('0020') . ';'),
120+'\\ ' => array( 'input'=>'~','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';'),
121+'quad' => array( 'input'=>'quad','tag'=>'mo', 'output'=>'&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
122+'qquad' => array( 'input'=>'qquad','tag'=>'mo', 'output'=> '&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';&#' . hexdec('00A0') . ';'),
123+'cdots' => array( 'input'=>'cdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EF') . ';'),
124+'vdots' => array( 'input'=>'vdots','tag'=>'mo', 'output'=>'&#' . hexdec('22EE') . ';'), /* 2005-06-11 wes */
125+'ddots' => array( 'input'=>'ddots','tag'=>'mo', 'output'=>'&#' . hexdec('22F1') . ';'), /* 2005-06-11 wes */
126+'diamond' => array( 'input'=>'diamond','tag'=>'mo', 'output'=>'&#' . hexdec('22C4') . ';'),
127+'square' => array( 'input'=>'square','tag'=>'mo', 'output'=>'&#' . hexdec('25A1') . ';'),
128+'|_' => array( 'input'=>'|_','tag'=>'mo', 'output'=>'&#' . hexdec('230A') . ';'),
129+'_|' => array( 'input'=>'_|','tag'=>'mo', 'output'=>'&#' . hexdec('230B') . ';'),
130+'|~' => array( 'input'=>'|~','tag'=>'mo', 'output'=>'&#' . hexdec('2308') . ';'),
131+'~|' => array( 'input'=>'~|','tag'=>'mo', 'output'=>'&#' . hexdec('2309') . ';'),
132+'CC' => array( 'input'=>'CC','tag'=>'mo', 'output'=>'&#' . hexdec('2102') . ';'),
133+'NN' => array( 'input'=>'NN','tag'=>'mo', 'output'=>'&#' . hexdec('2115') . ';'),
134+'QQ' => array( 'input'=>'QQ','tag'=>'mo', 'output'=>'&#' . hexdec('211A') . ';'),
135+'RR' => array( 'input'=>'RR','tag'=>'mo', 'output'=>'&#' . hexdec('211D') . ';'),
136+'ZZ' => array( 'input'=>'ZZ','tag'=>'mo', 'output'=>'&#' . hexdec('2124') . ';'),
137+
138+// Standard functions
139+'lim' => array( 'input'=>'lim','tag'=>'mo', 'output'=>'lim', 'underover'=>TRUE),
140+'Lim' => array( 'input'=>'Lim','tag'=>'mo', 'output'=>'Lim', 'underover'=>TRUE), /* 2005-06-11 wes */
141+'sin' => array( 'input'=>'sin','tag'=>'mo', 'output'=>'sin', 'unary'=>TRUE, 'func'=>TRUE),
142+'cos' => array( 'input'=>'cos', 'tag'=>'mo', 'output'=>'cos', 'unary'=>TRUE, 'func'=>TRUE),
143+'tan' => array( 'input'=>'tan', 'tag'=>'mo', 'output'=>'tan', 'unary'=>TRUE, 'func'=>TRUE),
144+'arcsin' => array( 'input'=>'arcsin','tag'=>'mo', 'output'=>'arcsin', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
145+'arccos' => array( 'input'=>'arccos', 'tag'=>'mo', 'output'=>'arccos', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
146+'arctan' => array( 'input'=>'arctan', 'tag'=>'mo', 'output'=>'arctan', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
147+'sinh' => array( 'input'=>'sinh','tag'=>'mo', 'output'=>'sinh', 'unary'=>TRUE, 'func'=>TRUE),
148+'cosh' => array( 'input'=>'cosh', 'tag'=>'mo', 'output'=>'cosh', 'unary'=>TRUE, 'func'=>TRUE),
149+'tanh' => array( 'input'=>'tanh', 'tag'=>'mo', 'output'=>'tanh', 'unary'=>TRUE, 'func'=>TRUE),
150+'cot' => array( 'input'=>'cot','tag'=>'mo', 'output'=>'cot', 'unary'=>TRUE, 'func'=>TRUE),
151+'sec' => array( 'input'=>'sec', 'tag'=>'mo', 'output'=>'sec', 'unary'=>TRUE, 'func'=>TRUE),
152+'csc' => array( 'input'=>'csc', 'tag'=>'mo', 'output'=>'csc', 'unary'=>TRUE, 'func'=>TRUE),
153+'coth' => array( 'input'=>'coth','tag'=>'mo', 'output'=>'coth', 'unary'=>TRUE, 'func'=>TRUE),
154+'sech' => array( 'input'=>'sech', 'tag'=>'mo', 'output'=>'sech', 'unary'=>TRUE, 'func'=>TRUE),
155+'csch' => array( 'input'=>'csch', 'tag'=>'mo', 'output'=>'csch', 'unary'=>TRUE, 'func'=>TRUE),
156+'log' => array( 'input'=>'log', 'tag'=>'mo', 'output'=>'log', 'unary'=>TRUE, 'func'=>TRUE),
157+'ln' => array( 'input'=>'ln', 'tag'=>'mo', 'output'=>'ln', 'unary'=>TRUE, 'func'=>TRUE),
158+'det' => array( 'input'=>'det', 'tag'=>'mo', 'output'=>'det', 'unary'=>TRUE, 'func'=>TRUE),
159+'dim' => array( 'input'=>'dim', 'tag'=>'mo', 'output'=>'dim'),
160+'mod' => array( 'input'=>'mod', 'tag'=>'mo', 'output'=>'mod'),
161+'gcd' => array( 'input'=>'gcd', 'tag'=>'mo', 'output'=>'gcd', 'unary'=>TRUE, 'func'=>TRUE),
162+'lcm' => array( 'input'=>'lcm', 'tag'=>'mo', 'output'=>'lcm', 'unary'=>TRUE, 'func'=>TRUE),
163+'lub' => array( 'input'=>'lub', 'tag'=>'mo', 'output'=>'lub'), /* 2005-06-11 wes */
164+'glb' => array( 'input'=>'glb', 'tag'=>'mo', 'output'=>'glb'), /* 2005-06-11 wes */
165+'min' => array( 'input'=>'min', 'tag'=>'mo', 'output'=>'min', 'underover'=>TRUE), /* 2005-06-11 wes */
166+'max' => array( 'input'=>'max', 'tag'=>'mo', 'output'=>'max', 'underover'=>TRUE), /* 2005-06-11 wes */
167+'f' => array( 'input'=>'f','tag'=>'mi', 'output'=>'f', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
168+'g' => array( 'input'=>'g', 'tag'=>'mi', 'output'=>'g', 'unary'=>TRUE, 'func'=>TRUE), //2006-9-7 DL
169+
170+// Arrows
171+'uarr' => array( 'input'=>'uarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2191') . ';'),
172+'darr' => array( 'input'=>'darr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2193') . ';'),
173+'rarr' => array( 'input'=>'rarr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
174+'->' => array( 'input'=>'->', 'tag'=>'mo', 'output'=>'&#' . hexdec('2192') . ';'),
175+'|->' => array( 'input'=>'|->', 'tag'=>'mo', 'output'=>'&#' . hexdec('21A6') . ';'), /* 2005-06-11 wes */
176+'larr' => array( 'input'=>'larr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2190') . ';'),
177+'harr' => array( 'input'=>'harr', 'tag'=>'mo', 'output'=>'&#' . hexdec('2194') . ';'),
178+'rArr' => array( 'input'=>'rArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D2') . ';'),
179+'lArr' => array( 'input'=>'lArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D0') . ';'),
180+'hArr' => array( 'input'=>'hArr', 'tag'=>'mo', 'output'=>'&#' . hexdec('21D4') . ';'),
181+
182+// Commands with argument
183+'sqrt' => array( 'input'=>'sqrt', 'tag'=>'msqrt', 'output'=>'sqrt', 'unary'=>TRUE ),
184+'root' => array( 'input'=>'root', 'tag'=>'mroot', 'output'=>'root', 'binary'=>TRUE ),
185+'frac' => array( 'input'=>'frac', 'tag'=>'mfrac', 'output'=>'/', 'binary'=>TRUE),
186+'/' => array( 'input'=>'/', 'tag'=>'mfrac', 'output'=>'/', 'infix'=>TRUE),
187+'_' => array( 'input'=>'_', 'tag'=>'msub', 'output'=>'_', 'infix'=>TRUE),
188+'^' => array( 'input'=>'^', 'tag'=>'msup', 'output'=>'^', 'infix'=>TRUE),
189+'hat' => array( 'input'=>'hat', 'tag'=>'mover', 'output'=>'&#' . hexdec('005E') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
190+'bar' => array( 'input'=>'bar', 'tag'=>'mover', 'output'=>'&#' . hexdec('00AF') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
191+'vec' => array( 'input'=>'vec', 'tag'=>'mover', 'output'=>'&#' . hexdec('2192') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
192+'dot' => array( 'input'=>'dot', 'tag'=>'mover', 'output'=>'.', 'unary'=>TRUE, 'acc'=>TRUE),
193+'ddot' => array( 'input'=>'ddot', 'tag'=>'mover', 'output'=>'..', 'unary'=>TRUE, 'acc'=>TRUE),
194+'ul' => array( 'input'=>'ul', 'tag'=>'munder', 'output'=>'&#' . hexdec('0332') . ';', 'unary'=>TRUE, 'acc'=>TRUE),
195+'avec' => array( 'input'=>'avec', 'tag'=>'munder', 'output'=>'~', 'unary'=>TRUE, 'acc'=>TRUE),
196+'text' => array( 'input'=>'text', 'tag'=>'mtext', 'output'=>'text', 'unary'=>TRUE),
197+'mbox' => array( 'input'=>'mbox', 'tag'=>'mtext', 'output'=>'mbox', 'unary'=>TRUE),
198+'"' => array( 'input'=>'"', 'tag'=>'mtext','output'=>'mbox', 'unary'=>TRUE),
199+
200+/* 2005-06-05 wes: added stackrel */
201+'stackrel' => array( 'input'=>'stackrel', 'tag'=>'mover', 'output'=>'stackrel', 'binary'=>TRUE),
202+
203+// Grouping brackets
204+'(' => array( 'input'=>'(', 'tag'=>'mo', 'output'=>'(', 'left_bracket'=>TRUE),
205+')' => array( 'input'=>')', 'tag'=>'mo', 'output'=>')', 'right_bracket'=>TRUE),
206+'[' => array( 'input'=>'[', 'tag'=>'mo', 'output'=>'[', 'left_bracket'=>TRUE),
207+']' => array( 'input'=>']', 'tag'=>'mo', 'output'=>']', 'right_bracket'=>TRUE),
208+'{' => array( 'input'=>'{', 'tag'=>'mo', 'output'=>'{', 'left_bracket'=>TRUE),
209+'}' => array( 'input'=>'}', 'tag'=>'mo', 'output'=>'}', 'right_bracket'=>TRUE),
210+'(:' => array( 'input'=>'(:', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE),
211+':)' => array( 'input'=>':)', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE),
212+'{:' => array( 'input'=>'{:', 'tag'=>'mo', 'output'=>'{:', 'left_bracket'=>TRUE, 'invisible'=>TRUE),
213+':}' => array( 'input'=>':}', 'tag'=>'mo', 'output'=>':}', 'right_bracket'=>TRUE ,'invisible'=>TRUE),
214+'<<' => array( 'input'=>'<<', 'tag'=>'mo', 'output'=>'&#' . hexdec('2329') . ';', 'left_bracket'=>TRUE), // 2005-06-07 wes
215+'>>' => array( 'input'=>'>>', 'tag'=>'mo', 'output'=>'&#' . hexdec('232A') . ';', 'right_bracket'=>TRUE) // 2005-06-07 wes
216+);
217+
218+?>
examples/includes/ASCIIMathPHP-2.0/ASCIIMathPHP-2.0.class.php+1119−0
@@ -0,0 +1,1119 @@
1+<?php
2+
3+/****
4+ * ASCIIMathPHP and associated classes:
5+ * -- XMLNode
6+ * -- MathMLNode extends XMLNode
7+ *
8+ * These classes are a PHP port of ASCIIMath
9+ * Version 1.3 Feb 19 2004, (c) Peter Jipsen http://www.chapman.edu/~jipsen
10+ *
11+ * ASCIIMathPHP Version 1.11, 26 April 2006, (c) Kee-Lin Steven Chan (kc56@cornell.edu)
12+ *
13+ * This program is free software; you can redistribute it and/or modify
14+ * it under the terms of the GNU General Public License as published by
15+ * the Free Software Foundation; either version 2 of the License, or (at
16+ * your option) any later version.
17+ *
18+ * This program is distributed in the hope that it will be useful,
19+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
20+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21+ * General Public License (at http://www.gnu.org/copyleft/gpl.html)
22+ * for more details.
23+ *
24+ * ChangeLog
25+ *
26+ * Ver 2.0
27+ * -- PHP5 only version of ASCIIMathPHP
28+ *
29+ * Ver 1.12.1
30+ * -- Included the missing setCurrExpr() method
31+ *
32+ * Ver 1.12
33+ * -- Added changes that David Lippman <DLippman@pierce.ctc.edu> made to bring ASCIIMathPHP up to
34+ * ASCIIMath 1.4.7 functionality.
35+ * -- Added parseIntExpr, for intermediate expression parsing rule, allowing x^2/x^3 to render as (x^2)/(x^3)
36+ * -- Added quotes as another way of designating text; "hello" is equivalent to text(hello)
37+ * -- Added FUNC designator to allow sin, cos, etc to act as functions, so sin(x)/x renders as {sin(x)}/x
38+ *
39+ * Ver 1.11
40+ * -- Fixed bug that stopped script execution for incomplete expressions
41+ * -- Changed the algorithm for parsing expressions so that it matches the longest string possible (greedy)
42+ *
43+ * Ver 1.10
44+ * -- Added definition support
45+ * -- Added stackrel support
46+ * -- Added a bunch of different symbols etc. >>, << and definitions like dx, dy, dz etc.
47+ *
48+ * Ver 1.02
49+ * -- Fixed bug with mbox and text
50+ * -- Fixed spacing bug with mbox and text
51+ *
52+ * Ver 1.01
53+ * -- Fixed Bug that did not parse symbols greater than a single character
54+ * correctly when appearing at end of expression.
55+ *
56+ ***/
57+
58+class XMLNode
59+{
60+ // Private variables
61+ var $_id;
62+ var $_name;
63+ var $_content;
64+ var $_mt_elem_flg;
65+ var $_attr_arr;
66+ var $_child_arr;
67+ var $_nmspc;
68+ var $_nmspc_alias;
69+ var $_parent_id;
70+ var $_parent_node;
71+
72+ function XMLNode($id = NULL)
73+ {
74+ $this->_id = isset($id) ? $id : md5(uniqid(rand(),1));
75+ $this->_name = '';
76+ $this->_content = '';
77+ $this->_mt_elem_flg = FALSE;
78+ $this->_attr_arr = array();
79+ $this->_child_arr = array();
80+ $this->_nmspc = '';
81+ $this->_nmspc_alias = '';
82+ $this->_parent_id = FALSE;
83+ $this->_parent_node = NULL;
84+ }
85+
86+ function addChild(&$node)
87+ {
88+ $this->_child_arr[$node->getId()] = $node;
89+ $node->setParentId($this->_id);
90+ $node->setParentNode($this);
91+ }
92+
93+ function addChildArr(&$node_arr)
94+ {
95+ $key_arr = array_keys($node_arr);
96+ $num_key = count($key_arr);
97+
98+ for ($i = 0; $i < $num_key; $i++) {
99+ $node = $node_arr[$key_arr[$i]];
100+ $this->addChild($node);
101+ }
102+ }
103+
104+ function insertChildBefore($idx,&$node)
105+ {
106+ $key_arr = array_keys($this->_child_arr);
107+ $num_key = count($key_arr);
108+ $tmp_arr = arry();
109+
110+ for ($i = 0;$i < $num_key;$i++) {
111+ if ($i == $idx) {
112+ $tmp_arr[$node->getId()] = $node;
113+ }
114+ $tmp_arr[$key_arr[$i]] = $this->_child_arr[$key_arr[$i]];
115+ }
116+ $this->_child_arr = $tmp_arr;
117+ }
118+
119+ function insertChildAfter($idx,&$node)
120+ {
121+ $key_arr = array_keys($this->_child_arr);
122+ $num_key = count($key_arr);
123+ $tmp_arr = arry();
124+
125+ for ($i = 0;$i < $num_key;$i++) {
126+ $tmp_arr[$key_arr[$i]] = $this->_child_arr[$key_arr[$i]];
127+ if ($i == $idx) {
128+ $tmp_arr[$node->getId()] = $node;
129+ }
130+ }
131+ $this->_child_arr = $tmp_arr;
132+ }
133+
134+ function setId($id)
135+ {
136+ $this->_id = $id;
137+ }
138+
139+ function setName($name)
140+ {
141+ $this->_name = $name;
142+ }
143+
144+ function setNamepace($nmspc)
145+ {
146+ $this->_nmspc = $nmspc;
147+ }
148+
149+ function setNamespaceAlias($nmspc_alias)
150+ {
151+ $this->_nmspc_alias = $nmspc_alias;
152+ }
153+
154+ function setContent($content)
155+ {
156+ $this->_content = $content;
157+ }
158+
159+ function setEmptyElem($mt_elem_flg)
160+ {
161+ $this->_mt_elem_flg = $mt_elem_flg;
162+ }
163+
164+ function setAttr($attr_nm,$attr_val)
165+ {
166+ $this->_attr_arr[$attr_nm] = $attr_val;
167+ }
168+
169+ function setAttrArr($attr_arr)
170+ {
171+ $this->_attr_arr = $attr_arr;
172+ }
173+
174+ function setParentId($id)
175+ {
176+ $this->_parent_id = $id;
177+ }
178+
179+ function setParentNode(&$node)
180+ {
181+ $this->_parent_node = $node;
182+ }
183+
184+ function getId()
185+ {
186+ return($this->_id);
187+ }
188+
189+ function getName()
190+ {
191+ return($this->_name);
192+ }
193+
194+ function getNamespace()
195+ {
196+ return($this->_nmspc);
197+ }
198+
199+ function getNamespaceAlias()
200+ {
201+ return($this->_nmspc_alias);
202+ }
203+
204+ function getContent()
205+ {
206+ return($this->_content);
207+ }
208+
209+ function getAttr($attr_nm)
210+ {
211+ if (isset($this->_attr_arr[$attr_nm])) {
212+ return($this->_attr_arr[$attr_nm]);
213+ } else {
214+ return(NULL);
215+ }
216+ }
217+
218+ function getAttrArr()
219+ {
220+ return($this->_attr_arr);
221+ }
222+
223+ function getParentId()
224+ {
225+ return($this->parent_id);
226+ }
227+
228+ function getParentNode()
229+ {
230+ return($this->_parent_node);
231+ }
232+
233+ function getChild($id)
234+ {
235+ if (isset($this->_child_arr[$id])) {
236+ return($this->_child_arr[$id]);
237+ } else {
238+ return(FALSE);
239+ }
240+ }
241+
242+ function getFirstChild()
243+ {
244+ $id_arr = array_keys($this->_child_arr);
245+ $num_child = count($id_arr);
246+
247+ if ($num_child > 0) {
248+ return($this->_child_arr[$id_arr[0]]);
249+ } else {
250+ return(FALSE);
251+ }
252+ }
253+
254+ function getLastChild()
255+ {
256+ $id_arr = array_keys($this->_child_arr);
257+ $num_child = count($id_arr);
258+
259+ if ($num_child > 0) {
260+ return($this->_child_arr[$id_arr[$num_child - 1]]);
261+ } else {
262+ return(FALSE);
263+ }
264+ }
265+
266+ function getChildByIdx($idx)
267+ {
268+ $id_arr = array_keys($this->_child_arr);
269+
270+ if (isset($this->_child_arr[$id_arr[$idx]])) {
271+ return($this->_child_arr[$id_arr[$idx]]);
272+ } else {
273+ return(FALSE);
274+ }
275+ }
276+
277+ function getNumChild()
278+ {
279+ return(count($this->_child_arr));
280+ }
281+
282+ function removeChild($id)
283+ {
284+ unset($this->_child_arr[$id]);
285+ }
286+
287+ function removeChildByIdx($idx)
288+ {
289+ $key_arr = array_keys($this->_child_arr);
290+ unset($this->_child_arr[$key_arr[$idx]]);
291+ }
292+
293+ function removeFirstChild()
294+ {
295+ $key_arr = array_keys($this->_child_arr);
296+ unset($this->_child_arr[$key_arr[0]]);
297+ }
298+
299+ function removeLastChild()
300+ {
301+ $key_arr = array_keys($this->_child_arr);
302+ unset($this->_child_arr[$key_arr[count($key_arr)-1]]);
303+ }
304+
305+ function dumpXML($indent_str = "\t")
306+ {
307+ $attr_txt = $this->_dumpAttr();
308+ $name = $this->_dumpName();
309+ $xmlns = $this->_dumpXmlns();
310+ $lvl = $this->_getCurrentLevel();
311+ $indent = str_pad('',$lvl,$indent_str);
312+
313+ if ($this->_mt_elem_flg) {
314+ $tag = "$indent<$name$xmlns$attr_txt />";
315+ return($tag);
316+ } else {
317+ $key_arr = array_keys($this->_child_arr);
318+ $num_child = count($key_arr);
319+
320+ $tag = "$indent<$name$xmlns$attr_txt>$this->_content";
321+
322+ for ($i = 0;$i < $num_child;$i++) {
323+ $node = $this->_child_arr[$key_arr[$i]];
324+
325+ $child_txt = $node->dumpXML($indent_str);
326+ $tag .= "\n$child_txt";
327+ }
328+
329+ $tag .= ($num_child > 0 ? "\n$indent</$name>" : "</$name>");
330+ return($tag);
331+ }
332+ }
333+
334+ function _dumpAttr()
335+ {
336+ $id_arr = array_keys($this->_attr_arr);
337+ $id_arr_cnt = count($id_arr);
338+ $attr_txt = '';
339+
340+ for($i = 0;$i < $id_arr_cnt;$i++) {
341+ $key = $id_arr[$i];
342+ $attr_txt .= " $key=\"{$this->_attr_arr[$key]}\"";
343+ }
344+
345+ return($attr_txt);
346+ }
347+
348+ function _dumpName()
349+ {
350+ $alias = $this->getNamespaceAlias();
351+ if ($alias == '') {
352+ return($this->getName());
353+ } else {
354+ return("$alias:" . $this->getName());
355+ }
356+ }
357+
358+ function _dumpXmlns()
359+ {
360+ $nmspc = $this->getNamespace();
361+ $alias = $this->getNamespaceAlias();
362+
363+ if ($nmspc != '') {
364+ if ($alias == '') {
365+ return(" xmlns=\"" . $nmspc . "\"");
366+ } else {
367+ return(" xmlns:$alias=\"" . $nmspc . "\"");
368+ }
369+ } else {
370+ return('');
371+ }
372+ }
373+
374+ function _getCurrentLevel()
375+ {
376+ if ($this->_parent_id === FALSE) {
377+ return(0);
378+ } else {
379+ $node = $this->getParentNode();
380+ $lvl = $node->_getCurrentLevel();
381+ $lvl++;
382+ return($lvl);
383+ }
384+ }
385+}
386+
387+class MathMLNode extends XMLNode
388+{
389+ function MathMLNode($id = NULL)
390+ {
391+ parent::XMLNode($id);
392+ }
393+
394+ function removeBrackets()
395+ {
396+ if ($this->_name == 'mrow') {
397+ if ($c_node_0 = $this->getFirstChild()) {
398+ $c_node_0->isLeftBracket() ? $this->removeFirstChild() : 0;
399+ }
400+
401+ if ($c_node_0 = $this->getLastChild()) {
402+ $c_node_0->isRightBracket() ? $this->removeLastChild() : 0;
403+ }
404+ }
405+ }
406+
407+ function isLeftBracket()
408+ {
409+ switch ($this->_content) {
410+ case '{':
411+ case '[':
412+ case '(':
413+ return(TRUE);
414+ break;
415+ }
416+ return(FALSE);
417+ }
418+
419+ function isRightBracket()
420+ {
421+ switch ($this->_content) {
422+ case '}':
423+ case ']':
424+ case ')':
425+ return(TRUE);
426+ break;
427+ }
428+ return(FALSE);
429+ }
430+}
431+
432+class ASCIIMathPHP
433+{
434+ var $_expr;
435+ var $_curr_expr;
436+ var $_prev_expr;
437+ var $_symbol_arr;
438+ var $_node_arr;
439+ var $_node_cntr;
440+
441+ function ASCIIMathPHP($symbol_arr,$expr = NULL)
442+ {
443+ $this->_symbol_arr = $symbol_arr;
444+ if (isset($expr)) {
445+ $this->setExpr($expr);
446+ }
447+ }
448+
449+ /**
450+ * Returns an empty node (containing a non-breaking space) 26-Apr-2006
451+ *
452+ * Used when an expression is incomplete
453+ *
454+ * @return object
455+ *
456+ * @access private
457+ */
458+ function emptyNode()
459+ {
460+ $tmp_node = $this->createNode();
461+ $tmp_node->setName('mn');
462+ $tmp_node->setContent('&#' . hexdec('200B') . ';');
463+ return $tmp_node;
464+ }
465+
466+ function pushExpr($prefix) // 2005-06-11 wes
467+ {
468+ $this->_curr_expr = $prefix . $this->_curr_expr;
469+ }
470+
471+ function setExpr($expr)
472+ {
473+ $this->_expr = $expr;
474+ $this->_curr_expr = $expr;
475+ $this->_prev_expr = $expr;
476+
477+ $this->_node_arr = array();
478+ $this->_node_cntr = 0;
479+ }
480+
481+ function genMathML($attr_arr = NULL)
482+ {
483+ // <math> node
484+ $node_0 = $this->createNode();
485+ $node_0->setName('math');
486+ $node_0->setNamepace('http://www.w3.org/1998/Math/MathML');
487+
488+ // <mstyle> node
489+ if (isset($attr_arr)) {
490+ $node_1 = $this->createNode();
491+ $node_1->setName('mstyle');
492+ $node_1->setAttrArr($attr_arr);
493+
494+ $node_arr = $this->parseExpr();
495+
496+ $node_1->addChildArr($node_arr);
497+ $node_0->addChild($node_1);
498+ } else {
499+ $node_arr = $this->parseExpr();
500+ $node_0->addChildArr($node_arr);
501+ }
502+
503+ return TRUE;
504+ }
505+
506+ /*
507+ function mergeNodeArr(&$node_arr_0,&$node_arr_1)
508+ {
509+ $key_arr_0 = array_keys($node_arr_0);
510+ $key_arr_1 = array_keys($node_arr_1);
511+
512+ $num_key_0 = count($key_arr_0);
513+ $num_key_1 = count($key_arr_1);
514+
515+ $merge_arr = array();
516+
517+ for ($i = 0;$i < $num_key_0;$i++) {
518+ $merge_arr[$key_arr_0[$i]] = $node_arr_0[$key_arr_0[$i]];
519+ }
520+
521+ for ($j = 0;$j < $num_key_1;$i++) {
522+ $merge_arr[$key_arr_1[$i]] = $node_arr_1[$key_arr_1[$i]];
523+ }
524+
525+ return($merge_arr);
526+ }
527+ */
528+
529+ //Broken out of parseExpr Sept 7, 2006 David Lippman for
530+ //ASCIIMathML 1.4.7 compatibility
531+ function parseIntExpr()
532+ {
533+ $sym_0 = $this->getSymbol();
534+ $node_0 = $this->parseSmplExpr();
535+ $sym = $this->getSymbol();
536+
537+ if (isset($sym['infix']) && $sym['input'] != '/') {
538+ $this->chopExpr($sym['symlen']);
539+ $node_1 = $this->parseSmplExpr();
540+
541+ if ($node_1 === FALSE) { //show box in place of missing argument
542+ $node_1 = $this->emptyNode();//??
543+ } else {
544+ $node_1->removeBrackets();
545+ }
546+
547+ // If 'sub' -- subscript
548+ if ($sym['input'] == '_') {
549+
550+ $sym_1 = $this->getSymbol();
551+
552+ // If 'sup' -- superscript
553+ if ($sym_1['input'] == '^') {
554+ $this->chopExpr($sym_1['symlen']);
555+ $node_2 = $this->parseSmplExpr();
556+ $node_2->removeBrackets();
557+
558+ $node_3 = $this->createNode();
559+ $node_3->setName(isset($sym_0['underover']) ? 'munderover' : 'msubsup');
560+ $node_3->addChild($node_0);
561+ $node_3->addChild($node_1);
562+ $node_3->addChild($node_2);
563+
564+ $node_4 = $this->createNode();
565+ $node_4->setName('mrow');
566+ $node_4->addChild($node_3);
567+
568+ return $node_4;
569+ } else {
570+ $node_2 = $this->createNode();
571+ $node_2->setName(isset($sym_0['underover']) ? 'munder' : 'msub');
572+ $node_2->addChild($node_0);
573+ $node_2->addChild($node_1);
574+
575+ return $node_2;
576+ }
577+ } else {
578+ $node_2 = $this->createNode();
579+ $node_2->setName($sym['tag']);
580+ $node_2->addChild($node_0);
581+ $node_2->addChild($node_1);
582+
583+ return($node_2);
584+ }
585+ } elseif ($node_0 !== FALSE) {
586+ return($node_0);
587+ } else {
588+ return $this->emptyNode();
589+ }
590+
591+ }
592+
593+ function parseExpr()
594+ {
595+ // Child/Fragment array
596+ $node_arr = array();
597+
598+ // Deal whole expressions like 'ax + by + c = 0' etc.
599+ do {
600+ $sym_0 = $this->getSymbol();
601+ $node_0 = $this->parseIntExpr();
602+ $sym = $this->getSymbol();
603+ // var_dump($sym);
604+
605+ if (isset($sym['infix']) && $sym['input'] == '/') {
606+ $this->chopExpr($sym['symlen']);
607+ $node_1 = $this->parseIntExpr();
608+
609+ if ($node_1 === FALSE) { //should show box in place of missing argument
610+ $node_1 = $this->emptyNode();
611+ continue;
612+ }
613+
614+ $node_1->removeBrackets();
615+
616+ // If 'div' -- divide
617+ $node_0->removeBrackets();
618+ $node_2 = $this->createNode();
619+ $node_2->setName($sym['tag']);
620+ $node_2->addChild($node_0);
621+ $node_2->addChild($node_1);
622+ $node_arr[$node_2->getId()] = $node_2;
623+
624+ } elseif ($node_0 !== FALSE) {
625+ $node_arr[$node_0->getId()] = $node_0;
626+ }
627+ } while (!isset($sym['right_bracket']) && $sym !== FALSE && $sym['output'] != '');
628+
629+ //var_dump($sym);
630+ // Possibly to deal with matrices
631+ if (isset($sym['right_bracket'])) {
632+ $node_cnt = count($node_arr);
633+ $key_node_arr = array_keys($node_arr);
634+
635+ if ($node_cnt > 1) {
636+ $node_5 = $node_arr[$key_node_arr[$node_cnt-1]];
637+ $node_6 = $node_arr[$key_node_arr[$node_cnt-2]];
638+ } else {
639+ $node_5 = FALSE;
640+ $node_6 = FALSE;
641+ }
642+
643+ // Dealing with matrices
644+ if ($node_5 !== FALSE && $node_6 !== FALSE &&
645+ $node_cnt > 1 &&
646+ $node_5->getName() == 'mrow' &&
647+ $node_6->getName() == 'mo' &&
648+ $node_6->getContent() == ',') {
649+
650+ // Checking if Node 5 has a LastChild
651+ if ($node_7 = $node_5->getLastChild()) {
652+ $node_7_cntnt = $node_7->getContent();
653+ } else {
654+ $node_7_cntnt = FALSE;
655+ }
656+
657+ // If there is a right bracket
658+ if ($node_7 !== FALSE && ($node_7_cntnt == ']' || $node_7_cntnt == ')')) {
659+
660+ // Checking if Node 5 has a firstChild
661+ if ($node_8 = $node_5->getFirstChild()) {
662+ $node_8_cntnt = $node_8->getContent();
663+ } else {
664+ $node_8_cntnt = FALSE;
665+ }
666+
667+ // If there is a matching left bracket
668+ if ($node_8 !== FALSE &&
669+ (($node_8_cntnt == '(' && $node_7_cntnt == ')' && $sym['output'] != '}') ||
670+ ($node_8_cntnt == '[' && $node_7_cntnt == ']'))) {
671+
672+ $is_mtrx_flg = TRUE;
673+ $comma_pos_arr = array();
674+
675+ $i = 0;
676+
677+ while ($i < $node_cnt && $is_mtrx_flg) {
678+ $tmp_node = $node_arr[$key_node_arr[$i]];
679+
680+ if($tmp_node_first = $tmp_node->getFirstChild()) {
681+ $tnfc = $tmp_node_first->getContent();
682+ } else {
683+ $tnfc = FALSE;
684+ }
685+
686+ if($tmp_node_last = $tmp_node->getLastChild()) {
687+ $tnlc = $tmp_node_last->getContent();
688+ } else {
689+ $tnlc = FALSE;
690+ }
691+
692+ if (isset($key_node_arr[$i+1])) {
693+ $next_tmp_node = $node_arr[$key_node_arr[$i+1]];
694+ $ntnn = $next_tmp_node->getName();
695+ $ntnc = $next_tmp_node->getContent();
696+ } else {
697+ $ntnn = FALSE;
698+ $ntnc = FALSE;
699+ }
700+
701+ // Checking each node in node array for matrix criteria
702+ if ($is_mtrx_flg) {
703+ $is_mtrx_flg = $tmp_node->getName() == 'mrow' &&
704+ ($i == $node_cnt-1 || $ntnn == 'mo' && $ntnc == ',') &&
705+ $tnfc == $node_8_cntnt && $tnlc == $node_7_cntnt;
706+ }
707+
708+ if ($is_mtrx_flg) {
709+ for ($j = 0;$j < $tmp_node->getNumChild();$j++) {
710+ $tmp_c_node = $tmp_node->getChildByIdx($j);
711+
712+ if ($tmp_c_node->getContent() == ',') {
713+ $comma_pos_arr[$i][] = $j;
714+ }
715+ }
716+ }
717+
718+ if ($is_mtrx_flg && $i > 1) {
719+
720+ $cnt_cpan = isset($comma_pos_arr[$i]) ? count($comma_pos_arr[$i]) : NULL;
721+ $cnt_cpap = isset($comma_pos_arr[$i-2]) ? count($comma_pos_arr[$i-2]) : NULL;
722+ $is_mtrx_flg = $cnt_cpan == $cnt_cpap;
723+ }
724+
725+ $i += 2;
726+ }
727+
728+ // If the node passes the matrix tests
729+ if ($is_mtrx_flg) {
730+ $tab_node_arr = array();
731+
732+ for ($i = 0;$i < $node_cnt;$i += 2) {
733+ $tmp_key_node_arr = array_keys($node_arr);
734+ if (!($tmp_node = $node_arr[$tmp_key_node_arr[0]])) {
735+ break;
736+ }
737+ $num_child = $tmp_node->getNumChild();
738+ $k = 0;
739+
740+ $tmp_node->removeFirstChild();
741+
742+ $row_node_arr = array();
743+ $row_frag_node_arr = array();
744+
745+ for ($j = 1;$j < ($num_child-1);$j++) {
746+ if (isset($comma_pos_arr[$i][$k]) &&
747+ $j == $comma_pos_arr[$i][$k]) {
748+
749+ $tmp_node->removeFirstChild();
750+
751+ $tmp_c_node = $this->createNode();
752+ $tmp_c_node->setName('mtd');
753+ $tmp_c_node->addChildArr($row_frag_node_arr);
754+ $row_frag_node_arr = array();
755+
756+ $row_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
757+
758+ $k++;
759+ } else {
760+
761+ if ($tmp_c_node = $tmp_node->getFirstChild()) {
762+ $row_frag_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
763+ $tmp_node->removeFirstChild();
764+ }
765+ }
766+ }
767+
768+ $tmp_c_node = $this->createNode();
769+ $tmp_c_node->setName('mtd');
770+ $tmp_c_node->addChildArr($row_frag_node_arr);
771+
772+ $row_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
773+
774+ if (count($node_arr) > 2) {
775+ $tmp_key_node_arr = array_keys($node_arr);
776+ unset($node_arr[$tmp_key_node_arr[0]]);
777+ unset($node_arr[$tmp_key_node_arr[1]]);
778+ }
779+
780+ $tmp_c_node = $this->createNode();
781+ $tmp_c_node->setName('mtr');
782+ $tmp_c_node->addChildArr($row_node_arr);
783+
784+ $tab_node_arr[$tmp_c_node->getId()] = $tmp_c_node;
785+ }
786+
787+ $tmp_c_node = $this->createNode();
788+ $tmp_c_node->setName('mtable');
789+ $tmp_c_node->addChildArr($tab_node_arr);
790+
791+ if (isset($sym['invisible'])) {
792+ $tmp_c_node->setAttr('columnalign','left');
793+ }
794+
795+ $key_node_arr = array_keys($node_arr);
796+ $tmp_c_node->setId($key_node_arr[0]);
797+
798+ $node_arr[$tmp_c_node->getId()] = $tmp_c_node;
799+ }
800+ }
801+ }
802+ }
803+
804+ $this->chopExpr($sym['symlen']);
805+ if (!isset($sym['invisible'])) {
806+ $node_7 = $this->createNode();
807+ $node_7->setName('mo');
808+ $node_7->setContent($sym['output']);
809+ $node_arr[$node_7->getId()] = $node_7;
810+ }
811+ }
812+
813+ return($node_arr);
814+ }
815+
816+ function parseSmplExpr()
817+ {
818+ $sym = $this->getSymbol();
819+
820+ if (!$sym || isset($sym['right_bracket'])) //return FALSE;
821+ return $this->emptyNode();
822+
823+ $this->chopExpr($sym['symlen']);
824+
825+ // 2005-06-11 wes: add definition type support
826+ if(isset($sym['definition'])) {
827+ $this->pushExpr($sym['output']);
828+ $sym = $this->getSymbol();
829+ $this->chopExpr($sym['symlen']);
830+ }
831+
832+ if (isset($sym['left_bracket'])) {
833+ $node_arr = $this->parseExpr();
834+
835+ if (isset($sym['invisible'])) {
836+ $node_0 = $this->createNode();
837+ $node_0->setName('mrow');
838+ $node_0->addChildArr($node_arr);
839+
840+ return($node_0);
841+ } else {
842+ $node_0 = $this->createNode();
843+ $node_0->setName('mo');
844+ $node_0->setContent($sym['output']);
845+
846+ $node_1 = $this->createNode();
847+ $node_1->setName('mrow');
848+ $node_1->addChild($node_0);
849+ $node_1->addChildArr($node_arr);
850+
851+ return($node_1);
852+ }
853+ } elseif (isset($sym['unary'])) {
854+
855+ if ($sym['input'] == 'sqrt') {
856+ $node_0 = $this->parseSmplExpr();
857+ $node_0->removeBrackets();
858+
859+ $node_1 = $this->createNode();
860+ $node_1->setName($sym['tag']);
861+ $node_1->addChild($node_0);
862+
863+ return($node_1);
864+ } elseif (isset($sym['func'])) { //added 2006-9-7 David Lippman
865+ $expr = ltrim($this->getCurrExpr());
866+ $st = $expr{0};
867+ $node_0 = $this->parseSmplExpr();
868+ //$node_0->removeBrackets();
869+ if ($st=='^' || $st == '_' || $st=='/' || $st=='|' || $st==',') {
870+ $node_1 = $this->createNode();
871+ $node_1->setName($sym['tag']);
872+ $node_1->setContent($sym['output']);
873+ $this->setCurrExpr($expr);
874+ return($node_1);
875+ } else {
876+ $node_1 = $this->createNode();
877+ $node_1->setName('mrow');
878+ $node_2 = $this->createNode();
879+ $node_2->setName($sym['tag']);
880+ $node_2->setContent($sym['output']);
881+ $node_1->addChild($node_2);
882+ $node_1->addChild($node_0);
883+ return($node_1);
884+ }
885+ } elseif ($sym['input'] == 'text' || $sym['input'] == 'mbox' || $sym['input'] == '"') {
886+ $expr = ltrim($this->getCurrExpr());
887+ if ($sym['input']=='"') {
888+ $end_brckt = '"';
889+ $txt = substr($expr,0,strpos($expr,$end_brckt));
890+ } else {
891+ switch($expr{0}) {
892+ case '(':
893+ $end_brckt = ')';
894+ break;
895+ case '[':
896+ $end_brckt = ']';
897+ break;
898+ case '{':
899+ $end_brckt = '}';
900+ break;
901+ default:
902+ $end_brckt = chr(11); // A character that will never be matched.
903+ break;
904+ }
905+ $txt = substr($expr,1,strpos($expr,$end_brckt)-1);
906+ }
907+
908+ //$txt = substr($expr,1,strpos($expr,$end_brckt)-1);
909+ $len = strlen($txt);
910+
911+ $node_0 = $this->createNode();
912+ $node_0->setName('mrow');
913+
914+ if ($len > 0) {
915+ if ($txt{0} == " ") {
916+ $node_1 = $this->createNode();
917+ $node_1->setName('mspace');
918+ $node_1->setAttr('width','1ex');
919+
920+ $node_0->addChild($node_1);
921+ }
922+
923+ $node_3 = $this->createNode();
924+ $node_3->setName($sym['tag']);
925+ $node_3->setContent(trim($txt));
926+
927+ $node_0->addChild($node_3);
928+
929+ if ($len > 1 && $txt{$len-1} == " ") {
930+ $node_2 = $this->createNode();
931+ $node_2->setName('mspace');
932+ $node_2->setAttr('width','1ex');
933+
934+ $node_0->addChild($node_2);
935+ }
936+
937+ $this->chopExpr($len+2);
938+ }
939+ return($node_0);
940+
941+ } elseif (isset($sym['acc'])) {
942+ $node_0 = $this->parseSmplExpr();
943+ $node_0->removeBrackets();
944+
945+ $node_1 = $this->createNode();
946+ $node_1->setName($sym['tag']);
947+ $node_1->addChild($node_0);
948+
949+ $node_2 = $this->createNode();
950+ $node_2->setName('mo');
951+ $node_2->setContent($sym['output']);
952+
953+ $node_1->addChild($node_2);
954+ return($node_1);
955+ } else {
956+ // Font change commands -- to complete
957+ }
958+ } elseif (isset($sym['binary'])) {
959+ $node_arr = array();
960+
961+ $node_0 = $this->parseSmplExpr();
962+ $node_0->removeBrackets();
963+
964+ $node_1 = $this->parseSmplExpr();
965+ $node_1->removeBrackets();
966+
967+ /* 2005-06-05 wes: added stackrel */
968+ if ($sym['input'] == 'root' || $sym['input'] == 'stackrel') {
969+ $node_arr[$node_1->getId()] = $node_1;
970+ $node_arr[$node_0->getId()] = $node_0;
971+ } elseif ($sym['input'] == 'frac') {
972+ $node_arr[$node_0->getId()] = $node_0;
973+ $node_arr[$node_1->getId()] = $node_1;
974+ }
975+
976+ $node_2 = $this->createNode();
977+ $node_2->setName($sym['tag']);
978+ $node_2->addChildArr($node_arr);
979+
980+ return($node_2);
981+ } elseif (isset($sym['infix'])) {
982+ $node_0 = $this->createNode();
983+ $node_0->setName('mo');
984+ $node_0->setContent($sym['output']);
985+
986+ return($node_0);
987+ } elseif (isset($sym['space'])) {
988+ $node_0 = $this->createNode();
989+ $node_0->setName('mrow');
990+
991+ $node_1 = $this->createNode();
992+ $node_1->setName('mspace');
993+ $node_1->setAttr('width',$sym['space']);
994+
995+ $node_2 = $this->createNode();
996+ $node_2->setName($sym['tag']);
997+ $node_2->setContent($sym['output']);
998+
999+ $node_3 = $this->createNode();
1000+ $node_3->setName('mspace');
1001+ $node_3->setAttr('width',$sym['space']);
1002+
1003+ $node_0->addChild($node_1);
1004+ $node_0->addChild($node_2);
1005+ $node_0->addChild($node_3);
1006+
1007+ return($node_0);
1008+ } else {
1009+
1010+ // A constant
1011+ $node_0 = $this->createNode();
1012+ $node_0->setName($sym['tag']);
1013+ $node_0->setContent($sym['output']);
1014+ return($node_0);
1015+ }
1016+
1017+ // Return an empty node
1018+ return $this->emptyNode();
1019+ }
1020+
1021+ function getMathML()
1022+ {
1023+ $root = $this->_node_arr[0];
1024+ return($root->dumpXML());
1025+ }
1026+
1027+ function getCurrExpr()
1028+ {
1029+ return($this->_curr_expr);
1030+ }
1031+
1032+ function setCurrExpr($str)
1033+ {
1034+ $this->_curr_expr = $str;
1035+ }
1036+
1037+ function getExpr()
1038+ {
1039+ return($this->_expr);
1040+ }
1041+
1042+ function getPrevExpr()
1043+ {
1044+ return($this->_prev_expr);
1045+ }
1046+
1047+ function createNode()
1048+ {
1049+ $node = new MathMLNode($this->_node_cntr);
1050+ // $node->setNamespaceAlias('m');
1051+ $this->_node_arr[$this->_node_cntr] = $node;
1052+ $this->_node_cntr++;
1053+ return($node);
1054+ }
1055+
1056+ /**
1057+ * Gets the largest symbol in the expression (greedy). Changed from non-greedy 26-Apr-2006
1058+ *
1059+ * @parameter boolean[optional] Chop original string?
1060+ *
1061+ * @return mixed
1062+ *
1063+ * @access private
1064+ */
1065+ function getSymbol($chop_flg = FALSE)
1066+ {
1067+ // Implemented a reverse symbol matcher.
1068+ // Instead of going front to back, it goes back to front. Steven 26-Apr-2006
1069+ $chr_cnt = strlen($this->_curr_expr);
1070+
1071+ if ($chr_cnt == 0) return FALSE;
1072+
1073+ for ($i = $chr_cnt; $i > 0; $i--) {
1074+ $sym_0 = substr($this->_curr_expr,0,$i);
1075+
1076+ // Reading string for numeric values
1077+ if (is_numeric($sym_0)) {
1078+
1079+ if ($chop_flg) $this->chopExpr($i);
1080+ return array('input'=>$sym_0, 'tag'=>'mn', 'output'=>$sym_0, 'symlen'=>$i);
1081+
1082+ } elseif (isset($this->_symbol_arr[$sym_0])) {
1083+
1084+ if ($chop_flg) $this->chopExpr($i);
1085+ $sym_arr = $this->_symbol_arr[$sym_0];
1086+ $sym_arr['symlen'] = $i;
1087+ return $sym_arr;
1088+ }
1089+ }
1090+
1091+ // Reading string for alphabetic constants and the minus sign
1092+ $char = $this->_curr_expr{0};
1093+ $len_left = $chop_flg ? $this->chopExpr(1) : strlen($this->_curr_expr)-1;
1094+
1095+ // Deals with expressions of length 1
1096+ if ($len_left == 0 && isset($this->_symbol_arr[$char])) {
1097+ $sym_arr = $this->_symbol_arr[$char];
1098+ $sym_arr['symlen'] = 1;
1099+ return $sym_arr;
1100+ } else {
1101+ $tag = preg_match('/[a-z]/i',$char) ? 'mi' : 'mo';
1102+ return array('input'=>$char, 'tag'=>$tag, 'output'=>$char, 'symlen'=>1);
1103+ }
1104+ }
1105+
1106+ function chopExpr($strlen)
1107+ {
1108+ $this->_prev_expr = $this->_curr_expr;
1109+
1110+ if ($strlen == strlen($this->_curr_expr)) {
1111+ $this->_curr_expr = '';
1112+ return(0);
1113+ } else {
1114+ $this->_curr_expr = ltrim(substr($this->_curr_expr,$strlen));
1115+ return(strlen($this->_curr_expr));
1116+ }
1117+ }
1118+}
1119+?>
examples/includes/ASCIIMathPHP-2.0/htmlMathML.js+86−0
@@ -0,0 +1,86 @@
1+/* March 19, 2004 MathHTML (c) Peter Jipsen http://www.chapman.edu/~jipsen
2+This program is free software; you can redistribute it and/or modify
3+it under the terms of the GNU General Public License as published by
4+the Free Software Foundation; either version 2 of the License, or (at
5+your option) any later version.
6+This program is distributed in the hope that it will be useful, but
7+WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8+or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
9+(at http://www.gnu.org/copyleft/gpl.html) for more details.*/
10+
11+function convertMath(node) {// for Gecko
12+ if (node.nodeType==1) {
13+ var newnode =
14+ document.createElementNS("http://www.w3.org/1998/Math/MathML",
15+ node.nodeName.toLowerCase());
16+ for(var i=0; i < node.attributes.length; i++) {
17+ if (node.attributes[i].nodeName == 'displaystyle') {
18+ newnode.setAttribute(node.attributes[i].nodeName,node.attributes[i].nodeValue);
19+ }
20+ }
21+ for (var i=0; i<node.childNodes.length; i++) {
22+ var st = node.childNodes[i].nodeValue;
23+ if (st==null || st.slice(0,1)!=" " && st.slice(0,1)!="\n")
24+ newnode.appendChild(convertMath(node.childNodes[i]));
25+ }
26+ return newnode;
27+ }
28+ else return node;
29+}
30+function convert() {
31+
32+ if (document.createElementNS) {
33+ var mmlnode = document.getElementsByTagName("span");
34+
35+ for (var i=0; i<mmlnode.length; i++) {
36+ var tmp_node = mmlnode[i];
37+ if (tmp_node.className == 'asciimath') {
38+ tmp_node.replaceChild(convertMath(tmp_node.firstChild),tmp_node.firstChild);
39+ /*
40+ for (var j=0;j<tmp_node.childNodes.length;j++) {
41+ if (tmp_node.childNodes[j].nodeType != 3) {
42+
43+ }
44+ }
45+ */
46+ }
47+ }
48+ } else {
49+ var st,node,newnode;
50+ var mmlnode = document.getElementsByTagName("math");
51+
52+ for (var i=0; i<mmlnode.length; i++) {
53+ var str = "";
54+ node = mmlnode[i];
55+ while (node.nodeName!="/MATH" && node.nextSibling) {
56+ st = node.nodeName.toLowerCase();
57+ if (st=="#text") {
58+ str += node.nodeValue;
59+ } else {
60+ str += (st.slice(0,1)=="/" ? "</m:"+st.slice(1) : "<m:"+st);
61+ if (st.slice(0,1)!="/") {
62+ for(var j=0; j < node.attributes.length; j++) {
63+ if (node.attributes[j].nodeValue!="italic" &&
64+ node.attributes[j].nodeValue!="" &&
65+ node.attributes[j].nodeValue!="inherit" &&
66+ node.attributes[j].nodeValue!=undefined) {
67+ str += " "+node.attributes[j].nodeName+"="+
68+ "\""+node.attributes[j].nodeValue+"\"";
69+ }
70+ }
71+ }
72+ str += ">";
73+ }
74+ node = node.nextSibling;
75+ node.parentNode.removeChild(node.previousSibling);
76+ }
77+
78+ if (str != '') {
79+ str += "</m:math>";
80+ newnode = document.createElement("span");
81+ node.parentNode.replaceChild(newnode,node);
82+ newnode.innerHTML = str;
83+ }
84+ }
85+ }
86+}
examples/includes/HTML-Toc-0.91/.gitattributes+1−0
@@ -0,0 +1 @@
1+* -crlf
examples/includes/HTML-Toc-0.91/Changes+26−0
@@ -0,0 +1,26 @@
1+Revision history for Perl extension HTML::Toc.
2+
3+2001-09-03 Freddy Vulto <fvu@fvu.myweb.nl>
4+
5+ Release 0.91
6+
7+ - Tested on Cygwin.
8+ - Used Unix file type for source files.
9+ - Updated documentation.
10+ - Prohibited call with undefined parameter to HTML::Parser->parse() from
11+ HTML::_tokenTocEndParser->parse() which caused havoc with version 3.25
12+ of HTML::Parser.
13+ - Specified 'HTML::Parser' as module that needs to be available in order
14+ to use HTML::Toc.
15+ - Added protected method HTML::TocGenerator::_setActiveAnchorName().
16+ This method replaces the incongruous access of
17+ 'HTML::TocUpdator::_doDeleteTokens' by HTML::TocGenerator.
18+ HTML::TocUpdator now overrides '_setActiveAnchorName()' to allow
19+ the ancestor call to HTML::TocGenerator only when '_doDeleteTokens'
20+ equals false.
21+
22+2001-08-09 Freddy Vulto <fvu@fvu.myweb.nl>
23+
24+ Release 0.90
25+
26+ - First release.
examples/includes/HTML-Toc-0.91/MANIFEST+26−0
@@ -0,0 +1,26 @@
1+Changes
2+Toc.pod
3+Toc.pm
4+TocGenerator.pm
5+TocInsertor.pm
6+TocUpdator.pm
7+Makefile.PL
8+MANIFEST
9+t/extend.t
10+t/format.t
11+t/generate.t
12+t/insert.t
13+t/manualTest.t
14+t/options.t
15+t/podExamples.t
16+t/propagate.t
17+t/siteMap.t
18+t/update.t
19+t/ManualTest/manualTest1.htm
20+t/SiteMap/index.htm
21+t/SiteMap/SubDir1/index.htm
22+t/SiteMap/SubDir1/SubSubDir1/index.htm
23+t/SiteMap/SubDir2/index.htm
24+t/SiteMap/SubDir2/SubSubDir1/index.htm
25+t/SiteMap/SubDir2/SubSubDir2/index.htm
26+t/SiteMap/SubDir3/index.htm
examples/includes/HTML-Toc-0.91/Makefile.PL+8−0
@@ -0,0 +1,8 @@
1+use ExtUtils::MakeMaker;
2+
3+WriteMakefile(
4+ 'NAME' => 'HTML::Toc',
5+ 'VERSION_FROM' => 'Toc.pm',
6+ 'PREREQ_PM' => {'HTML::Parser' => 0},
7+ 'MAN3PODS' => {},
8+);
examples/includes/HTML-Toc-0.91/Toc.pm+549−0
@@ -0,0 +1,549 @@
1+#=== HTML::Toc ================================================================
2+# function: HTML Table of Contents
3+
4+
5+package HTML::Toc;
6+
7+
8+use strict;
9+
10+
11+BEGIN {
12+ use vars qw($VERSION);
13+
14+ $VERSION = '0.91';
15+}
16+
17+
18+use constant FILE_FILTER => '.*';
19+use constant GROUP_ID_H => 'h';
20+use constant LEVEL_1 => 1;
21+use constant NUMBERING_STYLE_DECIMAL => 'decimal';
22+
23+ # Templates
24+
25+ # Anchor templates
26+use constant TEMPLATE_ANCHOR_NAME => '$groupId."-".$node';
27+use constant TEMPLATE_ANCHOR_HREF_BEGIN =>
28+ '"<a href=#$anchorName>"';
29+use constant TEMPLATE_ANCHOR_HREF_BEGIN_FILE =>
30+ '"<a href=$file#$anchorName>"';
31+use constant TEMPLATE_ANCHOR_HREF_END => '"</a>"';
32+use constant TEMPLATE_ANCHOR_NAME_BEGIN =>
33+ '"<a name=$anchorName>"';
34+use constant TEMPLATE_ANCHOR_NAME_END => '"</a>"';
35+use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN =>
36+ '<!-- #BeginTocAnchorNameBegin -->';
37+use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN =>
38+ '<!-- #EndTocAnchorNameBegin -->';
39+use constant TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END =>
40+ '<!-- #BeginTocAnchorNameEnd -->';
41+use constant TOKEN_UPDATE_END_OF_ANCHOR_NAME_END =>
42+ '<!-- #EndTocAnchorNameEnd -->';
43+use constant TOKEN_UPDATE_BEGIN_NUMBER =>
44+ '<!-- #BeginTocNumber -->';
45+use constant TOKEN_UPDATE_END_NUMBER =>
46+ '<!-- #EndTocNumber -->';
47+use constant TOKEN_UPDATE_BEGIN_TOC =>
48+ '<!-- #BeginToc -->';
49+use constant TOKEN_UPDATE_END_TOC =>
50+ '<!-- #EndToc -->';
51+
52+use constant TEMPLATE_TOKEN_NUMBER => '"$node &nbsp;"';
53+
54+ # Level templates
55+use constant TEMPLATE_LEVEL => '"<li>$text\n"';
56+use constant TEMPLATE_LEVEL_BEGIN => '"<ul>\n"';
57+use constant TEMPLATE_LEVEL_END => '"</ul>\n"';
58+
59+
60+END {}
61+
62+
63+#--- HTML::Toc::new() ---------------------------------------------------------
64+# function: Constructor
65+
66+sub new {
67+ # Get arguments
68+ my ($aType) = @_;
69+ # Local variables
70+ my $self;
71+
72+ $self = bless({}, $aType);
73+ # Default to empty 'options' array
74+ $self->{options} = {};
75+ # Empty toc
76+ $self->{_toc} = "";
77+ # Hash reference to array for each groupId, each array element
78+ # referring to the group of the level indicated by the array index.
79+ # For example, with the default 'tokenGroups', '_levelGroups' would
80+ # look like:
81+ #
82+ # {'h'} => [\$group1, \$group2, \$group3, \$group4, \$group5, \$group6];
83+ #
84+ $self->{_levelGroups} = undef;
85+ # Set default options
86+ $self->_setDefaults();
87+ return $self;
88+} # new()
89+
90+
91+#--- HTML::Toc::_compareLevels() ----------------------------------------------
92+# function: Compare levels.
93+# args: - $aLevel: pointer to level
94+# - $aGroupLevel
95+# - $aPreviousLevel
96+# - $aPreviousGroupLevel
97+# returns: 0 if new level equals previous level, 1 if new level exceeds
98+# previous level, -1 if new level is smaller then previous level.
99+
100+sub _compareLevels {
101+ # Get arguments
102+ my (
103+ $self, $aLevel, $aPreviousLevel, $aGroupLevel, $aPreviousGroupLevel
104+ ) = @_;
105+ # Local variables
106+ my ($result);
107+ # Levels equals?
108+ if (
109+ ($aLevel == $aPreviousLevel) &&
110+ ($aGroupLevel == $aPreviousGroupLevel)
111+ ) {
112+ # Yes, levels are equals;
113+ # Indicate so
114+ $result = 0;
115+ }
116+ else {
117+ # No, levels differ;
118+ # Bias to new level being smaller than previous level;
119+ $result = -1;
120+ # Must groups not be nested and do group levels differ?
121+ if (
122+ ($self->{options}{'doNestGroup'} == 0) &&
123+ ($aGroupLevel != $aPreviousGroupLevel)
124+ ) {
125+ # Yes, groups must be kept apart and the group levels differ;
126+ # Level is greater than previous level?
127+ if (
128+ ($aLevel > $aPreviousLevel)
129+ ) {
130+ # Yes, level is greater than previous level;
131+ # Indicate so
132+ $result = 1;
133+ }
134+ }
135+ else {
136+ # No, group must be nested;
137+ # Level is greater than previous level?
138+ if (
139+ ($aLevel > $aPreviousLevel) ||
140+ ($aGroupLevel > $aPreviousGroupLevel)
141+ ) {
142+ # Yes, level is greater than previous level;
143+ # Indicate so
144+ $result = 1;
145+ }
146+ }
147+ }
148+ # Return value
149+ return $result;
150+} # _compareLevels()
151+
152+
153+#--- HTML::TocGenerator::_formatLevelIndent() ---------------------------------
154+# function: Format indent.
155+# args: - $aText: text to indent
156+# - $aLevel: Level.
157+# - $aGroupLevel: Group level.
158+# - $aAdd
159+# - $aGlobalLevel
160+
161+sub _formatLevelIndent {
162+ # Get arguments
163+ my ($self, $aText, $aAdd, $aGlobalLevel) = @_;
164+ # Local variables
165+ my ($levelIndent, $indent, $nrOfIndents);
166+ # Alias indentation option
167+ $levelIndent = $self->{options}{'levelIndent'}; #=~ s/[0-9]+/&/;
168+ # Calculate number of indents
169+ $nrOfIndents = ($aGlobalLevel + $aAdd) * $levelIndent;
170+ # Assemble indents
171+ $indent = pack("A$nrOfIndents");
172+ # Return value
173+ return $indent . $aText;
174+} # _formatLevelIndent()
175+
176+
177+#--- HTML::Toc::_formatToc() --------------------------------------------------
178+# function: Format ToC.
179+# args: - aPreviousLevel
180+# - aPreviousGroupLevel
181+# - aToc: ToC to format.
182+# - aHeaderLines
183+# note: Recursive function this is.
184+
185+sub _formatToc {
186+ # Get arguments
187+ my (
188+ $self, $aPreviousLevel, $aPreviousGroupLevel, $aToc, $aHeaderLines,
189+ $aGlobalLevel
190+ ) = @_;
191+ # Local variables
192+ my ($level, $groupLevel, $line, $groupId, $text, $compareStatus);
193+ my ($anchorName, $globalLevel, $node, $sequenceNr);
194+
195+ LOOP: {
196+ # Lines need processing?
197+ while (scalar(@$aHeaderLines) > 0) {
198+ # Yes, lines need processing;
199+ # Get line
200+ $line = shift @$aHeaderLines;
201+
202+ # Determine levels
203+ ($level, $groupLevel, $groupId, $node, $sequenceNr,
204+ $anchorName, $text) = split(
205+ / /, $line, 7
206+ );
207+ # Must level and group be processed?
208+ if (
209+ ($level =~ m/$self->{options}{'levelToToc'}/) &&
210+ ($groupId =~ m/$self->{options}{'groupToToc'}/)
211+ ) {
212+ # Yes, level must be processed;
213+ # Compare levels
214+ $compareStatus = $self->_compareLevels(
215+ $level, $aPreviousLevel, $groupLevel, $aPreviousGroupLevel
216+ );
217+
218+ COMPARE_LEVELS: {
219+
220+ # Equals?
221+ if ($compareStatus == 0) {
222+ # Yes, levels are equal;
223+ # Format level
224+ $$aToc .= $self->_formatLevelIndent(
225+ ref($self->{_templateLevel}) eq "CODE" ?
226+ &{$self->{_templateLevel}}(
227+ $level, $groupId, $node, $sequenceNr, $text
228+ ) :
229+ eval($self->{_templateLevel}),
230+ 0, $aGlobalLevel
231+ );
232+ }
233+
234+ # Greater?
235+ if ($compareStatus > 0) {
236+ # Yes, new level is greater than previous level;
237+ # Must level be single-stepped?
238+ if (
239+ $self->{options}{'doSingleStepLevel'} &&
240+ ($aPreviousLevel) &&
241+ ($level > $aPreviousLevel)
242+ ) {
243+ # Yes, level must be single-stepped;
244+ # Make sure, new level is increased one step only
245+ $level = $aPreviousLevel + 1;
246+ }
247+ # Increase global level
248+ $aGlobalLevel++;
249+ # Format begin of level
250+ $$aToc .= $self->_formatLevelIndent(
251+ eval($self->{_templateLevelBegin}), -1, $aGlobalLevel
252+ );
253+ # Process line again
254+ unshift @$aHeaderLines, $line;
255+ # Assemble TOC (recursive) for next level
256+ $self->_formatToc(
257+ $level, $groupLevel, $aToc, $aHeaderLines, $aGlobalLevel
258+ );
259+ # Format end of level
260+ $$aToc .= $self->_formatLevelIndent(
261+ eval($self->{_templateLevelEnd}), -1, $aGlobalLevel
262+ );
263+ # Decrease global level
264+ $aGlobalLevel--;
265+ # Exit loop
266+ last COMPARE_LEVELS;
267+ }
268+
269+ # Smaller?
270+ if ($compareStatus < 0) {
271+ # Yes, new level is smaller than previous level;
272+ # Process line again
273+ unshift @$aHeaderLines, $line;
274+ # End loop
275+ last LOOP;
276+ }
277+ }
278+ }
279+ }
280+ }
281+} # _formatToc()
282+
283+
284+#--- HTML::Toc::_parseTokenGroups() -------------------------------------------
285+# function: Parse token groups
286+
287+sub _parseTokenGroups {
288+ # Get arguments
289+ my ($self) = @_;
290+ # Local variables
291+ my ($group, $levelGroups, $numberingStyle);
292+
293+ # Clear any previous 'levelGroups'
294+ $self->{_levelGroups} = undef;
295+ # Determine default 'numberingStyle'
296+ $numberingStyle = defined($self->{options}{'numberingStyle'}) ?
297+ $self->{options}{'numberingStyle'} : NUMBERING_STYLE_DECIMAL;
298+
299+ # Loop through groups
300+ foreach $group (@{$self->{options}{'tokenToToc'}}) {
301+ # 'groupId' is specified?
302+ if (! defined($group->{'groupId'})) {
303+ # No, 'groupId' isn't specified;
304+ # Set default groupId
305+ $group->{'groupId'} = GROUP_ID_H;
306+ }
307+ # 'level' is specified?
308+ if (! defined($group->{'level'})) {
309+ # No, 'level' isn't specified;
310+ # Set default level
311+ $group->{'level'} = LEVEL_1;
312+ }
313+ # 'numberingStyle' is specified?
314+ if (! defined($group->{'numberingStyle'})) {
315+ # No, 'numberingStyle' isn't specified;
316+ # Set default numberingStyle
317+ $group->{'numberingStyle'} = $numberingStyle;
318+ }
319+ # Add group to '_levelGroups' variabele
320+ $self->{_levelGroups}{$group->{'groupId'}}[$group->{'level'} - 1] =
321+ $group;
322+ }
323+} # _parseTokenGroups()
324+
325+
326+#--- HTML::Toc::_setDefaults() ------------------------------------------------
327+# function: Set default options.
328+
329+sub _setDefaults {
330+ # Get arguments
331+ my ($self) = @_;
332+ # Set default options
333+ $self->setOptions(
334+ {
335+ 'attributeToExcludeToken' => '-',
336+ 'attributeToTocToken' => '@',
337+ 'insertionPoint' => 'after <body>',
338+ 'levelToToc' => '.*',
339+ 'groupToToc' => '.*',
340+ 'doNumberToken' => 0,
341+ 'doLinkToFile' => 0,
342+ 'doLinkToToken' => 1,
343+ 'doLinkToId' => 0,
344+ 'doSingleStepLevel' => 1,
345+ 'linkUri' => '',
346+ 'levelIndent' => 3,
347+ 'doNestGroup' => 0,
348+ 'doUseExistingAnchors' => 1,
349+ 'doUseExistingIds' => 1,
350+ 'tokenToToc' => [
351+ {
352+ 'level' => 1,
353+ 'tokenBegin' => '<h1>'
354+ }, {
355+ 'level' => 2,
356+ 'tokenBegin' => '<h2>'
357+ }, {
358+ 'level' => 3,
359+ 'tokenBegin' => '<h3>'
360+ }, {
361+ 'level' => 4,
362+ 'tokenBegin' => '<h4>'
363+ }, {
364+ 'level' => 5,
365+ 'tokenBegin' => '<h5>'
366+ }, {
367+ 'level' => 6,
368+ 'tokenBegin' => '<h6>'
369+ }
370+ ],
371+ 'header' =>
372+ "\n<!-- Table of Contents generated by Perl - HTML::Toc -->\n",
373+ 'footer' =>
374+ "\n<!-- End of generated Table of Contents -->\n",
375+ }
376+ );
377+} # _setDefaults()
378+
379+
380+#--- HTML::Toc::clear() -------------------------------------------------------
381+# function: Clear ToC.
382+
383+sub clear {
384+ # Get arguments
385+ my ($self) = @_;
386+ # Clear ToC
387+ $self->{_toc} = "";
388+ $self->{toc} = "";
389+ $self->{groupIdLevels} = undef;
390+ $self->{levels} = undef;
391+} # clear()
392+
393+
394+#--- HTML::Toc::format() ------------------------------------------------------
395+# function: Format ToC.
396+# returns: Formatted ToC.
397+
398+sub format {
399+ # Get arguments
400+ my ($self) = @_;
401+ # Local variables;
402+ my $toc = "";
403+ my @tocLines = split(/\r\n|\n/, $self->{_toc});
404+ # Format table of contents
405+ $self->_formatToc("0", "0", \$toc, \@tocLines, 0);
406+ # Remove last newline
407+ $toc =~ s/\n$//m;
408+ # Add header & footer
409+ $toc = $self->{options}{'header'} . $toc . $self->{options}{'footer'};
410+ # Return value
411+ return $toc;
412+} # format()
413+
414+
415+#--- HTML::Toc::parseOptions() ------------------------------------------------
416+# function: Parse options.
417+
418+sub parseOptions {
419+ # Get arguments
420+ my ($self) = @_;
421+ # Alias options
422+ my $options = $self->{options};
423+
424+ # Parse token groups
425+ $self->_parseTokenGroups();
426+
427+ # Link ToC to tokens?
428+ if ($self->{options}{'doLinkToToken'}) {
429+ # Yes, link ToC to tokens;
430+ # Determine anchor href template begin
431+ $self->{_templateAnchorHrefBegin} =
432+ defined($options->{'templateAnchorHrefBegin'}) ?
433+ $options->{'templateAnchorHrefBegin'} :
434+ $options->{'doLinkToFile'} ?
435+ TEMPLATE_ANCHOR_HREF_BEGIN_FILE : TEMPLATE_ANCHOR_HREF_BEGIN;
436+
437+ # Determine anchor href template end
438+ $self->{_templateAnchorHrefEnd} =
439+ defined($options->{'templateAnchorHrefEnd'}) ?
440+ $options->{'templateAnchorHrefEnd'} :
441+ TEMPLATE_ANCHOR_HREF_END;
442+
443+ # Determine anchor name template
444+ $self->{_templateAnchorName} =
445+ defined($options->{'templateAnchorName'}) ?
446+ $options->{'templateAnchorName'} :
447+ TEMPLATE_ANCHOR_NAME;
448+
449+ # Determine anchor name template begin
450+ $self->{_templateAnchorNameBegin} =
451+ defined($options->{'templateAnchorNameBegin'}) ?
452+ $options->{'templateAnchorNameBegin'} :
453+ TEMPLATE_ANCHOR_NAME_BEGIN;
454+
455+ # Determine anchor name template end
456+ $self->{_templateAnchorNameEnd} =
457+ defined($options->{'templateAnchorNameEnd'}) ?
458+ $options->{'templateAnchorNameEnd'} :
459+ TEMPLATE_ANCHOR_NAME_END;
460+ }
461+
462+ # Determine token number template
463+ $self->{_templateTokenNumber} =
464+ defined($options->{'templateTokenNumber'}) ?
465+ $options->{'templateTokenNumber'} :
466+ TEMPLATE_TOKEN_NUMBER;
467+
468+ # Determine level template
469+ $self->{_templateLevel} =
470+ defined($options->{'templateLevel'}) ?
471+ $options->{'templateLevel'} :
472+ TEMPLATE_LEVEL;
473+
474+ # Determine level begin template
475+ $self->{_templateLevelBegin} =
476+ defined($options->{'templateLevelBegin'}) ?
477+ $options->{'templateLevelBegin'} :
478+ TEMPLATE_LEVEL_BEGIN;
479+
480+ # Determine level end template
481+ $self->{_templateLevelEnd} =
482+ defined($options->{'templateLevelEnd'}) ?
483+ $options->{'templateLevelEnd'} :
484+ TEMPLATE_LEVEL_END;
485+
486+ # Determine 'anchor name begin' begin update token
487+ $self->{_tokenUpdateBeginOfAnchorNameBegin} =
488+ defined($options->{'tokenUpdateBeginOfAnchorNameBegin'}) ?
489+ $options->{'tokenUpdateBeginOfAnchorNameBegin'} :
490+ TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_BEGIN;
491+
492+ # Determine 'anchor name begin' end update token
493+ $self->{_tokenUpdateEndOfAnchorNameBegin} =
494+ defined($options->{'tokenUpdateEndOfAnchorNameBegin'}) ?
495+ $options->{'tokenUpdateEndOfAnchorNameBegin'} :
496+ TOKEN_UPDATE_END_OF_ANCHOR_NAME_BEGIN;
497+
498+ # Determine 'anchor name end' begin update token
499+ $self->{_tokenUpdateBeginOfAnchorNameEnd} =
500+ defined($options->{'tokenUpdateBeginOfAnchorNameEnd'}) ?
501+ $options->{'tokenUpdateBeginOfAnchorNameEnd'} :
502+ TOKEN_UPDATE_BEGIN_OF_ANCHOR_NAME_END;
503+
504+ # Determine 'anchor name end' end update token
505+ $self->{_tokenUpdateEndOfAnchorNameEnd} =
506+ defined($options->{'tokenUpdateEndOfAnchorNameEnd'}) ?
507+ $options->{'tokenUpdateEndOfAnchorNameEnd'} :
508+ TOKEN_UPDATE_END_OF_ANCHOR_NAME_END;
509+
510+ # Determine number begin update token
511+ $self->{_tokenUpdateBeginNumber} =
512+ defined($options->{'tokenUpdateBeginNumber'}) ?
513+ $options->{'tokenUpdateBeginNumber'} :
514+ TOKEN_UPDATE_BEGIN_NUMBER;
515+
516+ # Determine number end update token
517+ $self->{_tokenUpdateEndNumber} =
518+ defined($options->{'tokenUpdateEndNumber'}) ?
519+ $options->{'tokenUpdateEndNumber'} :
520+ TOKEN_UPDATE_END_NUMBER;
521+
522+ # Determine toc begin update token
523+ $self->{_tokenUpdateBeginToc} =
524+ defined($options->{'tokenUpdateBeginToc'}) ?
525+ $options->{'tokenUpdateBeginToc'} :
526+ TOKEN_UPDATE_BEGIN_TOC;
527+
528+ # Determine toc end update token
529+ $self->{_tokenUpdateEndToc} =
530+ defined($options->{'tokenUpdateEndToc'}) ?
531+ $options->{'tokenUpdateEndToc'} :
532+ TOKEN_UPDATE_END_TOC;
533+
534+} # parseOptions()
535+
536+
537+#--- HTML::Toc::setOptions() --------------------------------------------------
538+# function: Set options.
539+# args: - aOptions: Reference to hash containing options.
540+
541+sub setOptions {
542+ # Get arguments
543+ my ($self, $aOptions) = @_;
544+ # Add options
545+ %{$self->{options}} = (%{$self->{options}}, %$aOptions);
546+} # setOptions()
547+
548+
549+1;
examples/includes/HTML-Toc-0.91/Toc.pod+1710−0
@@ -0,0 +1,1710 @@
1+=head1 NAME
2+
3+HTML::Toc - Generate, insert and update HTML Table of Contents.
4+
5+=head1 DESCRIPTION
6+
7+Generate, insert and update HTML Table of Contents.
8+
9+=head1 Introduction
10+
11+The HTML::Toc consists out of the following packages:
12+
13+ HTML::Toc
14+ HTML::TocGenerator
15+ HTML::TocInsertor
16+ HTML::TocUpdator
17+
18+HTML::Toc is the object which will eventually hold the Table of Contents. HTML::TocGenerator does the actual generation of the ToC. HTML::TocInsertor handles the insertion of the ToC in the source. HTML::TocUpdator takes care of updating previously inserted ToCs.
19+
20+HTML::Parser is the base object of HTML::TocGenerator, HTML::TocInsertor and HTML::TocUpdator. Each of these objects uses its predecessor as its ancestor, as shown in the UML diagram underneath:
21+
22+ +---------------------+
23+ | HTML::Parser |
24+ +---------------------+
25+ +---------------------+
26+ | +parse() |
27+ | +parse_file() |
28+ +----------+----------+
29+ /_\
30+ |
31+ +----------+----------+ <<uses>> +-----------+
32+ | HTML::TocGenerator + - - - - - -+ HTML::Toc |
33+ +---------------------+ +-----------+
34+ +---------------------+ +-----------+
35+ | +extend() | | +clear() |
36+ | +extendFromFile() | | +format() |
37+ | +generate() | +-----+-----+
38+ | +generateFromFile() | :
39+ +----------+----------+ :
40+ /_\ :
41+ | :
42+ +----------+----------+ <<uses>> :
43+ | HTML::TocInsertor + - - - - - - - - -+
44+ +---------------------+ :
45+ +---------------------+ :
46+ | +insert() | :
47+ | +insertIntoFile() | :
48+ +----------+----------+ :
49+ /_\ :
50+ | :
51+ +----------+----------+ <<uses>> :
52+ | HTML::TocUpdator + - - - - - - - - -+
53+ +---------------------+
54+ +---------------------+
55+ | +insert() |
56+ | +insertIntoFile() |
57+ | +update() |
58+ | +updateFile() |
59+ +---------------------+
60+
61+When generating a ToC you'll have to decide which object you want to use:
62+
63+ TocGenerator:
64+ for generating a ToC without inserting the ToC into the source
65+ TocInsertor:
66+ for generating a ToC and inserting the ToC into the source
67+ TocUpdator:
68+ for generating and inserting a ToC, removing any previously
69+ inserted ToC elements
70+
71+Thus in tabular view, each object is capable of:
72+
73+ generating inserting updating
74+ ---------------------------------
75+ TocGenerator X
76+ TocInsertor X X
77+ TocUpdator X X X
78+
79+=head2 Generating
80+
81+The code underneath will generate a ToC of the HTML headings C<<h1>>..C<<h6>> from a file C<index.htm>:
82+
83+ use HTML::Toc;
84+ use HTML::TocGenerator;
85+
86+ my $toc = HTML::Toc->new();
87+ my $tocGenerator = HTML::TocGenerator->new();
88+
89+ $tocGenerator->generateFromFile($toc, 'index.htm');
90+ print $toc->format();
91+
92+For example, with C<index.htm> containing:
93+
94+ <html>
95+ <body>
96+ <h1>Chapter</h1>
97+ </body>
98+ </html>
99+
100+the output will be:
101+
102+
103+ <!-- Table of Contents generated by Perl - HTML::Toc -->
104+ <ul>
105+ <li><a href=#h-1>Chapter</a>
106+ </ul>
107+ <!-- End of generated Table of Contents -->
108+
109+=head2 Inserting
110+
111+This code will generate a ToC of HTML headings C<<h1>>..C<<h6>> of file C<index.htm>, and insert the ToC after the C<<body>> tag at the same time:
112+
113+ use HTML::Toc;
114+ use HTML::TocInsertor;
115+
116+ my $toc = HTML::Toc->new();
117+ my $tocInsertor = HTML::TocInsertor->new();
118+
119+ $tocInsertor->insertIntoFile($toc, 'index.htm');
120+
121+For example, with C<index.htm> containing:
122+
123+ <html>
124+ <body>
125+ <h1>Chapter</h1>
126+ </body>
127+ </html>
128+
129+the output will be:
130+
131+ <html>
132+ <body>
133+ <!-- Table of Contents generated by Perl - HTML::Toc -->
134+ <ul>
135+ <li><a href=#h-1>Chapter</a>
136+ </ul>
137+ <!-- End of generated Table of Contents -->
138+
139+ <a name=h-1><h1>Chapter</h1></a>
140+ </body>
141+ </html>
142+
143+If you're planning to update the inserted ToC, you'd better use C<TocUpdator> to insert the ToC. C<TocUpdator> marks the inserted ToC elements with update tokens. These update tokens allow C<TocUpdator> to identify and remove the ToC elements during a future update session. This code uses C<TocUpdator> instead of C<TocInsertor>:
144+
145+ use HTML::Toc;
146+ use HTML::TocUpdator;
147+
148+ my $toc = HTML::Toc->new();
149+ my $tocUpdator = HTML::TocUpdator->new();
150+
151+ $tocUpdator->insertIntoFile($toc, 'index.htm');
152+
153+When applying the code above on 'index.htm':
154+
155+ <html>
156+ <body>
157+ <h1>
158+ Chapter
159+ </h1>
160+ </body>
161+ </html>
162+
163+the output will contain additional update tokens:
164+
165+ <!-- #BeginToc -->
166+ <!-- #EndToc -->
167+ <!-- #BeginTocAnchorNameBegin -->
168+ <!-- #EndTocAnchorNameBegin -->
169+ <!-- #BeginTocAnchorNameEnd -->
170+ <!-- #EndTocAnchorNameEnd -->
171+
172+around the inserted ToC elements:
173+
174+ <html>
175+ <body><!-- #BeginToc-->
176+ <!-- Table of Contents generated by Perl - HTML::Toc -->
177+ <ul>
178+ <li><a href=#h-1> Chapter </a>
179+ </ul>
180+ <!-- End of generated Table of Contents -->
181+ <!-- #EndToc -->
182+ <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
183+ Chapter
184+ </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
185+ </body>
186+ </html>
187+
188+Instead of C<HTML::TocUpdator::insertIntoFile> you can also use C<HTML::TocUpdator::updateFile()>. C<HTML::TocUpdator::updateFile()> will also insert the ToC, whether there is a ToC already inserted or not.
189+
190+=head2 Updating
191+
192+This code will generate a ToC of HTML headings C<<h1>>..C<<h6>> of file C<indexToc.htm>, and insert or update the ToC after the C<<body>> tag at the same time:
193+
194+ use HTML::Toc;
195+ use HTML::TocUpdator;
196+
197+ my $toc = HTML::Toc->new();
198+ my $tocUpdator = HTML::TocUpdator->new();
199+
200+ $tocUpdator->updateFile($toc, 'indexToc.htm');
201+
202+For example, with C<indexToc.htm> containing:
203+
204+ <html>
205+ <body><!-- #BeginToc -->
206+ foo
207+ <!-- #EndToc -->
208+ <!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
209+ Chapter
210+ </h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
211+ </body>h
212+ </html>
213+
214+the output will be:
215+
216+ <html>
217+ <body><!-- #BeginToc -->
218+ <!-- Table of Contents generated by Perl - HTML::Toc -->
219+ <ul>
220+ <li><a href=#h-1> Chapter </a>
221+ </ul>
222+ <!-- End of generated Table of Contents -->
223+ <!-- #EndToc -->
224+ <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
225+ Chapter
226+ </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
227+ </body>
228+ </html>
229+
230+All text between the update tokens will be replaced. So be warned: all manual changes made to text between update tokens will be removed unrecoverable after calling C<HTML::TocUpdator::update()> or C<HTML::TocUpdator::updateFile()>.
231+
232+=head2 Formatting
233+
234+The ToC isn't generated all at once. There are two stages involved: generating and formatting. Generating the ToC actually means storing a preliminary ToC in C<HTML::Toc-E<gt>{_toc}>. This preliminary, tokenized ToC has to be turned into something useful by calling C<HTML::Toc-E<gt>format()>. For an example, see paragraph 'L<Generating|"generating">'.
235+
236+=head1 Advanced
237+
238+The ToC generation can be modified in a variety of ways. The following paragraphs each explain a single modification. An example of most of the modifications can be found in the C<manualTest.t> test file. Within this test, a manual containing:
239+
240+ preface
241+ introduction
242+ table of contents
243+ table of figures
244+ table of tables
245+ parts
246+ chapters
247+ appendixes
248+ bibliography
249+
250+is formatted.
251+
252+=head2 Using attribute value as ToC text
253+
254+Normally, the ToC will be made of text between specified ToC tokens. It's also possible to use the attribute value of a token as a ToC text. This can be done by specifying the attribute marked with an L<attributeToTocToken|"attributeToTocToken"> within the L<tokenBegin|"tokenBegin"> token. For example, suppose you want to generate a ToC of the C<alt> attributes of the following image tokens:
255+
256+ <body>
257+ <img src=test1.gif alt="First picture">
258+ <img src=test2.gif alt="Second picture">
259+ </body>
260+
261+This would be the code:
262+
263+ use HTML::Toc;
264+ use HTML::TocInsertor;
265+
266+ my $toc = HTML::Toc->new();
267+ my $tocInsertor = HTML::TocInsertor->new();
268+
269+ $toc->setOptions({
270+ 'tokenToToc' => [{
271+ 'groupId' => 'image',
272+ 'tokenBegin' => '<img alt=@>'
273+ }],
274+ });
275+ $tocInsertor->insertIntoFile($toc, $filename);
276+
277+and the output will be:
278+
279+ <body>
280+ <!-- Table of Contents generated by Perl - HTML::Toc -->
281+ <ul>
282+ <li><a href=#image-1>First picture</a>
283+ <li><a href=#image-2>Second picture</a>
284+ </ul>
285+ <!-- End of generated Table of Contents -->
286+
287+ <a name=image-1><img src=test1.gif alt="First picture"></a>
288+ <a name=image-2><img src=test2.gif alt="Second picture"></a>
289+ </body>
290+
291+=head2 Generate single ToC of multiple files
292+
293+Besides generating a ToC of a single file, it's also possible to generate a single ToC of multiple files. This can be done by specifying either an array of files as the file argument and/or by extending an existing ToC.
294+
295+=head3 Specify an array of files
296+
297+For example, suppose you want to generate a ToC of both C<doc1.htm>:
298+
299+ <body>
300+ <h1>Chapter of document 1</h1>
301+ </body>
302+
303+and C<doc2.htm>:
304+
305+ <body>
306+ <h1>Chapter of document 2</h1>
307+ </body>
308+
309+Here's the code to do so by specifying an array of files:
310+
311+ use HTML::Toc;
312+ use HTML::TocGenerator;
313+
314+ my $toc = HTML::Toc->new();
315+ my $tocGenerator = HTML::TocGenerator->new();
316+
317+ $toc->setOptions({'doLinkToFile' => 1});
318+ $tocGenerator->generateFromFile($toc, ['doc1.htm', 'doc2.htm']);
319+ print $toc->format();
320+
321+And the output will be:
322+
323+
324+ <!-- Table of Contents generated by Perl - HTML::Toc -->
325+ <ul>
326+ <li><a href=doc1.htm#h-1>Chapter of document 1</a>
327+ <li><a href=doc2.htm#h-2>Chapter of document 2</a>
328+ </ul>
329+ <!-- End of generated Table of Contents -->
330+
331+=head3 Extend an existing ToC
332+
333+It's also possible to extend an existing ToC. For example, suppose we want the generate a ToC of file C<doc1.htm>:
334+
335+ <body>
336+ <h1>Chapter of document 1</h1>
337+ </body>
338+
339+and extend this ToC with text from C<doc2.htm>:
340+
341+ <body>
342+ <h1>Chapter of document 2</h1>
343+ </body>
344+
345+Here's the code to do so:
346+
347+ use HTML::Toc;
348+ use HTML::TocGenerator;
349+
350+ my $toc = HTML::Toc->new();
351+ my $tocGenerator = HTML::TocGenerator->new();
352+
353+ $toc->setOptions({'doLinkToFile' => 1});
354+ $tocGenerator->generateFromFile($toc, 'doc1.htm');
355+ $tocGenerator->extendFromFile($toc, 'doc2.htm');
356+ print $toc->format();
357+
358+And the output will be:
359+
360+
361+ <!-- Table of Contents generated by Perl - HTML::Toc -->
362+ <ul>
363+ <li><a href=doc1.htm#h-1>Chapter of document 1</a>
364+ <li><a href=doc2.htm#h-2>Chapter of document 2</a>
365+ </ul>
366+ <!-- End of generated Table of Contents -->
367+
368+=head2 Generate multiple ToCs
369+
370+It's possible to generate multiple ToCs at once by specifying a C<HTML::Toc> object array as the ToC argument. For example, suppose you want to generate a default ToC of HTML headings <h1>..<h6> as well as a ToC of the C<alt> image attributes of the following text:
371+
372+ <body>
373+ <h1>Header One</h1>
374+ <img src=test1.gif alt="First picture" id=image_001>
375+ <h2>Paragraph One</h2>
376+ <img src=test2.gif alt="Second picture" id=image_002>
377+ </body>
378+
379+Here's how you would do so:
380+
381+ use HTML::Toc;
382+ use HTML::TocInsertor;
383+
384+ my $toc1 = HTML::Toc->new();
385+ my $toc2 = HTML::Toc->new();
386+ my $tocInsertor = HTML::TocInsertor->new();
387+
388+ $toc2->setOptions({
389+ 'tokenToToc' => [{
390+ 'groupId' => 'image',
391+ 'tokenBegin' => '<img alt=@>'
392+ }],
393+ });
394+ $tocInsertor->insertIntoFile([$toc1, $toc2], $filename);
395+
396+And the output will be:
397+
398+ <body>
399+ <!-- Table of Contents generated by Perl - HTML::Toc -->
400+ <ul>
401+ <li><a href=#h-1>Header One</a>
402+ <ul>
403+ <li><a href=#h-1.1>Paragraph One</a>
404+ </ul>
405+ </ul>
406+ <!-- End of generated Table of Contents -->
407+
408+ <!-- Table of Contents generated by Perl - HTML::Toc -->
409+ <ul>
410+ <li><a href=#image-1>First picture</a>
411+ <li><a href=#image-2>Second picture</a>
412+ </ul>
413+ <!-- End of generated Table of Contents -->
414+
415+ <a name=h-1><h1>Header One</h1></a>
416+ <a name=image-1><img src=test1.gif alt="First picture"></a>
417+ <a name=h-1.1><h2>Paragraph One</h2></a>
418+ <a name=image-2><img src=test2.gif alt="Second picture"></a>
419+ </body>
420+
421+=head2 Generate multiple groups in one ToC
422+
423+You may want to generate a ToC consisting of multiple ToC groups.
424+
425+=head3 Specify an additional 'Appendix' group
426+
427+Suppose you want to generate a ToC with one group for the normal headings, and one group for the appendix headings, using this source file:
428+
429+ <body>
430+ <h1>Chapter</h1>
431+ <h2>Paragraph</h2>
432+ <h3>Subparagraph</h3>
433+ <h1>Chapter</h1>
434+ <h1 class=appendix>Appendix Chapter</h1>
435+ <h2 class=appendix>Appendix Paragraph</h2>
436+ </body>
437+
438+With the code underneath:
439+
440+ use HTML::Toc;
441+ use HTML::TocInsertor;
442+
443+ my $toc = HTML::Toc->new();
444+ my $tocInsertor = HTML::TocInsertor->new();
445+
446+ $toc->setOptions({
447+ 'tokenToToc' => [{
448+ 'tokenBegin' => '<h1 class=-appendix>'
449+ }, {
450+ 'tokenBegin' => '<h2 class=-appendix>',
451+ 'level' => 2
452+ }, {
453+ 'groupId' => 'appendix',
454+ 'tokenBegin' => '<h1 class=appendix>',
455+ }, {
456+ 'groupId' => 'appendix',
457+ 'tokenBegin' => '<h2 class=appendix>',
458+ 'level' => 2
459+ }]
460+ });
461+ $tocInsertor->insertIntoFile($toc, $filename);
462+
463+the output will be:
464+
465+ <body>
466+ <!-- Table of Contents generated by Perl - HTML::Toc -->
467+ <ul>
468+ <li><a href=#h-1>Chapter</a>
469+ <ul>
470+ <li><a href=#h-1.1>Paragraph</a>
471+ </ul>
472+ <li><a href=#h-2>Chapter</a>
473+ </ul>
474+ <ul>
475+ <li><a href=#appendix-1>Appendix Chapter</a>
476+ <ul>
477+ <li><a href=#appendix-1.1>Appendix Paragraph</a>
478+ </ul>
479+ </ul>
480+ <!-- End of generated Table of Contents -->
481+
482+ <a name=h-1><h1>Chapter</h1></a>
483+ <a name=h-1.1><h2>Paragraph</h2></a>
484+ <h3>Subparagraph</h3>
485+ <a name=h-2><h1>Chapter</h1></a>
486+ <a name=appendix-1><h1 class=appendix>Appendix Chapter</h1></a>
487+ <a name=appendix-1.1><h2 class=appendix>Appendix Paragraph</h2></a>
488+ </body>
489+
490+=head3 Specify an additional 'Part' group
491+
492+Suppose you want to generate a ToC of a document which is divided in multiple parts like this file underneath:
493+
494+ <body>
495+ <h1 class=part>First Part</h1>
496+ <h1>Chapter</h1>
497+ <h2>Paragraph</h2>
498+ <h1 class=part>Second Part</h1>
499+ <h1>Chapter</h1>
500+ <h2>Paragraph</h2>
501+ </body>
502+
503+With the code underneath:
504+
505+ use HTML::Toc;
506+ use HTML::TocInsertor;
507+
508+ my $toc = HTML::Toc->new();
509+ my $tocInsertor = HTML::TocInsertor->new();
510+
511+ $toc->setOptions({
512+ 'doNumberToken' => 1,
513+ 'tokenToToc' => [{
514+ 'tokenBegin' => '<h1 class=-part>'
515+ }, {
516+ 'tokenBegin' => '<h2 class=-part>',
517+ 'level' => 2,
518+ }, {
519+ 'groupId' => 'part',
520+ 'tokenBegin' => '<h1 class=part>',
521+ 'level' => 1,
522+ 'numberingStyle' => 'upper-alpha'
523+ }]
524+ });
525+ $tocInsertor->insertIntoFile($toc, $filename);
526+
527+the output will be:
528+
529+ <body>
530+ <!-- Table of Contents generated by Perl - HTML::Toc -->
531+ <ul>
532+ <li><a href=#part-A>First Part</a>
533+ </ul>
534+ <ul>
535+ <li><a href=#h-1>Chapter</a>
536+ <ul>
537+ <li><a href=#h-1.1>Paragraph</a>
538+ </ul>
539+ </ul>
540+ <ul>
541+ <li><a href=#part-B>Second Part</a>
542+ </ul>
543+ <ul>
544+ <li><a href=#h-2>Chapter</a>
545+ <ul>
546+ <li><a href=#h-2.1>Paragraph</a>
547+ </ul>
548+ </ul>
549+ <!-- End of generated Table of Contents -->
550+
551+ <a name=part-A><h1 class=part>A &nbsp;First Part</h1></a>
552+ <a name=h-1><h1>1 &nbsp;Chapter</h1></a>
553+ <a name=h-1.1><h2>1.1 &nbsp;Paragraph</h2></a>
554+ <a name=part-B><h1 class=part>B &nbsp;Second Part</h1></a>
555+ <a name=h-2><h1>2 &nbsp;Chapter</h1></a>
556+ <a name=h-2.1><h2>2.1 &nbsp;Paragraph</h2></a>
557+ </body>
558+
559+=head2 Number ToC entries
560+
561+By default, the generated ToC will list its entries unnumbered. If you want to number the ToC entries, two options are available. Either you can specify a numbered list by modifying L<templateLevelBegin|"templateLevelBegin"> and L<templateLevelEnd|"templateLevelEnd">. Or when the ToC isn't a simple numbered list, you can use the numbers generated by HTML::TocGenerator.
562+
563+=head3 Specify numbered list
564+
565+By modifying L<templateLevelBegin|"templateLevelBegin"> and L<templateLevelEnd|"templateLevelEnd"> you can specify a numbered ToC:
566+
567+ use HTML::Toc;
568+ use HTML::TocGenerator;
569+
570+ my $toc = HTML::Toc->new();
571+ my $tocGenerator = HTML::TocGenerator->new();
572+
573+ $toc->setOptions({
574+ 'templateLevelBegin' => '"<ol>\n"',
575+ 'templateLevelEnd' => '"</ol>\n"',
576+ });
577+ $tocGenerator->generateFromFile($toc, 'index.htm');
578+ print $toc->format();
579+
580+For instance with the original file containing:
581+
582+ <body>
583+ <h1>Chapter</h1>
584+ <h2>Paragraph</h2>
585+ </body>
586+
587+The formatted ToC now will contain C<ol> instead of C<ul> tags:
588+
589+ <!-- Table of Contents generated by Perl - HTML::Toc -->
590+ <ol>
591+ <li><a href=#h-1>Chapter</a>
592+ <ol>
593+ <li><a href=#h-1.1>Paragraph</a>
594+ </ol>
595+ </ol>
596+ <!-- End of generated Table of Contents -->
597+
598+See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
599+
600+=head3 Use generated numbers
601+
602+Instead of using the HTML ordered list (OL), it's also possible to use the generated numbers to number to ToC nodes. This can be done by modifying L<templateLevel|"templateLevel">:
603+
604+ use HTML::Toc;
605+ use HTML::TocGenerator;
606+
607+ my $toc = HTML::Toc->new();
608+ my $tocGenerator = HTML::TocGenerator->new();
609+
610+ $toc->setOptions({
611+ 'templateLevel' => '"<li>$node &nbsp;$text\n"',
612+ });
613+ $tocGenerator->generateFromFile($toc, 'index.htm');
614+ print $toc->format();
615+
616+For instance with the original file containing:
617+
618+ <body>
619+ <h1>Chapter</h1>
620+ <h2>Paragraph</h2>
621+ </body>
622+
623+The formatted ToC now will have the node numbers hard-coded:
624+
625+ <!-- Table of Contents generated by Perl - HTML::Toc -->
626+ <ul>
627+ <li>1 &nbsp;<a href=#h-1>Chapter</a>
628+ <ul>
629+ <li>1.1 &nbsp;<a href=#h-1.1>Paragraph</a>
630+ </ul>
631+ </ul>
632+ <!-- End of generated Table of Contents -->
633+
634+See also: L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
635+
636+=head2 Using CSS for ToC formatting
637+
638+Suppose you want to display a ToC with upper-alpha numbered appendix headings. To accomplish this, you can specify a CSS style within the source document:
639+
640+ <html>
641+ <head>
642+ <style type="text/css">
643+ ol.toc_appendix1 { list-style-type: upper-alpha }
644+ </style>
645+ </head>
646+ <body>
647+ <h1 class=appendix>Appendix</h1>
648+ <h2 class=appendix>Appendix Paragraph</h2>
649+ <h1 class=appendix>Appendix</h1>
650+ <h2 class=appendix>Appendix Paragraph</h2>
651+ </body>
652+ </html>
653+
654+Here's the code:
655+
656+ my $toc = new HTML::Toc;
657+ my $tocInsertor = new HTML::TocInsertor;
658+
659+ $toc->setOptions({
660+ 'templateLevelBegin' => '"<ol class=toc_$groupId$level>\n"',
661+ 'templateLevelEnd' => '"</ol>\n"',
662+ 'doNumberToken' => 1,
663+ 'tokenToToc' => [{
664+ 'groupId' => 'appendix',
665+ 'tokenBegin' => '<h1>',
666+ 'numberingStyle' => 'upper-alpha'
667+ }, {
668+ 'groupId' => 'appendix',
669+ 'tokenBegin' => '<h2>',
670+ 'level' => 2,
671+ }]
672+ });
673+ $tocInsertor->insertIntoFile($toc, $filename);
674+
675+Which whill result in the following output:
676+
677+ <html>
678+ <head>
679+ <style type="text/css">
680+ ol.toc_appendix1 { list-style-type: upper-alpha }
681+ </style>
682+ </head>
683+ <body>
684+ <!-- Table of Contents generated by Perl - HTML::Toc -->
685+ <ol class=toc_appendix1>
686+ <li><a href=#appendix-A>Appendix</a>
687+ <ol class=toc_appendix2>
688+ <li><a href=#appendix-A.1>Appendix Paragraph</a>
689+ </ol>
690+ <li><a href=#appendix-B>Appendix</a>
691+ <ol class=toc_appendix2>
692+ <li><a href=#appendix-B.1>Appendix Paragraph</a>
693+ </ol>
694+ </ol>
695+ <!-- End of generated Table of Contents -->
696+
697+ <a name=appendix-A><h1>A &nbsp;Appendix</h1></a>
698+ <a name=appendix-A.1><h2>A.1 &nbsp;Appendix Paragraph</h2></a>
699+ <a name=appendix-B><h1>B &nbsp;Appendix</h1></a>
700+ <a name=appendix-B.1><h2>B.1 &nbsp;Appendix Paragraph</h2></a>
701+ </body>
702+ </html>
703+
704+=head2 Creating site map
705+
706+Suppose you want to generate a table of contents of the E<lt>titleE<gt> tags of the files in the following directory structure:
707+
708+ path file
709+
710+ . index.htm, <title>Main</title>
711+ |- SubDir1 index.htm, <title>Sub1</title>
712+ | |- SubSubDir1 index.htm, <title>SubSub1</title>
713+ |
714+ |- SubDir2 index.htm, <title>Sub2</title>
715+ | |- SubSubDir1 index.htm, <title>SubSub1</title>
716+ | |- SubSubDir2 index.htm, <title>SubSub2</title>
717+ |
718+ |- SubDir3 index.htm, <title>Sub3</title>
719+
720+By specifying 'fileSpec' which determine how many slashes (/) each file may contain for a specific level:
721+
722+ use HTML::Toc;
723+ use HTML::TocGenerator;
724+ use File::Find;
725+
726+ my $toc = HTML::Toc->new;
727+ my $tocGenerator = HTML::TocGenerator->new;
728+ my @fileList;
729+
730+ sub wanted {
731+ # Add file to 'fileList' if extension matches '.htm'
732+ push (@fileList, $File::Find::name) if (m/\.htm$/);
733+ }
734+
735+ $toc->setOptions({
736+ 'doLinkToFile' => 1,
737+ 'templateAnchorName' => '""',
738+ 'templateAnchorHref' => '"<a href=$file"."#".$groupId.$level.">"',
739+ 'doLinkTocToToken' => 1,
740+ 'tokenToToc' => [{
741+ 'groupId' => 'dir',
742+ 'level' => 1,
743+ 'tokenBegin' => '<title>',
744+ 'tokenEnd' => '</title>',
745+ 'fileSpec' => '\./[^/]+$'
746+ }, {
747+ 'groupId' => 'dir',
748+ 'level' => 2,
749+ 'tokenBegin' => '<title>',
750+ 'tokenEnd' => '</title>',
751+ 'fileSpec' => '\./[^/]+?/[^/]+$'
752+ }, {
753+ 'groupId' => 'dir',
754+ 'level' => 3,
755+ 'tokenBegin' => '<title>',
756+ 'tokenEnd' => '</title>',
757+ 'fileSpec' => '\./[^/]+?/[^/]+?/[^/]+$'
758+ }]
759+ });
760+
761+ # Traverse directory structure
762+ find({wanted => \&wanted, no_chdir => 1}, '.');
763+ # Generate ToC of case-insensitively sorted file list
764+ $tocGenerator->extendFromFile(
765+ $toc, [sort {uc($a) cmp uc($b)} @fileList]
766+ );
767+ print $toc->format();
768+
769+the following ToC will be generated:
770+
771+ <!-- Table of Contents generated by Perl - HTML::Toc -->
772+ <ul>
773+ <li><a href=./index.htm#>Main</a>
774+ <ul>
775+ <li><a href=./SubDir1/index.htm#>Sub1</a>
776+ <ul>
777+ <li><a href=./SubDir1/SubSubDir1/index.htm#>SubSub1</a>
778+ </ul>
779+ <li><a href=./SubDir2/index.htm#>Sub2</a>
780+ <ul>
781+ <li><a href=./SubDir2/SubSubDir1/index.htm#>SubSub1</a>
782+ <li><a href=./SubDir2/SubSubDir2/index.htm#>SubSub2</a>
783+ </ul>
784+ <li><a href=./SubDir3/index.htm#>Sub3</a>
785+ </ul>
786+ </ul>
787+ <!-- End of generated Table of Contents -->
788+
789+=head1 Methods
790+
791+=head2 HTML::Toc::clear()
792+
793+ syntax: $toc->clear()
794+ returns: --
795+
796+Clear the ToC.
797+
798+=head2 HTML::Toc::format()
799+
800+ syntax: $scalar = $toc->format()
801+ returns: Formatted ToC.
802+
803+Format tokenized ToC.
804+
805+=head2 HTML::TocGenerator::extend()
806+
807+ syntax: $tocGenerator->extend($toc, $string [, $options])
808+ args: - $toc: (reference to array of) HTML::Toc object(s) to extend
809+ - $string: string to retrieve ToC from
810+ - $options: hash reference containing generator options.
811+
812+Extend ToC from specified string. For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">
813+
814+=head2 HTML::TocGenerator::extendFromFile()
815+
816+ syntax: $tocGenerator->extendFromFile($toc, $filename [, $options])
817+ args: - $toc: (reference to array of) HTML::Toc object(s) to extend
818+ - $filename: (reference to array of) file(s) to extend ToC from
819+ - $options: hash reference containing generator options.
820+
821+Extend ToC from specified file. For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">. For an example, see L<Extend an existing ToC>.
822+
823+=head2 HTML::TocGenerator::generate()
824+
825+ syntax: $tocGenerator->generate($toc, $string [, $options])
826+ args: - $toc: (reference to array of) HTML::Toc object(s) to generate
827+ - $string: string to retrieve ToC from
828+ - $options: hash reference containing generator options.
829+
830+Generate ToC from specified string. Before generating, the ToC will be cleared. For extending an existing ToC, use the L<HTML::TocGenerator::extend()|"HTML::TocGenerator::extend()"> method. For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">.
831+
832+=head2 HTML::TocGenerator::generateFromFile()
833+
834+ syntax: $tocGenerator->generateFromFile($toc, $filename [, $options])
835+ args: - $toc: (reference to array of) HTML::Toc object(s) to
836+ generate
837+ - $filename: (reference to array of) file(s) to generate ToC from
838+ - $options: hash reference containing generator options.
839+
840+Generate ToC from specified file. Before generating, the ToC will be cleared. For extending an extisting ToC, use the L<HTML::TocGenerator::extendFromFile()|"HTML::TocGenerator::extendFromFile()"> method. For generator options, see L<HTML::TocGenerator Options|"HTML::TocGenerator Options">.
841+
842+=head2 HTML::TocInsertor::insert()
843+
844+ syntax: $tocInsertor->insert($toc, $string [, $options])
845+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
846+ - $string: string to insert ToC in
847+ - $options: hash reference containing insertor options.
848+
849+Insert ToC into specified string. For insertor options, see L<HTML::TocInsertor Options|"HTML::TocInsertor Options">.
850+
851+=head2 HTML::TocInsertor::insertIntoFile()
852+
853+ syntax: $tocInsertor->insertIntoFile($toc, $filename [, $options])
854+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
855+ - $filename: (reference to array of) file(s) to insert ToC in
856+ - $options: hash reference containing insertor options.
857+
858+Insert ToC into specified file. For insertor options, see L<HTML::TocInsertor Options|"HTML::TocInsertor Options">.
859+
860+=head2 HTML::TocUpdator::insert()
861+
862+ syntax: $tocUpdator->insert($toc, $string [, $options])
863+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
864+ - $string: string to insert ToC in
865+ - $options: hash reference containing updator options.
866+
867+Insert ToC into specified string. Differs from L<HTML::TocInsertor::insert()|"HTML::TocInsertor::insert()"> in that inserted text will be surrounded with update tokens in order for C<HTML::TocUpdator> to be able to update this text the next time an update is issued. For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
868+
869+=head2 HTML::TocUpdator::insertIntoFile()
870+
871+ syntax: $tocUpdator->insertIntoFile($toc, $filename [, $options])
872+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
873+ - $filename: (reference to array of) file(s) to insert ToC in
874+ - $options: hash reference containing updator options.
875+
876+Insert ToC into specified file. Differs from L<HTML::TocInsertor::insert()|"HTML::TocInsertor::insert()"> in that inserted text will be surrounded with update tokens in order for C<HTML::TocUpdator> to be able to update this text the next time an update is issued. For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
877+
878+=head2 HTML::TocUpdator::update()
879+
880+ syntax: $tocUpdator->update($toc, $string [, $options])
881+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
882+ - $string: string to update ToC in
883+ - $options: hash reference containing updator options.
884+
885+Update ToC within specified string. For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
886+
887+=head2 HTML::TocUpdator::updateFile()
888+
889+ syntax: $tocUpdator->updateFile($toc, $filename [, $options])
890+ args: - $toc: (reference to array of) HTML::Toc object(s) to insert
891+ - $filename: (reference to array of) file(s) to update ToC in
892+ - $options: hash reference containing updator options.
893+
894+Update ToC of specified file. For updator options, see L<HTML::TocUpdator Options|"HTML::TocUpdator Options">.
895+
896+=head1 Parser Options
897+
898+When generating a ToC, additional options may be specified which influence the way the ToCs are generated using either C<TocGenerator>, C<TocInsertor> or C<TocUpdator>. The options must be specified as a hash reference. For example:
899+
900+ $tocGenerator->generateFromFile($toc, $filename, {doUseGroupsGlobal => 1});
901+
902+Available options are:
903+
904+=over 4
905+
906+=item L<doGenerateToc|"doGenerateToc">
907+
908+=item L<doUseGroupsGlobal|"doUseGroupsGlobal">
909+
910+=item L<output|"output">
911+
912+=item L<outputFile|"outputFile">
913+
914+=back
915+
916+=head2 doGenerateToc
917+
918+ syntax: [0|1]
919+ default: 1
920+ applicable to: TocInsertor, TocUpdator
921+
922+True (1) if ToC must be generated. False (0) if ToC must be inserted only.
923+
924+=head2 doUseGroupsGlobal
925+
926+ syntax: [0|1]
927+ default: 0
928+ applicable to: TocGenerator, TocInsertor, TocUpdator
929+
930+True (1) if group levels must be used globally accross ToCs. False (0) if not. This option only makes sense when an array of ToCs is specified. For example, suppose you want to generate two ToCs, one ToC for '<h1>' tokens and one ToC for '<h2>' tokens, of the file 'index.htm':
931+
932+ <h1>Chapter</h1>
933+ <h2>Paragraph</h2>
934+
935+Using the default setting of 'doUseGroupsGlobal' => 0:
936+
937+ use HTML::Toc;
938+ use HTML::TocGenerator;
939+
940+ my $toc1 = HTML::Toc->new();
941+ my $toc2 = HTML::Toc->new();
942+ my $tocGenerator = HTML::TocGenerator->new();
943+
944+ $toc1->setOptions({
945+ 'header' => '',
946+ 'footer' => '',
947+ 'tokenToToc' => [{'tokenBegin' => '<h1>'}]
948+ });
949+ $toc2->setOptions({
950+ 'header' => '',
951+ 'footer' => '',
952+ 'tokenToToc' => [{'tokenBegin' => '<h2>'}]
953+ });
954+ $tocGenerator->generateFromFile([$toc1, $toc2], 'index.htm');
955+ print $toc1->format() . "\n\n" . $toc2->format();
956+
957+the output will be:
958+
959+ <ul>
960+ <li><a href=#h-1>Chapter</a>
961+ </ul>
962+
963+ <ul>
964+ <li><a href=#h-1>Paragraph</a>
965+ </ul>
966+
967+Each ToC will use its own numbering scheme. Now if 'C<doUseGroupsGlobal = 1>' is specified:
968+
969+ $tocGenerator->generateFromFile(
970+ [$toc1, $toc2], 'index.htm', {'doUseGroupsGlobal' => 1}
971+ );
972+
973+the output will be:
974+
975+ <ul>
976+ <li><a href=#h-1>Chapter</a>
977+ </ul>
978+
979+ <ul>
980+ <li><a href=#h-2>Paragraph</a>
981+ </ul>
982+
983+using a global numbering scheme for all ToCs.
984+
985+=head2 output
986+
987+ syntax: reference to scalar
988+ default: none
989+ applicable to: TocInsertor, TocUpdator
990+
991+Reference to scalar where the output must be stored in.
992+
993+=head2 outputFile
994+
995+ syntax: scalar
996+ default: none
997+ applicable to: TocInsertor, TocUpdator
998+
999+Filename to write output to. If no filename is specified, output will be written to standard output.
1000+
1001+=head1 HTML::Toc Options
1002+
1003+The C<HTML::Toc> options can be grouped in the following categories:
1004+
1005+=over 4
1006+
1007+=item L<Generate options|"Generate options">
1008+
1009+=item L<Insert options|"Insert options">
1010+
1011+=item L<Update options|"Update options">
1012+
1013+=item L<Format options|"Format options">
1014+
1015+=back
1016+
1017+The ToC options must be specified using the 'setOptions' method. For example:
1018+
1019+ my $toc = new HTML::Toc;
1020+
1021+ $toc->setOptions({
1022+ 'doNumberToken' => 1,
1023+ 'footer' => '<!-- End Of ToC -->'
1024+ 'tokenToToc' => [{
1025+ 'level' => 1,
1026+ 'tokenBegin' => '<h1>',
1027+ 'numberingStyle' => 'lower-alpha'
1028+ }]
1029+ });
1030+
1031+=head2 Generate options
1032+
1033+=over 4
1034+
1035+=item Token groups
1036+
1037+=over 4
1038+
1039+=item L<tokenToToc|"tokenToToc">
1040+
1041+=over 4
1042+
1043+=item L<doNumberToken|"doNumberToken">
1044+
1045+=item L<fileSpec|"fileSpec">
1046+
1047+=item L<groupId|"groupId">
1048+
1049+=item L<level|"level">
1050+
1051+=item L<tokenBegin|"tokenBegin">
1052+
1053+=item L<tokenEnd|"tokenEnd">
1054+
1055+=item L<numberingStyle|"numberingStyle">
1056+
1057+=back
1058+
1059+=item L<groupToToc|"groupToToc">
1060+
1061+=item L<levelToToc|"levelToToc">
1062+
1063+=back
1064+
1065+=item Numbering tokens
1066+
1067+=over 4
1068+
1069+=item L<doNumberToken|"doNumberToken">
1070+
1071+=item L<numberingStyle|"numberingStyle">
1072+
1073+=item L<templateTokenNumber|"templateTokenNumber">
1074+
1075+=back
1076+
1077+=item Miscellaneous
1078+
1079+=over 4
1080+
1081+=item L<attributeToExcludeToken|"attributeToExcludeToken">
1082+
1083+=item L<attributeToTocToken|"attributeToTocToken">
1084+
1085+=item L<groupToToc|"groupToToc">
1086+
1087+=item L<levelToToc|"levelToToc">
1088+
1089+=back
1090+
1091+=item Linking ToC to tokens
1092+
1093+=over 4
1094+
1095+=item L<doLinkToToken|"doLinkToToken">
1096+
1097+=item L<doLinkToFile|"doLinkToFile">
1098+
1099+=item L<doLinkToId|"doLinkToId">
1100+
1101+=item L<templateAnchorName|"templateAnchorName">
1102+
1103+=item L<templateAnchorHrefBegin|"templateAnchorHrefBegin">
1104+
1105+=item L<templateAnchorHrefEnd|"templateAnchorHrefEnd">
1106+
1107+=item L<templateAnchorNameBegin|"templateAnchorNameBegin">
1108+
1109+=item L<templateAnchorNameEnd|"templateAnchorNameEnd">
1110+
1111+=back
1112+
1113+=back
1114+
1115+=head2 Insert options
1116+
1117+=over 4
1118+
1119+=item L<insertionPoint|"insertionPoint">
1120+
1121+=back
1122+
1123+=head2 Update options
1124+
1125+=over 4
1126+
1127+=item L<tokenUpdateBeginAnchorName|"tokenUpdateBeginAnchorName">
1128+
1129+=item L<tokenUpdateEndAnchorName|"tokenUpdateEndAnchorName">
1130+
1131+=item L<tokenUpdateBeginToc|"tokenUpdateBeginToc">
1132+
1133+=item L<tokenUpdateEndToc|"tokenUpdateEndToc">
1134+
1135+=item L<tokenUpdateBeginNumber|"tokenUpdateBeginNumber">
1136+
1137+=item L<tokenUpdateEndNumber|"tokenUpdateEndNumber">
1138+
1139+=back
1140+
1141+=head2 Format options
1142+
1143+=over 4
1144+
1145+=item L<doSingleStepLevel|"doSingleStepLevel">
1146+
1147+=item L<doNestGroup|"doNestGroup">
1148+
1149+=item L<footer|"footer">
1150+
1151+=item L<groupToToc|"groupToToc">
1152+
1153+=item L<header|"header">
1154+
1155+=item L<levelIndent|"levelIndent">
1156+
1157+=item L<levelToToc|"levelToToc">
1158+
1159+=item L<templateLevelBegin|"templateLevelBegin">
1160+
1161+=item L<templateLevelEnd|"templateLevelEnd">
1162+
1163+=back
1164+
1165+=head1 HTML::Toc Options Reference
1166+
1167+=head2 attributeToExcludeToken
1168+
1169+ syntax: $scalar
1170+ default: '-'
1171+
1172+Token which marks an attribute value in a L<tokenBegin|"tokenBegin"> or L<insertionPoint|"insertionPoint"> token as an attribute value a token should not have to be marked as a ToC token. See also: L<Using attribute value as ToC entry|"Using attribute value as ToC text">.
1173+
1174+=head2 attributeToTocToken
1175+
1176+ syntax: $scalar
1177+ default: '@'
1178+
1179+Token which marks an attribute in a L<tokenBegin|"tokenBegin"> token as an attribute which must be used as ToC text. See also: L<Using attribute value as ToC entry|"Using attribute value as ToC text">.
1180+
1181+=head2 doLinkToToken
1182+
1183+ syntax: [0|1]
1184+ default: 1
1185+
1186+True (1) if ToC must be linked to tokens, False (0) if not. Note that 'HTML::TocInsertor' must be used to do the actual insertion of the anchor name within the source data.
1187+
1188+=head2 doLinkToFile
1189+
1190+ syntax: [0|1]
1191+ default: 0
1192+
1193+True (1) if ToC must be linked to file, False (0) if not. In effect only when L<doLinkToToken|"doLinkToToken"> equals True (1) and L<templateAnchorHrefBegin|"templateAnchorHrefBegin"> isn't specified.
1194+
1195+=head2 doLinkToId
1196+
1197+ syntax: [0|1]
1198+ default: 0
1199+
1200+True (1) if ToC must be linked to tokens by using token ids. False (0) if ToC must be linked to tokens by using anchor names.
1201+
1202+=head2 doNestGroup
1203+
1204+ syntax: [0|1]
1205+ default: 0
1206+
1207+True (1) if groups must be nested in the formatted ToC, False (0) if not. In effect only when multiple groups are specified within the L<tokenToToc|"tokenToToc"> setting. For an example, see L<Generate multiple groups in one ToC|"Generate multiple groups in one ToC">.
1208+
1209+=head2 doNumberToken
1210+
1211+ syntax: [0|1]
1212+ default: 0
1213+
1214+True (1) if tokens which are used for the ToC generation must be numbered. This option may be specified both as a global ToC option or within a L<tokenToToc|"tokenToToc"> group. When specified within a C<tokenToToc> option, the C<doNumberToken> applies to that group only. For an example, see L<Specify an additional 'Part' group|"Specify an additional 'Part' group">.
1215+
1216+=head2 doSingleStepLevel
1217+
1218+ syntax: [0|1]
1219+ default: 1
1220+
1221+True (1) if levels of a formatted ToC must advance one level at a time. For example, when generating a ToC of a file with a missing '<h2>':
1222+
1223+ <h1>Chapter</h1>
1224+ <h3>Paragraph</h3>
1225+
1226+By default, an empty indentation level will be inserted in the ToC:
1227+
1228+ <!-- Table of Contents generated by Perl - HTML::Toc -->
1229+ <ul>
1230+ <li><a href=#h-1>Header 1</a>
1231+ <ul>
1232+ <ul>
1233+ <li><a href=#h-1.0.1>Header 3</a>
1234+ </ul>
1235+ </ul>
1236+ </ul>
1237+ <!-- End of generated Table of Contents -->
1238+
1239+After specifying:
1240+
1241+ $toc->setOptions({'doSingleStepLevel' => 0});
1242+
1243+the ToC will not have an indentation level inserted for level 2:
1244+
1245+ <!-- Table of Contents generated by Perl - HTML::Toc -->
1246+ <ul>
1247+ <li><a href=#h-1>Header 1</a>
1248+ <ul>
1249+ <li><a href=#h-1.0.1>Header 3</a>
1250+ </ul>
1251+ </ul>
1252+ <!-- End of generated Table of Contents -->
1253+
1254+=head2 fileSpec
1255+
1256+ syntax: <regexp>
1257+ default: undef
1258+
1259+Specifies which files should match the current level. Valid only if L<doLinkToFile|"doLinkToFile"> equals 1. For an example, see L<Site map|"Site map">.
1260+
1261+=head2 footer
1262+
1263+ syntax: $scalar
1264+ default: "\n<!-- End of generated Table of Contents -->\n"
1265+
1266+String to output at end of ToC.
1267+
1268+=head2 groupId
1269+
1270+ syntax: $scalar
1271+ default: 'h'
1272+
1273+Sets the group id attribute of a tokenGroup. With this attribute it's possible to divide the ToC into multiple groups. Each group has its own numbering scheme. For example, to generate a ToC of both normal headings and 'appendix' headings, specify the following ToC settings:
1274+
1275+ $toc->setOptions({
1276+ 'tokenToToc' => [{
1277+ 'tokenBegin' => '<h1 class=-appendix>'
1278+ }, {
1279+ 'groupId' => 'appendix',
1280+ 'tokenBegin' => '<h1 class=appendix>'
1281+ }]
1282+ });
1283+
1284+=head2 groupToToc
1285+
1286+ syntax: <regexp>
1287+ default: '.*'
1288+
1289+Determines which groups to use for generating the ToC. For example, to create a ToC for groups [a-b] only, specify:
1290+
1291+ 'groupToToc => '[a-b]'
1292+
1293+This option is evaluated during both ToC generation and ToC formatting. This enables you to generate a ToC of all groups, but - after generating - format only specified groups:
1294+
1295+ $toc->setOptions({'groupToToc' => '.*'});
1296+ $tocGenerator->generateToc($toc, ...);
1297+ # Get ToC of all groups
1298+ $fullToc = $toc->format();
1299+ # Get ToC of 'appendix' group only
1300+ $toc->setOptions({'groupToToc' => 'appendix'});
1301+ $appendixToc = $toc->format();
1302+
1303+=head2 header
1304+
1305+ syntax: $scalar
1306+ default: "\n<!-- Table of Contents generated by Perl - HTML::Toc -->\n"
1307+
1308+String to output at begin of ToC.
1309+
1310+
1311+=head2 insertionPoint
1312+
1313+ syntax: [<before|after|replace>] <token>
1314+ default: 'after <body>'
1315+ token: <[/]tag{ attribute=[-|@]<regexp>}> |
1316+ <text regexp> |
1317+ <declaration regexp> |
1318+ <comment regexp>
1319+
1320+Determines the point within the source, where the ToC should be inserted. When specifying a start tag as the insertion point token, attributes to be included may be specified as well. Note that the attribute value must be specified as a regular expression. For example, to specify the C<<h1 class=header>> tag as insertion point:
1321+
1322+ '<h1 class=^header$>'
1323+
1324+Examples of valid 'insertionPoint' tokens are:
1325+
1326+ '<h1>'
1327+ '</h1>'
1328+ '<!-- ToC -->'
1329+ '<!ToC>'
1330+ 'ToC will be placed here'
1331+
1332+It is also possible to specify attributes to exclude, by prefixing the value with an L<attributeToExcludeToken|"attributeToExcludeToken">, default a minus sign (-). For example, to specify the C<<h1>> tag as insertion point, excluding all C<<h1 class=header>> tags:
1333+
1334+ '<h1 class=-^header$>'
1335+
1336+See also L<tokenBegin|"tokenBegin">.
1337+
1338+=head2 level
1339+
1340+ syntax: number
1341+ default: 1
1342+
1343+Number which identifies at which level the tokengroup should be incorporated into the ToC. See also: L<tokenToToc|"tokenToToc">.
1344+
1345+=head2 levelIndent
1346+
1347+ syntax: number
1348+ default: 3
1349+
1350+Sets the number of spaces each level will be indented, when formatting the ToC.
1351+
1352+=head2 levelToToc
1353+
1354+ syntax: <regexp>
1355+ default: '.*'
1356+
1357+Determines which group levels to use for generating the ToC. For example, to create a ToC for levels 1-2 only, specify:
1358+
1359+ 'levelToToc => '[1-2]'
1360+
1361+This option is evaluated during both ToC generation and ToC formatting. This enables you to generate a ToC of all levels, but - after generating - retrieve only specified levels:
1362+
1363+ $toc->setOptions({'levelToToc' => '.*'});
1364+ $tocGenerator->generateToc($toc, ...);
1365+ # Get ToC of all levels
1366+ $fullToc = $toc->getToc();
1367+ # Get ToC of level 1 only
1368+ $toc->setOptions({'levelToToc' => '1'});
1369+ $level1Toc = $toc->getToc();
1370+
1371+=head2 numberingStyle
1372+
1373+ syntax: [decimal|lower-alpha|upper-alpha|lower-roman|upper-roman]}
1374+ default: decimal
1375+
1376+Determines which numbering style to use for a token group when L<doLinkToToken|"doLinkToToken"> is set to True (1). When specified as a main ToC option, the setting will be the default for all groups. When specified within a tokengroup, this setting will override any default for that particular tokengroup, e.g.:
1377+
1378+ $toc->setOptions({
1379+ 'doNumberToken' => 1,
1380+ 'tokenToToc' => [{
1381+ 'level' => 1,
1382+ 'tokenBegin' => '<h1>',
1383+ 'numberingStyle' => 'lower-alpha'
1384+ }]
1385+ });
1386+
1387+If C<roman> style is specified, be sure to have the Roman module installed, available from L<http://www.perl.com/CPAN/modules/by-module/Roman>.
1388+
1389+=head2 templateAnchorName
1390+
1391+ syntax: <expression|function reference>
1392+ default: '$groupId."-".$node'
1393+
1394+Anchor name to use when L<doLinkToToken|"doLinkToToken"> is set to True (1). The anchor name is passed to both L<templateAnchorHrefBegin|"templateAnchorHrefBegin"> and L<templateAnchorNameBegin|"templateAnchorNameBegin">. The template may be specified as either an expression or a function reference. The expression may contain the following variables:
1395+
1396+ $file
1397+ $groupId
1398+ $level
1399+ $node
1400+
1401+If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
1402+
1403+ $toc->setOptions({'templateAnchorName' => \&assembleAnchorName});
1404+
1405+the function will be called with the following arguments:
1406+
1407+ $anchorName = assembleAnchorName($file, $groupId, $level, $node);
1408+
1409+=head2 templateAnchorHrefBegin
1410+
1411+ syntax: <expression|function reference>
1412+ default: '"<a href=#$anchorName>"' or
1413+ '"<a href=$file#$anchorName>"',
1414+ depending on 'doLinkToFile' being 0 or 1 respectively.
1415+
1416+Anchor reference begin token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1). The template may be specified as either an expression or a function reference. The expression may contain the following variables:
1417+
1418+ $file
1419+ $groupId
1420+ $level
1421+ $node
1422+ $anchorName
1423+
1424+If C<templateAnchorHrefBegin> is a function reference to a function returning the anchor, like in:
1425+
1426+ $toc->setOptions({'templateAnchorHrefBegin' => \&assembleAnchorHrefBegin});
1427+
1428+the function will be called with the following arguments:
1429+
1430+ $anchorHrefBegin = &assembleAnchorHrefBegin(
1431+ $file, $groupId, $level, $node, $anchorName
1432+ );
1433+
1434+See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorHrefEnd|"templateAnchorHrefEnd">.
1435+
1436+=head2 templateAnchorHrefEnd
1437+
1438+ syntax: <expression|function reference>
1439+ default: '"</a>"'
1440+
1441+Anchor reference end token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1). The template may be specified as either an expression or a function reference. If L<templateAnchorHrefEnd|"templateAnchorHrefEnd"> is a function reference to a function returning the anchor end, like in:
1442+
1443+ $toc->setOptions({'templateAnchorHrefEnd' => \&assembleAnchorHrefEnd});
1444+
1445+the function will be called without arguments:
1446+
1447+ $anchorHrefEnd = &assembleAnchorHrefEnd;
1448+
1449+See also: L<templateAnchorHrefBegin|"templateAnchorHrefBegin">.
1450+
1451+=head2 templateAnchorNameBegin
1452+
1453+ syntax: <expression|function reference>
1454+ default: '"<a name=$anchorName>"'
1455+
1456+Anchor name begin token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1). The template may be specified as either an expression or a function reference. The expression may contain the following variables:
1457+
1458+ $file
1459+ $groupId
1460+ $level
1461+ $node
1462+ $anchorName
1463+
1464+If C<templateAnchorNameBegin> is a function reference to a function returning the anchor name, like in:
1465+
1466+ $toc->setOptions({'templateAnchorNameBegin' => \&assembleAnchorNameBegin});
1467+
1468+the function will be called with the following arguments:
1469+
1470+ $anchorNameBegin = assembleAnchorNameBegin(
1471+ $file, $groupId, $level, $node, $anchorName
1472+ );
1473+
1474+See also: L<templateAnchorName|"templateAnchorName">, L<templateAnchorNameEnd|"templateAnchorNameEnd">.
1475+
1476+=head2 templateAnchorNameEnd
1477+
1478+ syntax: <expression|function reference>
1479+ default: '"</a>"'
1480+
1481+Anchor name end token to use when L<doLinkToToken|"doLinkToToken"> is set to True (1). The template may be specified as either an expression or a function reference. If L<templateAnchorNameEnd|"templateAnchorNameEnd"> is a function reference to a function returning the anchor end, like in:
1482+
1483+ $toc->setOptions({'templateAnchorNameEnd' => \&assembleAnchorNameEnd});
1484+
1485+the function will be called without arguments:
1486+
1487+ $anchorNameEnd = &assembleAnchorNameEnd;
1488+
1489+See also: L<templateAnchorNameBegin|"templateAnchorNameBegin">.
1490+
1491+=head2 templateLevel
1492+
1493+ syntax: <expression|function reference>
1494+ default: '"<li>$text\n"'
1495+
1496+Expression to use when formatting a ToC node. The template may be specified as either an expression or a function reference. The expression may contain the following variables:
1497+
1498+ $level
1499+ $groupId
1500+ $node
1501+ $sequenceNr
1502+ $text
1503+
1504+If C<templateLevel> is a function reference to a function returning the ToC node, like in:
1505+
1506+ $toc->setOptions({'templateLevel' => \&AssembleTocNode});
1507+
1508+the function will be called with the following arguments:
1509+
1510+ $tocNode = &AssembleTocNode(
1511+ $level, $groupId, $node, $sequenceNr, $text
1512+ );
1513+
1514+=head2 templateLevelBegin
1515+
1516+ syntax: <expression>
1517+ default: '"<ul>\n"'
1518+
1519+Expression to use when formatting begin of ToC level. See L<templateLevel|"templateLevel"> for list of available variables to use within the expression. For example, to give each ToC level a class name to use with Cascading Style Sheets (CSS), use the expression:
1520+
1521+ '"<ul class=toc_$groupId$level>\n"'
1522+
1523+which will result in each ToC group being given a class name:
1524+
1525+ <ul class=toc_h1>
1526+ <li>Header
1527+ </ul>
1528+
1529+For an example, see L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
1530+
1531+=head2 templateLevelEnd
1532+
1533+ syntax: <expression>
1534+ default: '"<ul>\n"'
1535+
1536+Expression to use when formatting end of ToC level. See L<templateLevel|"templateLevel"> for a list of available variables to use within the expression. The default expression is:
1537+
1538+ '"</ul>\n"'
1539+
1540+For an example, see L<Using CSS for ToC formatting|"Using CSS for ToC formatting">.
1541+
1542+=head2 templateTokenNumber
1543+
1544+ syntax: <expression|function reference>
1545+ default: '"$node &nbsp;"'
1546+
1547+Token number to use when L<doNumberToken|"doNumberToken"> equals True (1). The template may be specified as either an expression or a function reference. The expression has access to the following variables:
1548+
1549+ $file
1550+ $groupId
1551+ $groupLevel
1552+ $level
1553+ $node
1554+ $toc
1555+
1556+If C<templateTokenNumber> is a function reference to a function returning the token number, like in:
1557+
1558+ $toc->setOptions({'templateTokenNumber' => \&assembleTokenNumber});
1559+
1560+the function will be called with the following arguments:
1561+
1562+ $number = &assembleTokenNumber(
1563+ $node, $groupId, $file, $groupLevel, $level, $toc
1564+ );
1565+
1566+=head2 tokenBegin
1567+
1568+ syntax: <token>
1569+ default: '<h1>'
1570+ token: <[/]tag{ attribute=[-|@]<regexp>}> |
1571+ <text regexp> |
1572+ <declaration regexp> |
1573+ <comment regexp>
1574+
1575+This scalar defines the token that will trigger text to be put into the ToC. Any start tag, end tag, comment, declaration or text string can be specified. Examples of valid 'tokenBegin' tokens are:
1576+
1577+ '<h1>'
1578+ '</end>'
1579+ '<!-- Start ToC entry -->'
1580+ '<!Start ToC entry>'
1581+ 'ToC entry'
1582+
1583+When specifying a start tag, attributes to be included may be specified as well. Note that the attribute value is used as a regular expression. For example, to specify the C<<h1 class=header>> tag as tokenBegin:
1584+
1585+ '<h1 class=^header$>'
1586+
1587+It is also possible to specify attributes to exclude, by prefixing the value with an L<attributeToExcludeToken|"attributeToExcludeToken">, default a minus sign (-). For example, to specify the C<<h1>> tag as tokenBegin, excluding all C<<h1 class=header>> tags:
1588+
1589+ '<h1 class=-^header$>'
1590+
1591+Also, you can specify here an attribute value which has to be used as ToC text, by prefixing the value with an L<attributeToTocToken|"">, default an at sign (@). For example, to use the class value as ToC text:
1592+
1593+ '<h1 class=@>'
1594+
1595+See L<Generate multiple ToCs|"Generate multiple ToCs"> for an elaborated example using the C<attributeToTocToken> to generate a ToC of image C<alt> attribute values.
1596+
1597+See also: L<tokenEnd|"tokenEnd">, L<tokenToToc|"tokenToToc">.
1598+
1599+=head2 tokenEnd
1600+
1601+ syntax: $scalar
1602+ default: empty string ('') or end tag counterpart of 'tokenBegin' if
1603+ 'tokenBegin' is a start tag
1604+
1605+The 'tokenEnd' definition applies to the same rules as L<tokenBegin|"tokenBegin">.
1606+
1607+See also: L<tokenBegin|"tokenBegin">, L<tokenToToc|"tokenToToc">.
1608+
1609+=head2 tokenToToc
1610+
1611+ syntax: [{array of hashrefs}]
1612+ default: [{
1613+ 'level' => 1,
1614+ 'tokenBegin' => '<h1>'
1615+ }, {
1616+ 'level' => 2,
1617+ 'tokenBegin' => '<h2>'
1618+ }, {
1619+ 'level' => 3,
1620+ 'tokenBegin' => '<h3>'
1621+ }, {
1622+ 'level' => 4,
1623+ 'tokenBegin' => '<h4>'
1624+ }, {
1625+ 'level' => 5,
1626+ 'tokenBegin' => '<h5>'
1627+ }, {
1628+ 'level' => 6,
1629+ 'tokenBegin' => '<h6>'
1630+ }]
1631+
1632+This hash define the tokens that must act as ToC entries. Each tokengroup may contain a L<groupId|"groupId">, L<level|"level">, L<numberingStyle|"numberingStyle">, L<tokenBegin|"tokenBegin"> and L<tokenEnd|"tokenEnd"> identifier.
1633+
1634+=head2 tokenUpdateBeginAnchorName
1635+
1636+ syntax: <string>
1637+ default: '<!-- #BeginTocAnchorNameBegin -->';
1638+
1639+This token marks the begin of an anchor name, inserted by C<HTML::TocInsertor>. This option is used by C<HTML::TocUpdator>.
1640+
1641+=head2 tokenUpdateEndAnchorName
1642+
1643+ syntax: <string>
1644+ default: '<!-- #EndTocAnchorName -->';
1645+
1646+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted anchor name.
1647+
1648+=head2 tokenUpdateBeginNumber
1649+
1650+ syntax: <string>
1651+ default: '<!-- #BeginTocNumber -->';
1652+
1653+This option is used by C<HTML::TocUpdator>, to mark the begin of an inserted number.
1654+
1655+=head2 tokenUpdateEndNumber
1656+
1657+ syntax: <string>
1658+ default: '<!-- #EndTocAnchorName -->';
1659+
1660+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted number.
1661+
1662+=head2 tokenUpdateBeginToc
1663+
1664+ syntax: <string>
1665+ default: '<!-- #BeginToc -->';
1666+
1667+This option is used by C<HTML::TocUpdator>, to mark the begin of an inserted ToC.
1668+
1669+=head2 tokenUpdateEndToc
1670+
1671+ syntax: <string>
1672+ default: '<!-- #EndToc -->';
1673+
1674+This option is used by C<HTML::TocUpdator>, to mark the end of an inserted ToC.
1675+
1676+=head1 Known issues
1677+
1678+=head2 Cygwin
1679+
1680+In order for the test files to run on Cygwin without errors, the 'UNIX' default text file type has to be selected during the Cygwin setup.
1681+When extracting the tar.gz file with WinZip the 'TAR file smart CR/LF conversion' has to be turned off via {Options|Configuration...|Miscellaneous} in order for the files 'toc.pod' and './manualTest/manualTest1.htm' to be left in UNIX format.
1682+
1683+=head2 Nested anchors
1684+
1685+HTML::Toc can only link to existing anchors if these anchors are placed outside of the ToC tokens. Otherwise a warning will be given. For example, generating a L<linked|"doLinkToToken"> ToC of C<E<lt>h1E<gt>> tokens of the following text:
1686+
1687+ <a name=foo><h1>Header</h1></a>
1688+
1689+will go all right, whereas:
1690+
1691+ <h1><a name=foo>Header</a></h1>
1692+
1693+will yield the warning:
1694+
1695+ warning (1): Nested anchor '<a name=foo>' within anchor '<a name=h-1>'.
1696+
1697+since anchor names aren't allowed to be nested according to the HTML 4.01 specification.
1698+
1699+=head1 AUTHOR
1700+
1701+Freddy Vulto E<lt>L<"fvu@fvu.myweb.nl">E<gt>
1702+
1703+=head1 COPYRIGHT
1704+
1705+Copyright (c) 2001 Freddy Vulto. All rights reserved.
1706+
1707+This library is free software; you can redistribute it and/or
1708+modify it under the same terms as Perl itself.
1709+
1710+=cut
examples/includes/HTML-Toc-0.91/TocGenerator.pm+1793−0
@@ -0,0 +1,1793 @@
1+#=== HTML::TocGenerator =======================================================
2+# function: Generate 'HTML::Toc' table of contents.
3+# note: - 'TT' is an abbrevation of 'TocToken'.
4+
5+
6+package HTML::TocGenerator;
7+
8+
9+use strict;
10+use HTML::Parser;
11+
12+
13+BEGIN {
14+ use vars qw(@ISA $VERSION);
15+
16+ $VERSION = '0.91';
17+
18+ @ISA = qw(HTML::Parser);
19+}
20+
21+
22+ # Warnings
23+use constant WARNING_NESTED_ANCHOR_PS_WITHIN_PS => 1;
24+use constant WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS => 2;
25+
26+
27+use constant TOC_TOKEN_ID => 0;
28+use constant TOC_TOKEN_INCLUDE => 1;
29+use constant TOC_TOKEN_EXCLUDE => 2;
30+use constant TOC_TOKEN_TOKENS => 3;
31+use constant TOC_TOKEN_GROUP => 4;
32+use constant TOC_TOKEN_TOC => 5;
33+
34+ # Token types
35+use constant TT_TAG_BEGIN => 0;
36+use constant TT_TAG_END => 1;
37+use constant TT_TAG_TYPE_END => 2;
38+use constant TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
39+use constant TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
40+use constant TT_INCLUDE_ATTRIBUTES_END => 5;
41+use constant TT_EXCLUDE_ATTRIBUTES_END => 6;
42+use constant TT_GROUP => 7;
43+use constant TT_TOC => 8;
44+use constant TT_ATTRIBUTES_TOC => 9;
45+
46+
47+use constant CONTAINMENT_INCLUDE => 0;
48+use constant CONTAINMENT_EXCLUDE => 1;
49+
50+use constant TEMPLATE_ANCHOR => '$groupId."-".$node';
51+use constant TEMPLATE_ANCHOR_HREF =>
52+ '"<a href=#".' . TEMPLATE_ANCHOR . '.">"';
53+use constant TEMPLATE_ANCHOR_HREF_FILE =>
54+ '"<a href=".$file."#".' . TEMPLATE_ANCHOR . '.">"';
55+use constant TEMPLATE_ANCHOR_NAME =>
56+ '"<a name=".' . TEMPLATE_ANCHOR . '.">"';
57+
58+use constant TEMPLATE_TOKEN_NUMBER => '"$node &nbsp"';
59+
60+
61+use constant TT_TOKENTYPE_START => 0;
62+use constant TT_TOKENTYPE_END => 1;
63+use constant TT_TOKENTYPE_TEXT => 2;
64+use constant TT_TOKENTYPE_COMMENT => 3;
65+use constant TT_TOKENTYPE_DECLARATION => 4;
66+
67+
68+END {}
69+
70+
71+#--- HTML::TocGenerator::new() ------------------------------------------------
72+# function: Constructor
73+
74+sub new {
75+ # Get arguments
76+ my ($aType) = @_;
77+ my $self = $aType->SUPER::new;
78+ # Bias to not generate ToC
79+ $self->{_doGenerateToc} = 0;
80+ # Bias to not use global groups
81+ $self->{_doUseGroupsGlobal} = 0;
82+ # Output
83+ $self->{output} = "";
84+ # Reset internal variables
85+ $self->_resetBatchVariables();
86+
87+ $self->{options} = {};
88+
89+ return $self;
90+} # new()
91+
92+
93+#--- HTML::TocGenerator::_deinitializeBatch() ---------------------------------
94+
95+sub _deinitializeBatch() {
96+ # Get arguments
97+ my ($self) = @_;
98+} # _deinitializeBatch()
99+
100+
101+#--- HTML::TocGenerator::_deinitializeExtenderBatch() -------------------------
102+
103+sub _deinitializeExtenderBatch() {
104+ # Get arguments
105+ my ($self) = @_;
106+ # Do general batch deinitialization
107+ $self->_deinitializeBatch();
108+ # Indicate end of ToC generation
109+ $self->{_doGenerateToc} = 0;
110+ # Reset batch variables
111+ $self->_resetBatchVariables();
112+} # _deinitializeExtenderBatch()
113+
114+
115+#--- HTML::TocGenerator::_deinitializeGeneratorBatch() ------------------------
116+
117+sub _deinitializeGeneratorBatch() {
118+ # Get arguments
119+ my ($self) = @_;
120+ # Do 'extender' batch deinitialization
121+ $self->_deinitializeExtenderBatch();
122+} # _deinitializeBatchGenerator()
123+
124+
125+#--- HTML::TocGenerator::_doesHashContainHash() -------------------------------
126+# function: Determines whether hash1 matches regular expressions of hash2.
127+# args: - $aHash1
128+# - $aHash2
129+# - $aContainmentType: 0 (include) or 1 (exclude)
130+# returns: True (1) if hash1 satisfies hash2, 0 if not. For example, with the
131+# following hashes:
132+#
133+# %hash1 = { %hash2 = {
134+# 'class' => 'header' 'class' => '^h'
135+# 'id' => 'intro' }
136+# }
137+#
138+# the routine will return 1 if 'aContainmentType' equals 0, cause
139+# 'hash1' satisfies the conditions of 'hash2'. The routine will
140+# return 0 if 'aContainmentType' equals 1, cause 'hash1' doesn't
141+# exclude the conditions of 'hash2'.
142+# note: Class function.
143+
144+sub _doesHashContainHash {
145+ # Get arguments
146+ my ($aHash1, $aHash2, $aContainmentType) = @_;
147+ # Local variables
148+ my ($key1, $value1, $key2, $value2, $result);
149+ # Bias to success
150+ $result = 1;
151+ # Loop through hash2
152+ HASH2: while (($key2, $value2) = each %$aHash2) {
153+ # Yes, values are available;
154+ # Get value1
155+ $value1 = $aHash1->{$key2};
156+ # Does value1 match criteria of value2?
157+ if (defined($value1) && $value1 =~ m/$value2/) {
158+ # Yes, value1 matches criteria of value2;
159+ # Containment type was exclude?
160+ if ($aContainmentType == CONTAINMENT_EXCLUDE) {
161+ # Yes, containment type was exclude;
162+ # Indicate condition fails
163+ $result = 0;
164+ # Reset 'each' iterator which we're going to break
165+ keys %$aHash2;
166+ # Break loop
167+ last HASH2;
168+ }
169+ }
170+ else {
171+ # No, value1 didn't match criteria of value2;
172+ # Containment type was include?
173+ if ($aContainmentType == CONTAINMENT_INCLUDE) {
174+ # Yes, containment type was include;
175+ # Indicate condition fails
176+ $result = 0;
177+ # Reset 'each' iterator which we're going to break
178+ keys %$aHash2;
179+ # Break loop
180+ last HASH2;
181+ }
182+ }
183+ }
184+ # Return value
185+ return $result;
186+} # _doesHashContainHash()
187+
188+
189+#--- HTML::TocGenerator::_extend() --------------------------------------------
190+# function: Extend ToC.
191+# - $aString: String to parse.
192+
193+sub _extend {
194+ # Get arguments
195+ my ($self, $aFile) = @_;
196+ # Local variables
197+ my ($file);
198+ # Parse string
199+ $self->parse($aFile);
200+ # Flush remaining buffered text
201+ $self->eof();
202+} # _extend()
203+
204+
205+#--- HTML::TocGenerator::_extendFromFile() ------------------------------------
206+# function: Extend ToC.
207+# - $aFile: (reference to array of) file to parse.
208+
209+sub _extendFromFile {
210+ # Get arguments
211+ my ($self, $aFile) = @_;
212+ # Local variables
213+ my ($file, @files);
214+ # Dereference array reference or make array of file specification
215+ @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
216+ # Loop through files
217+ foreach $file (@files) {
218+ # Store filename
219+ $self->{_currentFile} = $file;
220+ # Parse file
221+ $self->parse_file($file);
222+ # Flush remaining buffered text
223+ $self->eof();
224+ }
225+} # _extendFromFile()
226+
227+
228+#--- HTML::TocGenerator::_formatHeadingLevel() --------------------------------
229+# function: Format heading level.
230+# args: - $aLevel: Level of current heading
231+# - $aClass: Class of current heading
232+# - $aGroup: Group of current heading
233+# - $aToc: Toc of current heading
234+
235+sub _formatHeadingLevel {
236+ # Get arguments
237+ my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
238+ # Local variables
239+ my ($result, $headingNumber, $numberingStyle);
240+
241+ $headingNumber = $self->_getGroupIdManager($aToc)->
242+ {levels}{$aClass}[$aLevel - 1] || 0;
243+
244+ # Alias numbering style of current group
245+ $numberingStyle = $aGroup->{numberingStyle};
246+
247+ SWITCH: {
248+ if ($numberingStyle eq "decimal") {
249+ $result = $headingNumber;
250+ last SWITCH;
251+ }
252+ if ($numberingStyle eq "lower-alpha") {
253+ $result = chr($headingNumber + ord('a') - 1);
254+ last SWITCH;
255+ }
256+ if ($numberingStyle eq "upper-alpha") {
257+ $result = chr($headingNumber + ord('A') - 1);
258+ last SWITCH;
259+ }
260+ if ($numberingStyle eq "lower-roman") {
261+ require Roman;
262+ $result = Roman::roman($headingNumber);
263+ last SWITCH;
264+ }
265+ if ($numberingStyle eq "upper-roman") {
266+ require Roman;
267+ $result = Roman::Roman($headingNumber);
268+ last SWITCH;
269+ }
270+ die "Unknown case: $numberingStyle";
271+ }
272+ # Return value
273+ return $result;
274+} # _formatHeadingLevel()
275+
276+
277+#--- HTML::TocGenerator::_formatTocNode() -------------------------------------
278+# function: Format heading node.
279+# args: - $aLevel: Level of current heading
280+# - $aClass: Class of current heading
281+# - $aGroup: Group of current heading
282+# - $aToc: Toc of current heading
283+
284+sub _formatTocNode {
285+ # Get arguments
286+ my ($self, $aLevel, $aClass, $aGroup, $aToc) = @_;
287+ # Local variables
288+ my ($result, $level, $levelGroups);
289+
290+ # Alias 'levelGroups' of right 'groupId'
291+ $levelGroups = $aToc->{_levelGroups}{$aGroup->{'groupId'}};
292+ # Loop through levels
293+ for ($level = 1; $level <= $aLevel; $level++) {
294+ # If not first level, add dot
295+ $result = ($result ? $result . "." : $result);
296+ # Format heading level using argument group
297+ $result .= $self->_formatHeadingLevel(
298+ $level, $aClass, @{$levelGroups}[$level - 1], $aToc
299+ );
300+ }
301+ # Return value
302+ return $result;
303+} # _formatTocNode()
304+
305+
306+#--- HTML::TocGenerator::_generate() ------------------------------------------
307+# function: Generate ToC.
308+# args: - $aString: Reference to string to parse
309+
310+sub _generate {
311+ # Get arguments
312+ my ($self, $aString) = @_;
313+ # Local variables
314+ my ($toc);
315+ # Loop through ToCs
316+ foreach $toc (@{$self->{_tocs}}) {
317+ # Clear ToC
318+ $toc->clear();
319+ }
320+ # Extend ToCs
321+ $self->_extend($aString);
322+} # _generate()
323+
324+
325+#--- HTML::TocGenerator::_generateFromFile() ----------------------------------
326+# function: Generate ToC.
327+# args: - $aFile: (reference to array of) file to parse.
328+
329+sub _generateFromFile {
330+ # Get arguments
331+ my ($self, $aFile) = @_;
332+ # Local variables
333+ my ($toc);
334+ # Loop through ToCs
335+ foreach $toc (@{$self->{_tocs}}) {
336+ # Clear ToC
337+ $toc->clear();
338+ }
339+ # Extend ToCs
340+ $self->_extendFromFile($aFile);
341+} # _generateFromFile()
342+
343+
344+#--- HTML::TocGenerator::_getGroupIdManager() ---------------------------------
345+# function: Get group id manager.
346+# args: - $aToc: Active ToC.
347+# returns: Group id levels.
348+
349+sub _getGroupIdManager {
350+ # Get arguments
351+ my ($self, $aToc) = @_;
352+ # Local variables
353+ my ($result);
354+ # Global groups?
355+ if ($self->{options}{'doUseGroupsGlobal'}) {
356+ # Yes, global groups;
357+ $result = $self;
358+ }
359+ else {
360+ # No, local groups;
361+ $result = $aToc;
362+ }
363+ # Return value
364+ return $result;
365+} # _getGroupIdManager()
366+
367+
368+#--- HTML::TocGenerator::_initializeBatch() -----------------------------------
369+# function: Initialize batch. This function is called once when a parse batch
370+# is started.
371+# args: - $aTocs: Reference to array of tocs.
372+
373+sub _initializeBatch {
374+ # Get arguments
375+ my ($self, $aTocs) = @_;
376+ # Local variables
377+ my ($toc);
378+
379+ # Store reference to tocs
380+
381+ # Is ToC specification reference to array?
382+ if (ref($aTocs) =~ m/ARRAY/) {
383+ # Yes, ToC specification is reference to array;
384+ # Store array reference
385+ $self->{_tocs} = $aTocs;
386+ }
387+ else {
388+ # No, ToC specification is reference to ToC object;
389+ # Wrap reference in array reference, containing only one element
390+ $self->{_tocs} = [$aTocs];
391+ }
392+ # Loop through ToCs
393+ foreach $toc (@{$self->{_tocs}}) {
394+ # Parse ToC options
395+ $toc->parseOptions();
396+ }
397+} # _initializeBatch()
398+
399+
400+#--- HTML::TocGenerator::_initializeExtenderBatch() --------------------------
401+# function: Initialize 'extender' batch. This function is called once when a
402+# parse batch is started.
403+# args: - $aTocs: Reference to array of tocs.
404+
405+sub _initializeExtenderBatch {
406+ # Get arguments
407+ my ($self, $aTocs) = @_;
408+ # Do general batch initialization
409+ $self->_initializeBatch($aTocs);
410+ # Parse ToC options
411+ $self->_parseTocOptions();
412+ # Indicate start of batch
413+ $self->{_doGenerateToc} = 1;
414+} # _initializeExtenderBatch()
415+
416+
417+#--- HTML::TocGenerator::_initializeGeneratorBatch() --------------------------
418+# function: Initialize generator batch. This function is called once when a
419+# parse batch is started.
420+# args: - $aTocs: Reference to array of tocs.
421+# - $aOptions: optional options
422+
423+sub _initializeGeneratorBatch {
424+ # Get arguments
425+ my ($self, $aTocs, $aOptions) = @_;
426+ # Add invocation options
427+ $self->setOptions($aOptions);
428+ # Option 'doUseGroupsGlobal' specified?
429+ if (!defined($self->{options}{'doUseGroupsGlobal'})) {
430+ # No, options 'doUseGroupsGlobal' not specified;
431+ # Default to no 'doUseGroupsGlobal'
432+ $self->{options}{'doUseGroupsGlobal'} = 0;
433+ }
434+ # Global groups?
435+ if ($self->{options}{'doUseGroupsGlobal'}) {
436+ # Yes, global groups;
437+ # Reset groups and levels
438+ $self->_resetStackVariables();
439+ }
440+ # Do 'extender' batch initialization
441+ $self->_initializeExtenderBatch($aTocs);
442+} # _initializeGeneratorBatch()
443+
444+
445+#--- HTML::TocGenerator::_linkTocToToken() ------------------------------------
446+# function: Link ToC to token.
447+# args: - $aToc: ToC to add token to.
448+# - $aFile
449+# - $aGroupId
450+# - $aLevel
451+# - $aNode
452+# - $aGroupLevel
453+# - $aLinkType
454+# - $aTokenAttributes: reference to hash containing attributes of
455+# currently parsed token
456+
457+sub _linkTocToToken {
458+ # Get arguments
459+ my (
460+ $self, $aToc, $aFile, $aGroupId, $aLevel, $aNode, $aGroupLevel,
461+ $aDoLinkToId, $aTokenAttributes
462+ ) = @_;
463+ # Local variables
464+ my ($file, $groupId, $level, $node, $anchorName);
465+ my ($doInsertAnchor, $doInsertId);
466+
467+ # Fill local arguments to be used by templates
468+ $file = $aFile;
469+ $groupId = $aGroupId;
470+ $level = $aLevel;
471+ $node = $aNode;
472+
473+ # Assemble anchor name
474+ $anchorName =
475+ ref($aToc->{_templateAnchorName}) eq "CODE" ?
476+ &{$aToc->{_templateAnchorName}}(
477+ $aFile, $aGroupId, $aLevel, $aNode
478+ ) :
479+ eval($aToc->{_templateAnchorName});
480+
481+ # Bias to insert anchor name
482+ $doInsertAnchor = 1;
483+ $doInsertId = 0;
484+ # Link to 'id'?
485+ if ($aDoLinkToId) {
486+ # Yes, link to 'id';
487+ # Indicate to insert anchor id
488+ $doInsertAnchor = 0;
489+ $doInsertId = 1;
490+ # Id attribute is available?
491+ if (defined($aTokenAttributes->{id})) {
492+ # Yes, id attribute is available;
493+ # Use existing ids?
494+ if ($aToc->{options}{'doUseExistingIds'}) {
495+ # Yes, use existing ids;
496+ # Use existing id
497+ $anchorName = $aTokenAttributes->{id};
498+ # Indicate to not insert id
499+ $doInsertId = 0;
500+ }
501+ }
502+
503+ }
504+ else {
505+ # No, link to 'name';
506+ # Anchor name is currently active?
507+ if (defined($self->{_activeAnchorName})) {
508+ # Yes, anchor name is currently active;
509+ # Use existing anchors?
510+ if ($aToc->{options}{'doUseExistingAnchors'}) {
511+ # Yes, use existing anchors;
512+ # Use existing anchor name
513+ $anchorName = $self->{_activeAnchorName};
514+ # Indicate to not insert anchor name
515+ $doInsertAnchor = 0;
516+ }
517+ else {
518+ # No, don't use existing anchors; insert new anchor;
519+ #
520+ }
521+ }
522+ }
523+
524+ # Add reference to ToC
525+ $aToc->{_toc} .=
526+ ref($aToc->{_templateAnchorHrefBegin}) eq "CODE" ?
527+ &{$aToc->{_templateAnchorHrefBegin}}(
528+ $aFile, $aGroupId, $aLevel, $aNode, $anchorName
529+ ) :
530+ eval($aToc->{_templateAnchorHrefBegin});
531+
532+ # Bias to not output anchor name end
533+ $self->{_doOutputAnchorNameEnd} = 0;
534+ # Must anchor be inserted?
535+ if ($doInsertAnchor) {
536+ # Yes, anchor must be inserted;
537+ # Allow adding of anchor name begin token to text by calling
538+ # 'anchorNameBegin' method
539+ $self->anchorNameBegin(
540+ ref($aToc->{_templateAnchorNameBegin}) eq "CODE" ?
541+ &{$aToc->{_templateAnchorNameBegin}}(
542+ $aFile, $aGroupId, $aLevel, $aNode, $anchorName
543+ ) :
544+ eval($aToc->{_templateAnchorNameBegin}),
545+ $aToc
546+ );
547+ }
548+
549+ # Must anchorId attribute be inserted?
550+ if ($doInsertId) {
551+ # Yes, anchorId attribute must be inserted;
552+ # Allow adding of anchorId attribute to text by calling 'anchorId'
553+ # method
554+ $self->anchorId($anchorName);
555+ }
556+} # _linkTocToToken()
557+
558+
559+#--- HTML::TocGenerator::_outputAnchorNameEndConditionally() ------------------
560+# function: Output 'anchor name end' if necessary
561+# args: - $aToc: ToC of which 'anchor name end' must be output.
562+
563+sub _outputAnchorNameEndConditionally {
564+ # Get arguments
565+ my ($self, $aToc) = @_;
566+ # Must anchor name end be output?
567+ if ($self->{_doOutputAnchorNameEnd}) {
568+ # Yes, output anchor name end;
569+ # Allow adding of anchor to text by calling 'anchorNameEnd'
570+ # method
571+ $self->anchorNameEnd(
572+ ref($aToc->{_templateAnchorNameEnd}) eq "CODE" ?
573+ &{$aToc->{_templateAnchorNameEnd}} :
574+ eval($aToc->{_templateAnchorNameEnd}),
575+ $aToc
576+ );
577+ }
578+} # _outputAnchorNameEndConditionally()
579+
580+
581+#--- HTML::TocGenerator::_parseTocOptions() -----------------------------------
582+# function: Parse ToC options.
583+
584+sub _parseTocOptions {
585+ # Get arguments
586+ my ($self) = @_;
587+ # Local variables
588+ my ($toc, $group, $tokens, $tokenType, $i);
589+ # Create parsers for ToC tokens
590+ $self->{_tokensTocBegin} = [];
591+ my $tokenTocBeginParser = HTML::_TokenTocBeginParser->new(
592+ $self->{_tokensTocBegin}
593+ );
594+ my $tokenTocEndParser = HTML::_TokenTocEndParser->new();
595+ # Loop through ToCs
596+ foreach $toc (@{$self->{_tocs}}) {
597+ # Reference parser ToC to current ToC
598+ $tokenTocBeginParser->setToc($toc);
599+ # Loop through 'tokenToToc' groups
600+ foreach $group (@{$toc->{options}{'tokenToToc'}}) {
601+ # Reference parser group to current group
602+ $tokenTocBeginParser->setGroup($group);
603+ # Parse 'tokenToToc' group
604+ $tokenTocBeginParser->parse($group->{'tokenBegin'});
605+ # Flush remaining buffered text
606+ $tokenTocBeginParser->eof();
607+ $tokenTocEndParser->parse(
608+ $group->{'tokenEnd'},
609+ $tokenTocBeginParser->{_lastAddedToken},
610+ $tokenTocBeginParser->{_lastAddedTokenType}
611+ );
612+ # Flush remaining buffered text
613+ $tokenTocEndParser->eof();
614+ }
615+ }
616+} # _parseTocOptions()
617+
618+
619+#--- HTML::TocGenerator::_processTocEndingToken() -----------------------------
620+# function: Process ToC-ending-token.
621+# args: - $aTocToken: token which acts as ToC-ending-token.
622+
623+sub _processTocEndingToken {
624+ # Get arguments
625+ my ($self, $aTocToken) = @_;
626+ # Local variables
627+ my ($toc);
628+ # Aliases
629+ $toc = $aTocToken->[TT_TOC];
630+ # Link ToC to tokens?
631+ if ($toc->{options}{'doLinkToToken'}) {
632+ # Yes, link ToC to tokens;
633+ # Add anchor href end
634+ $toc->{_toc} .=
635+ (ref($toc->{_templateAnchorHrefEnd}) eq "CODE") ?
636+ &{$toc->{_templateAnchorHrefEnd}} :
637+ eval($toc->{_templateAnchorHrefEnd});
638+
639+ # Output anchor name end only if necessary
640+ $self->_outputAnchorNameEndConditionally($toc);
641+ }
642+} # _processTocEndingToken()
643+
644+
645+#--- HTML::TocGenerator::_processTocStartingToken() ---------------------------
646+# function: Process ToC-starting-token.
647+# args: - $aTocToken: token which acts as ToC-starting-token.
648+# - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
649+# _END, _TEXT, _COMMENT or _DECLARATION.
650+# - $aTokenAttributes: reference to hash containing attributes of
651+# currently parsed token
652+# - $aTokenOrigText: reference to original token text
653+
654+sub _processTocStartingToken {
655+ # Get arguments
656+ my ($self, $aTocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText) = @_;
657+ # Local variables
658+ my ($i, $level, $doLinkToId, $node, $groupLevel);
659+ my ($file, $tocTokenId, $groupId, $toc, $attribute);
660+ # Aliases
661+ $file = $self->{_currentFile};
662+ $toc = $aTocToken->[TT_TOC];
663+ $level = $aTocToken->[TT_GROUP]{'level'};
664+ $groupId = $aTocToken->[TT_GROUP]{'groupId'};
665+
666+ # Retrieve 'doLinkToId' setting from either group options or toc options
667+ $doLinkToId = (defined($aTocToken->[TT_GROUP]{'doLinkToId'})) ?
668+ $aTocToken->[TT_GROUP]{'doLinkToId'} : $toc->{options}{'doLinkToId'};
669+
670+ # Link to 'id' and tokenType isn't 'start'?
671+ if (($doLinkToId) && ($aTokenType != TT_TOKENTYPE_START)) {
672+ # Yes, link to 'id' and tokenType isn't 'start';
673+ # Indicate to *not* link to 'id'
674+ $doLinkToId = 0;
675+ }
676+
677+ if (ref($level) eq "CODE") {
678+ $level = &$level($self->{_currentFile}, $node);
679+ }
680+ if (ref($groupId) eq "CODE") {
681+ $groupId = &$groupId($self->{_currentFile}, $node);
682+ }
683+
684+ # Determine class level
685+
686+ my $groupIdManager = $self->_getGroupIdManager($toc);
687+ # Known group?
688+ if (!exists($groupIdManager->{groupIdLevels}{$groupId})) {
689+ # No, unknown group;
690+ # Add group
691+ $groupIdManager->{groupIdLevels}{$groupId} = keys(
692+ %{$groupIdManager->{groupIdLevels}}
693+ ) + 1;
694+ }
695+ $groupLevel = $groupIdManager->{groupIdLevels}{$groupId};
696+
697+ # Temporarily allow symbolic references
698+ #no strict qw(refs);
699+ # Increase level
700+ $groupIdManager->{levels}{$groupId}[$level - 1] += 1;
701+ # Reset remaining levels of same group
702+ for ($i = $level; $i < @{$groupIdManager->{levels}{$groupId}}; $i++) {
703+ $groupIdManager->{levels}{$groupId}[$i] = 0;
704+ }
705+
706+ # Assemble numeric string indicating current level
707+ $node = $self->_formatTocNode(
708+ $level, $groupId, $aTocToken->[TT_GROUP], $toc
709+ );
710+
711+ # Add newline if _toc not empty
712+ if ($toc->{_toc}) {
713+ $toc->{_toc} .= "\n";
714+ }
715+
716+ # Add toc item info
717+ $toc->{_toc} .= "$level $groupLevel $groupId $node " .
718+ $groupIdManager->{levels}{$groupId}[$level - 1] . " ";
719+
720+ # Add value of 'id' attribute if available
721+ if (defined($aTokenAttributes->{id})) {
722+ $toc->{_toc} .= $aTokenAttributes->{id};
723+ }
724+ $toc->{_toc} .= " ";
725+ # Link ToC to tokens?
726+ if ($toc->{options}{'doLinkToToken'}) {
727+ # Yes, link ToC to tokens;
728+ # Link ToC to token
729+ $self->_linkTocToToken(
730+ $toc, $file, $groupId, $level, $node, $groupLevel, $doLinkToId,
731+ $aTokenAttributes
732+ );
733+ }
734+
735+ # Number tokens?
736+ if (
737+ $aTocToken->[TT_GROUP]{'doNumberToken'} ||
738+ (
739+ ! defined($aTocToken->[TT_GROUP]{'doNumberToken'}) &&
740+ $toc->{options}{'doNumberToken'}
741+ )
742+ ) {
743+ # Yes, number tokens;
744+ # Add number by calling 'number' method
745+ $self->number(
746+ ref($toc->{_templateTokenNumber}) eq "CODE" ?
747+ &{$toc->{_templateTokenNumber}}(
748+ $node, $groupId, $file, $groupLevel, $level, $toc
749+ ) :
750+ eval($toc->{_templateTokenNumber}),
751+ $toc
752+ );
753+ }
754+
755+ # Must attribute be used as ToC text?
756+ if (defined($aTocToken->[TT_ATTRIBUTES_TOC])) {
757+ # Yes, attribute must be used as ToC text;
758+ # Loop through attributes
759+ foreach $attribute (@{$aTocToken->[TT_ATTRIBUTES_TOC]}) {
760+ # Attribute is available?
761+ if (defined($$aTokenAttributes{$attribute})) {
762+ # Yes, attribute is available;
763+ # Add attribute value to ToC
764+ $self->_processTocText($$aTokenAttributes{$attribute}, $toc);
765+ }
766+ else {
767+ # No, attribute isn't available;
768+ # Show warning
769+ $self->_showWarning(
770+ WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS,
771+ [$attribute, $$aTokenOrigText]
772+ );
773+ }
774+ # Output anchor name end only if necessary
775+ #$self->_outputAnchorNameEndConditionally($toc);
776+ # End attribute
777+ $self->_processTocEndingToken($aTocToken);
778+ }
779+ }
780+ else {
781+ # No, attribute mustn't be used as ToC text;
782+ # Add end token to 'end token array'
783+ push(
784+ @{$self->{_tokensTocEnd}[$aTocToken->[TT_TAG_TYPE_END]]}, $aTocToken
785+ );
786+ }
787+} # _processTocStartingToken()
788+
789+
790+#--- HTML::TocGenerator::_processTocText() ------------------------------------
791+# function: This function processes text which must be added to the preliminary
792+# ToC.
793+# args: - $aText: Text to add to ToC.
794+# - $aToc: ToC to add text to.
795+
796+sub _processTocText {
797+ # Get arguments
798+ my ($self, $aText, $aToc) = @_;
799+ # Add text to ToC
800+ $aToc->{_toc} .= $aText;
801+} # _processTocText()
802+
803+
804+#--- HTML::TocGenerator::_processTokenAsTocEndingToken() ----------------------
805+# function: Check for token being a token to use for triggering the end of
806+# a ToC line and process it accordingly.
807+# args: - $aTokenType: type of token: 'start', 'end', 'comment' or 'text'.
808+# - $aTokenId: token id of currently parsed token
809+
810+sub _processTokenAsTocEndingToken {
811+ # Get arguments
812+ my ($self, $aTokenType, $aTokenId) = @_;
813+ # Local variables
814+ my ($i, $tokenId, $toc, $tokens);
815+ # Loop through dirty start tokens
816+ $i = 0;
817+
818+ # Alias token array of right type
819+ $tokens = $self->{_tokensTocEnd}[$aTokenType];
820+ # Loop through token array
821+ while ($i < scalar @$tokens) {
822+ # Aliases
823+ $tokenId = $tokens->[$i][TT_TAG_END];
824+ # Does current end tag equals dirty tag?
825+ if ($aTokenId eq $tokenId) {
826+ # Yes, current end tag equals dirty tag;
827+ # Process ToC-ending-token
828+ $self->_processTocEndingToken($tokens->[$i]);
829+ # Remove dirty tag from array, automatically advancing to
830+ # next token
831+ splice(@$tokens, $i, 1);
832+ }
833+ else {
834+ # No, current end tag doesn't equal dirty tag;
835+ # Advance to next token
836+ $i++;
837+ }
838+ }
839+} # _processTokenAsTocEndingToken()
840+
841+
842+#--- HTML::TocGenerator::_processTokenAsTocStartingToken() --------------------
843+# function: Check for token being a ToC-starting-token and process it
844+# accordingly.
845+# args: - $aTokenType: type of token. Can be either TT_TOKENTYPE_START,
846+# _END, _TEXT, _COMMENT or _DECLARATION.
847+# - $aTokenId: token id of currently parsed token
848+# - $aTokenAttributes: reference to hash containing attributes of
849+# currently parsed token
850+# - $aTokenOrigText: reference to original text of token
851+# returns: 1 if successful, i.e. token is processed as ToC-starting-token, 0
852+# if not.
853+
854+sub _processTokenAsTocStartingToken {
855+ # Get arguments
856+ my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aTokenOrigText) = @_;
857+ # Local variables
858+ my ($level, $levelToToc, $groupId, $groupToToc);
859+ my ($result, $tocToken, $tagBegin, @tokensTocBegin, $fileSpec);
860+ # Bias to token not functioning as ToC-starting-token
861+ $result = 0;
862+ # Loop through start tokens of right type
863+ foreach $tocToken (@{$self->{_tokensTocBegin}[$aTokenType]}) {
864+ # Alias file filter
865+ $fileSpec = $tocToken->[TT_GROUP]{'fileSpec'};
866+ # File matches?
867+ if (!defined($fileSpec) || (
868+ defined($fileSpec) &&
869+ ($self->{_currentFile} =~ m/$fileSpec/)
870+ )) {
871+ # Yes, file matches;
872+ # Alias tag begin
873+ $tagBegin = $tocToken->[TT_TAG_BEGIN];
874+ # Tag and attributes match?
875+ if (
876+ defined($tagBegin) &&
877+ ($aTokenId =~ m/$tagBegin/) &&
878+ HTML::TocGenerator::_doesHashContainHash(
879+ $aTokenAttributes, $tocToken->[TT_INCLUDE_ATTRIBUTES_BEGIN], 0
880+ ) &&
881+ HTML::TocGenerator::_doesHashContainHash(
882+ $aTokenAttributes, $tocToken->[TT_EXCLUDE_ATTRIBUTES_BEGIN], 1
883+ )
884+ ) {
885+ # Yes, tag and attributes match;
886+ # Aliases
887+ $level = $tocToken->[TT_GROUP]{'level'};
888+ $levelToToc = $tocToken->[TT_TOC]{options}{'levelToToc'};
889+ $groupId = $tocToken->[TT_GROUP]{'groupId'};
890+ $groupToToc = $tocToken->[TT_TOC]{options}{'groupToToc'};
891+ # Must level and group be processed?
892+ if (
893+ ($level =~ m/$levelToToc/) &&
894+ ($groupId =~ m/$groupToToc/)
895+ ) {
896+ # Yes, level and group must be processed;
897+ # Indicate token acts as ToC-starting-token
898+ $result = 1;
899+ # Process ToC-starting-token
900+ $self->_processTocStartingToken(
901+ $tocToken, $aTokenType, $aTokenAttributes, $aTokenOrigText
902+ );
903+ }
904+ }
905+ }
906+ }
907+ # Return value
908+ return $result;
909+} # _processTokenAsTocStartingToken()
910+
911+
912+#--- HTML::TocGenerator::_resetBatchVariables() -------------------------------
913+# function: Reset variables which are set because of batch invocation.
914+
915+sub _resetBatchVariables {
916+ # Get arguments
917+ my ($self) = @_;
918+
919+ # Filename of current file being parsed, empty string if not available
920+ $self->{_currentFile} = "";
921+ # Arrays containing start, end, comment, text & declaration tokens which
922+ # must trigger the ToC assembling. Each array element may contain a
923+ # reference to an array containing the following elements:
924+ #
925+ # TT_TAG_BEGIN => 0;
926+ # TT_TAG_END => 1;
927+ # TT_TAG_TYPE_END => 2;
928+ # TT_INCLUDE_ATTRIBUTES_BEGIN => 3;
929+ # TT_EXCLUDE_ATTRIBUTES_BEGIN => 4;
930+ # TT_INCLUDE_ATTRIBUTES_END => 5;
931+ # TT_EXCLUDE_ATTRIBUTES_END => 6;
932+ # TT_GROUP => 7;
933+ # TT_TOC => 8;
934+ # TT_ATTRIBUTES_TOC => 9;
935+ #
936+ $self->{_tokensTocBegin} = [
937+ [], # TT_TOKENTYPE_START
938+ [], # TT_TOKENTYPE_END
939+ [], # TT_TOKENTYPE_COMMENT
940+ [], # TT_TOKENTYPE_TEXT
941+ [] # TT_TOKENTYPE_DECLARATION
942+ ];
943+ $self->{_tokensTocEnd} = [
944+ [], # TT_TOKENTYPE_START
945+ [], # TT_TOKENTYPE_END
946+ [], # TT_TOKENTYPE_COMMENT
947+ [], # TT_TOKENTYPE_TEXT
948+ [] # TT_TOKENTYPE_DECLARATION
949+ ];
950+ # TRUE if ToCs have been initialized, FALSE if not.
951+ $self->{_doneInitializeTocs} = 0;
952+ # Array of ToCs to process
953+ $self->{_tocs} = [];
954+ # Active anchor name
955+ $self->{_activeAnchorName} = undef;
956+} # _resetBatchVariables()
957+
958+
959+#--- HTML::TocGenerator::_resetStackVariables() -------------------------------
960+# function: Reset variables which cumulate during ToC generation.
961+
962+sub _resetStackVariables {
963+ # Get arguments
964+ my ($self) = @_;
965+ # Reset variables
966+ $self->{levels} = undef;
967+ $self->{groupIdLevels} = undef;
968+} # _resetStackVariables()
969+
970+
971+#--- HTML::TocGenerator::_setActiveAnchorName() -------------------------------
972+# function: Set active anchor name.
973+# args: - aAnchorName: Name of anchor name to set active.
974+
975+sub _setActiveAnchorName {
976+ # Get arguments
977+ my ($self, $aAnchorName) = @_;
978+ # Set active anchor name
979+ $self->{_activeAnchorName} = $aAnchorName;
980+} # _setActiveAnchorName()
981+
982+
983+#--- HTML::TocGenerator::_showWarning() ---------------------------------------
984+# function: Show warning.
985+# args: - aWarningNr: Number of warning to show.
986+# - aWarningArgs: Arguments to display within the warning.
987+
988+sub _showWarning {
989+ # Get arguments
990+ my ($self, $aWarningNr, $aWarningArgs) = @_;
991+ # Local variables
992+ my (%warnings);
993+ # Set warnings
994+ %warnings = (
995+ WARNING_NESTED_ANCHOR_PS_WITHIN_PS() =>
996+ "Nested anchor '%s' within anchor '%s'.",
997+ WARNING_TOC_ATTRIBUTE_PS_NOT_AVAILABLE_WITHIN_PS() =>
998+ "ToC attribute '%s' not available within token '%s'.",
999+ );
1000+ # Show warning
1001+ print STDERR "warning ($aWarningNr): " . sprintf($warnings{"$aWarningNr"}, @$aWarningArgs) . "\n";
1002+} # _showWarning()
1003+
1004+
1005+#--- HTML::TocGenerator::anchorId() -------------------------------------------
1006+# function: Anchor id processing method. Leave it up to the descendant to do
1007+# something useful with it.
1008+# args: - $aAnchorId
1009+# - $aToc: Reference to ToC to which anchorId belongs.
1010+
1011+sub anchorId {
1012+} # anchorId()
1013+
1014+
1015+#--- HTML::TocGenerator::anchorNameBegin() ------------------------------------
1016+# function: Anchor name begin processing method. Leave it up to the descendant
1017+# to do something useful with it.
1018+# args: - $aAnchorName
1019+# - $aToc: Reference to ToC to which anchorname belongs.
1020+
1021+sub anchorNameBegin {
1022+} # anchorNameBegin()
1023+
1024+
1025+#--- HTML::TocGenerator::anchorNameEnd() --------------------------------------
1026+# function: Anchor name end processing method. Leave it up to the descendant
1027+# to do something useful with it.
1028+# args: - $aAnchorName
1029+# - $aToc: Reference to ToC to which anchorname belongs.
1030+
1031+sub anchorNameEnd {
1032+} # anchorNameEnd()
1033+
1034+
1035+#--- HTML::TocGenerator::comment() --------------------------------------------
1036+# function: Process comment.
1037+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1038+
1039+sub comment {
1040+ # Get arguments
1041+ my ($self, $aComment) = @_;
1042+ # Must a ToC be generated?
1043+ if ($self->{_doGenerateToc}) {
1044+ # Yes, a ToC must be generated
1045+ # Process end tag as ToC-starting-token
1046+ $self->_processTokenAsTocStartingToken(
1047+ TT_TOKENTYPE_COMMENT, $aComment, undef, \$aComment
1048+ );
1049+ # Process end tag as token which ends ToC registration
1050+ $self->_processTokenAsTocEndingToken(
1051+ TT_TOKENTYPE_COMMENT, $aComment
1052+ );
1053+ }
1054+} # comment()
1055+
1056+
1057+#--- HTML::TocGenerator::end() ------------------------------------------------
1058+# function: This function is called every time a closing tag is encountered.
1059+# args: - $aTag: tag name (in lower case).
1060+# - $aOrigText: tag name including brackets.
1061+
1062+sub end {
1063+ # Get arguments
1064+ my ($self, $aTag, $aOrigText) = @_;
1065+ # Local variables
1066+ my ($tag, $toc, $i);
1067+ # Must a ToC be generated?
1068+ if ($self->{_doGenerateToc}) {
1069+ # Yes, a ToC must be generated
1070+ # Process end tag as ToC-starting-token
1071+ $self->_processTokenAsTocStartingToken(
1072+ TT_TOKENTYPE_END, $aTag, undef, \$aOrigText
1073+ );
1074+ # Process end tag as ToC-ending-token
1075+ $self->_processTokenAsTocEndingToken(
1076+ TT_TOKENTYPE_END, $aTag
1077+ );
1078+ # Tag is of type 'anchor'?
1079+ if (defined($self->{_activeAnchorName}) && ($aTag eq "a")) {
1080+ # Yes, tag is of type 'anchor';
1081+ # Reset dirty anchor
1082+ $self->{_activeAnchorName} = undef;
1083+ }
1084+ }
1085+} # end()
1086+
1087+
1088+#--- HTML::TocGenerator::extend() ---------------------------------------------
1089+# function: Extend ToCs.
1090+# args: - $aTocs: Reference to array of ToC objects
1091+# - $aString: String to parse.
1092+
1093+sub extend {
1094+ # Get arguments
1095+ my ($self, $aTocs, $aString) = @_;
1096+ # Initialize TocGenerator batch
1097+ $self->_initializeExtenderBatch($aTocs);
1098+ # Extend ToCs
1099+ $self->_extend($aString);
1100+ # Deinitialize TocGenerator batch
1101+ $self->_deinitializeExtenderBatch();
1102+} # extend()
1103+
1104+
1105+#--- HTML::TocGenerator::extendFromFile() -------------------------------------
1106+# function: Extend ToCs.
1107+# args: - @aTocs: Reference to array of ToC objects
1108+# - @aFiles: Reference to array of files to parse.
1109+
1110+sub extendFromFile {
1111+ # Get arguments
1112+ my ($self, $aTocs, $aFiles) = @_;
1113+ # Initialize TocGenerator batch
1114+ $self->_initializeExtenderBatch($aTocs);
1115+ # Extend ToCs
1116+ $self->_extendFromFile($aFiles);
1117+ # Deinitialize TocGenerator batch
1118+ $self->_deinitializeExtenderBatch();
1119+} # extendFromFile()
1120+
1121+
1122+#--- HTML::TocGenerator::generate() -------------------------------------------
1123+# function: Generate ToC.
1124+# args: - $aToc: Reference to (array of) ToC object(s)
1125+# - $aString: Reference to string to parse
1126+# - $aOptions: optional options
1127+
1128+sub generate {
1129+ # Get arguments
1130+ my ($self, $aToc, $aString, $aOptions) = @_;
1131+ # Initialize TocGenerator batch
1132+ $self->_initializeGeneratorBatch($aToc, $aOptions);
1133+ # Do generate ToC
1134+ $self->_generate($aString);
1135+ # Deinitialize TocGenerator batch
1136+ $self->_deinitializeGeneratorBatch();
1137+} # generate()
1138+
1139+
1140+#--- HTML::TocGenerator::generateFromFile() -----------------------------------
1141+# function: Generate ToC.
1142+# args: - $aToc: Reference to (array of) ToC object(s)
1143+# - $aFile: (reference to array of) file to parse.
1144+# - $aOptions: optional options
1145+
1146+sub generateFromFile {
1147+ # Get arguments
1148+ my ($self, $aToc, $aFile, $aOptions) = @_;
1149+ # Initialize TocGenerator batch
1150+ $self->_initializeGeneratorBatch($aToc, $aOptions);
1151+ # Do generate ToC
1152+ $self->_generateFromFile($aFile);
1153+ # Deinitialize TocGenerator batch
1154+ $self->_deinitializeGeneratorBatch();
1155+} # generateFromFile()
1156+
1157+
1158+#--- HTML::TocGenerator::number() ---------------------------------------------
1159+# function: Heading number processing method. Leave it up to the descendant
1160+# to do something useful with it.
1161+# args: - $aNumber
1162+# - $aToc: Reference to ToC to which anchorname belongs.
1163+
1164+sub number {
1165+ # Get arguments
1166+ my ($self, $aNumber, $aToc) = @_;
1167+} # number()
1168+
1169+
1170+#--- HTML::TocGenerator::parse() ----------------------------------------------
1171+# function: Parse scalar.
1172+# args: - $aString: string to parse
1173+
1174+sub parse {
1175+ # Get arguments
1176+ my ($self, $aString) = @_;
1177+ # Call ancestor
1178+ $self->SUPER::parse($aString);
1179+} # parse()
1180+
1181+
1182+#--- HTML::TocGenerator::parse_file() -----------------------------------------
1183+# function: Parse file.
1184+
1185+sub parse_file {
1186+ # Get arguments
1187+ my ($self, $aFile) = @_;
1188+ # Call ancestor
1189+ $self->SUPER::parse_file($aFile);
1190+} # parse_file()
1191+
1192+
1193+#--- HTML::TocGenerator::setOptions() -----------------------------------------
1194+# function: Set options.
1195+# args: - aOptions: Reference to hash containing options.
1196+
1197+sub setOptions {
1198+ # Get arguments
1199+ my ($self, $aOptions) = @_;
1200+ # Options are defined?
1201+ if (defined($aOptions)) {
1202+ # Yes, options are defined; add to options
1203+ %{$self->{options}} = (%{$self->{options}}, %$aOptions);
1204+ }
1205+} # setOptions()
1206+
1207+
1208+#--- HTML::TocGenerator::start() ----------------------------------------------
1209+# function: This function is called every time an opening tag is encountered.
1210+# args: - $aTag: tag name (in lower case).
1211+# - $aAttr: reference to hash containing all tag attributes (in lower
1212+# case).
1213+# - $aAttrSeq: reference to array containing all tag attributes (in
1214+# lower case) in the original order
1215+# - $aOrigText: the original HTML text
1216+
1217+sub start {
1218+ # Get arguments
1219+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1220+ $self->{isTocToken} = 0;
1221+ # Start tag is of type 'anchor name'?
1222+ if ($aTag eq "a" && defined($aAttr->{name})) {
1223+ # Yes, start tag is of type 'anchor name';
1224+ # Is another anchor already active?
1225+ if (defined($self->{_activeAnchorName})) {
1226+ # Yes, another anchor is already active;
1227+ # Is the first anchor inserted by 'TocGenerator'?
1228+ if ($self->{_doOutputAnchorNameEnd}) {
1229+ # Yes, the first anchor is inserted by 'TocGenerator';
1230+ # Show warning
1231+ $self->_showWarning(
1232+ WARNING_NESTED_ANCHOR_PS_WITHIN_PS,
1233+ [$aOrigText, $self->{_activeAnchorName}]
1234+ );
1235+ }
1236+ }
1237+ # Set active anchor name
1238+ $self->_setActiveAnchorName($aAttr->{name});
1239+ }
1240+ # Must a ToC be generated?
1241+ if ($self->{_doGenerateToc}) {
1242+ # Yes, a ToC must be generated
1243+ # Process start tag as ToC token
1244+ $self->{isTocToken} = $self->_processTokenAsTocStartingToken(
1245+ TT_TOKENTYPE_START, $aTag, $aAttr, \$aOrigText
1246+ );
1247+ # Process end tag as ToC-ending-token
1248+ $self->_processTokenAsTocEndingToken(
1249+ TT_TOKENTYPE_START, $aTag
1250+ );
1251+ }
1252+} # start()
1253+
1254+
1255+#--- HTML::TocGenerator::text() -----------------------------------------------
1256+# function: This function is called every time plain text is encountered.
1257+# args: - @_: array containing data.
1258+
1259+sub text {
1260+ # Get arguments
1261+ my ($self, $aText) = @_;
1262+ # Local variables
1263+ my ($text, $toc, $i, $token, $tokens);
1264+ # Must a ToC be generated?
1265+ if ($self->{_doGenerateToc}) {
1266+ # Yes, a ToC must be generated
1267+ # Are there dirty start tags?
1268+
1269+ # Loop through token types
1270+ foreach $tokens (@{$self->{_tokensTocEnd}}) {
1271+ # Loop though tokens
1272+ foreach $token (@$tokens) {
1273+ # Add text to toc
1274+
1275+ # Alias
1276+ $toc = $token->[TT_TOC];
1277+ # Remove possible newlines from text
1278+ ($text = $aText) =~ s/\s*\n\s*/ /g;
1279+ # Add text to toc
1280+ $self->_processTocText($text, $toc);
1281+ }
1282+ }
1283+ }
1284+} # text()
1285+
1286+
1287+
1288+
1289+#=== HTML::_TokenTocParser ====================================================
1290+# function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1291+# inserted into the ToC.
1292+# note: Used internally.
1293+
1294+package HTML::_TokenTocParser;
1295+
1296+
1297+BEGIN {
1298+ use vars qw(@ISA);
1299+
1300+ @ISA = qw(HTML::Parser);
1301+}
1302+
1303+
1304+END {}
1305+
1306+
1307+#--- HTML::_TokenTocParser::new() ---------------------------------------------
1308+# function: Constructor
1309+
1310+sub new {
1311+ # Get arguments
1312+ my ($aType) = @_;
1313+ # Create instance
1314+ my $self = $aType->SUPER::new;
1315+
1316+ # Return instance
1317+ return $self;
1318+} # new()
1319+
1320+
1321+#--- HTML::_TokenTocParser::_parseAttributes() --------------------------------
1322+# function: Parse attributes.
1323+# args: - $aAttr: Reference to hash containing all tag attributes (in lower
1324+# case).
1325+# - $aIncludeAttributes: Reference to hash to which 'include
1326+# attributes' must be added.
1327+# - $aExcludeAttributes: Reference to hash to which 'exclude
1328+# attributes' must be added.
1329+# - $aTocAttributes: Reference to hash to which 'ToC attributes'
1330+# must be added.
1331+
1332+sub _parseAttributes {
1333+ # Get arguments
1334+ my (
1335+ $self, $aAttr, $aIncludeAttributes, $aExcludeAttributes,
1336+ $aTocAttributes
1337+ ) = @_;
1338+ # Local variables
1339+ my ($key, $value);
1340+ my ($attributeToExcludeToken, $attributeToTocToken);
1341+ # Get token which marks attributes which must be excluded
1342+ $attributeToExcludeToken = $self->{_toc}{options}{'attributeToExcludeToken'};
1343+ $attributeToTocToken = $self->{_toc}{options}{'attributeToTocToken'};
1344+ # Loop through attributes
1345+ while (($key, $value) = each %$aAttr) {
1346+ # Attribute value equals 'ToC token'?
1347+ if ($value =~ m/$attributeToTocToken/) {
1348+ # Yes, attribute value equals 'ToC token';
1349+ # Add attribute to 'ToC attributes'
1350+ push @$aTocAttributes, $key;
1351+ }
1352+ else {
1353+ # No, attribute isn't 'ToC' token;
1354+ # Attribute value starts with 'exclude token'?
1355+ if ($value =~ m/^$attributeToExcludeToken(.*)/) {
1356+ # Yes, attribute value starts with 'exclude token';
1357+ # Add attribute to 'exclude attributes'
1358+ $$aExcludeAttributes{$key} = "$1";
1359+ }
1360+ else {
1361+ # No, attribute key doesn't start with '-';
1362+ # Add attribute to 'include attributes'
1363+ $$aIncludeAttributes{$key} = $value;
1364+ }
1365+ }
1366+ }
1367+} # _parseAttributes()
1368+
1369+
1370+
1371+
1372+#=== HTML::_TokenTocBeginParser ===============================================
1373+# function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1374+# inserted into the ToC.
1375+# note: Used internally.
1376+
1377+package HTML::_TokenTocBeginParser;
1378+
1379+
1380+BEGIN {
1381+ use vars qw(@ISA);
1382+
1383+ @ISA = qw(HTML::_TokenTocParser);
1384+}
1385+
1386+END {}
1387+
1388+
1389+#--- HTML::_TokenTocBeginParser::new() ----------------------------------------
1390+# function: Constructor
1391+
1392+sub new {
1393+ # Get arguments
1394+ my ($aType, $aTokenArray) = @_;
1395+ # Create instance
1396+ my $self = $aType->SUPER::new;
1397+ # Reference token array
1398+ $self->{tokens} = $aTokenArray;
1399+ # Reference to last added token
1400+ $self->{_lastAddedToken} = undef;
1401+ $self->{_lastAddedTokenType} = undef;
1402+ # Return instance
1403+ return $self;
1404+} # new()
1405+
1406+
1407+#--- HTML::_TokenTocBeginParser::_processAttributes() -------------------------
1408+# function: Process attributes.
1409+# args: - $aAttributes: Attributes to parse.
1410+
1411+sub _processAttributes {
1412+ # Get arguments
1413+ my ($self, $aAttributes) = @_;
1414+ # Local variables
1415+ my (%includeAttributes, %excludeAttributes, @tocAttributes);
1416+
1417+ # Parse attributes
1418+ $self->_parseAttributes(
1419+ $aAttributes, \%includeAttributes, \%excludeAttributes, \@tocAttributes
1420+ );
1421+ # Include attributes are specified?
1422+ if (keys(%includeAttributes) > 0) {
1423+ # Yes, include attributes are specified;
1424+ # Store include attributes
1425+ @${$self->{_lastAddedToken}}[
1426+ HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_BEGIN
1427+ ] = \%includeAttributes;
1428+ }
1429+ # Exclude attributes are specified?
1430+ if (keys(%excludeAttributes) > 0) {
1431+ # Yes, exclude attributes are specified;
1432+ # Store exclude attributes
1433+ @${$self->{_lastAddedToken}}[
1434+ HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_BEGIN
1435+ ] = \%excludeAttributes;
1436+ }
1437+ # Toc attributes are specified?
1438+ if (@tocAttributes > 0) {
1439+ # Yes, toc attributes are specified;
1440+ # Store toc attributes
1441+ @${$self->{_lastAddedToken}}[
1442+ HTML::TocGenerator::TT_ATTRIBUTES_TOC
1443+ ] = \@tocAttributes;
1444+ }
1445+} # _processAttributes()
1446+
1447+
1448+#--- HTML::_TokenTocBeginParser::_processToken() ------------------------------
1449+# function: Process token.
1450+# args: - $aTokenType: Type of token to process.
1451+# - $aTag: Tag of token.
1452+
1453+sub _processToken {
1454+ # Get arguments
1455+ my ($self, $aTokenType, $aTag) = @_;
1456+ # Local variables
1457+ my ($tokenArray, $index);
1458+ # Push element on array of update tokens
1459+ $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1;
1460+ # Alias token array to add element to
1461+ $tokenArray = $self->{tokens}[$aTokenType];
1462+ # Indicate last updated token array element
1463+ $self->{_lastAddedTokenType} = $aTokenType;
1464+ $self->{_lastAddedToken} = \$$tokenArray[$index];
1465+ # Add fields
1466+ $$tokenArray[$index][HTML::TocGenerator::TT_TAG_BEGIN] = $aTag;
1467+ $$tokenArray[$index][HTML::TocGenerator::TT_GROUP] = $self->{_group};
1468+ $$tokenArray[$index][HTML::TocGenerator::TT_TOC] = $self->{_toc};
1469+} # _processToken()
1470+
1471+
1472+#--- HTML::_TokenTocBeginParser::comment() ------------------------------------
1473+# function: Process comment.
1474+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1475+
1476+sub comment {
1477+ # Get arguments
1478+ my ($self, $aComment) = @_;
1479+ # Process token
1480+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
1481+} # comment()
1482+
1483+
1484+#--- HTML::_TokenTocBeginParser::declaration() --------------------------------
1485+# function: This function is called every time a markup declaration is
1486+# encountered by HTML::Parser.
1487+# args: - $aDeclaration: Markup declaration.
1488+
1489+sub declaration {
1490+ # Get arguments
1491+ my ($self, $aDeclaration) = @_;
1492+ # Process token
1493+ $self->_processToken(
1494+ HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
1495+ );
1496+} # declaration()
1497+
1498+
1499+#--- HTML::_TokenTocBeginParser::end() ----------------------------------------
1500+# function: This function is called every time a closing tag is encountered
1501+# by HTML::Parser.
1502+# args: - $aTag: tag name (in lower case).
1503+
1504+sub end {
1505+ # Get arguments
1506+ my ($self, $aTag, $aOrigText) = @_;
1507+ # Process token
1508+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
1509+} # end()
1510+
1511+
1512+#--- HTML::_TokenTocBeginParser::parse() --------------------------------------
1513+# function: Parse begin token.
1514+# args: - $aToken: 'toc token' to parse
1515+
1516+sub parse {
1517+ # Get arguments
1518+ my ($self, $aString) = @_;
1519+ # Call ancestor
1520+ $self->SUPER::parse($aString);
1521+} # parse()
1522+
1523+
1524+#--- HTML::_TokenTocBeginParser->setGroup() -----------------------------------
1525+# function: Set current 'tokenToToc' group.
1526+
1527+sub setGroup {
1528+ # Get arguments
1529+ my ($self, $aGroup) = @_;
1530+ # Set current 'tokenToToc' group
1531+ $self->{_group} = $aGroup;
1532+} # setGroup()
1533+
1534+
1535+#--- HTML::_TokenTocBeginParser->setToc() -------------------------------------
1536+# function: Set current ToC.
1537+
1538+sub setToc {
1539+ # Get arguments
1540+ my ($self, $aToc) = @_;
1541+ # Set current ToC
1542+ $self->{_toc} = $aToc;
1543+} # setToc()
1544+
1545+
1546+#--- HTML::_TokenTocBeginParser::start() --------------------------------------
1547+# function: This function is called every time an opening tag is encountered.
1548+# args: - $aTag: tag name (in lower case).
1549+# - $aAttr: reference to hash containing all tag attributes (in lower
1550+# case).
1551+# - $aAttrSeq: reference to array containing all attribute keys (in
1552+# lower case) in the original order
1553+# - $aOrigText: the original HTML text
1554+
1555+sub start {
1556+ # Get arguments
1557+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1558+ # Process token
1559+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
1560+ # Process attributes
1561+ $self->_processAttributes($aAttr);
1562+} # start()
1563+
1564+
1565+#--- HTML::_TokenTocBeginParser::text() ---------------------------------------
1566+# function: This function is called every time plain text is encountered.
1567+# args: - @_: array containing data.
1568+
1569+sub text {
1570+ # Get arguments
1571+ my ($self, $aText) = @_;
1572+ # Was token already created and is last added token of type 'text'?
1573+ if (
1574+ defined($self->{_lastAddedToken}) &&
1575+ $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT
1576+ ) {
1577+ # Yes, token is already created;
1578+ # Add tag to existing token
1579+ @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText;
1580+ }
1581+ else {
1582+ # No, token isn't created;
1583+ # Process token
1584+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
1585+ }
1586+} # text()
1587+
1588+
1589+
1590+
1591+#=== HTML::_TokenTocEndParser =================================================
1592+# function: Parse 'toc tokens'. 'Toc tokens' mark HTML code which is to be
1593+# inserted into the ToC.
1594+# note: Used internally.
1595+
1596+package HTML::_TokenTocEndParser;
1597+
1598+
1599+BEGIN {
1600+ use vars qw(@ISA);
1601+
1602+ @ISA = qw(HTML::_TokenTocParser);
1603+}
1604+
1605+
1606+END {}
1607+
1608+
1609+#--- HTML::_TokenTocEndParser::new() ------------------------------------------
1610+# function: Constructor
1611+# args: - $aType: Class type.
1612+
1613+sub new {
1614+ # Get arguments
1615+ my ($aType) = @_;
1616+ # Create instance
1617+ my $self = $aType->SUPER::new;
1618+ # Reference to last added token
1619+ $self->{_lastAddedToken} = undef;
1620+ # Return instance
1621+ return $self;
1622+} # new()
1623+
1624+
1625+#--- HTML::_TokenTocEndParser::_processAttributes() ---------------------------
1626+# function: Process attributes.
1627+# args: - $aAttributes: Attributes to parse.
1628+
1629+sub _processAttributes {
1630+ # Get arguments
1631+ my ($self, $aAttributes) = @_;
1632+ # Local variables
1633+ my (%includeAttributes, %excludeAttributes);
1634+
1635+ # Parse attributes
1636+ $self->_parseAttributes(
1637+ $aAttributes, \%includeAttributes, \%excludeAttributes
1638+ );
1639+ # Include attributes are specified?
1640+ if (keys(%includeAttributes) > 0) {
1641+ # Yes, include attributes are specified;
1642+ # Store include attributes
1643+ @${$self->{_Token}}[
1644+ HTML::TocGenerator::TT_INCLUDE_ATTRIBUTES_END
1645+ ] = \%includeAttributes;
1646+ }
1647+ # Exclude attributes are specified?
1648+ if (keys(%excludeAttributes) > 0) {
1649+ # Yes, exclude attributes are specified;
1650+ # Store exclude attributes
1651+ @${$self->{_Token}}[
1652+ HTML::TocGenerator::TT_EXCLUDE_ATTRIBUTES_END
1653+ ] = \%excludeAttributes;
1654+ }
1655+} # _processAttributes()
1656+
1657+
1658+#--- HTML::_TokenTocEndParser::_processToken() --------------------------------
1659+# function: Process token.
1660+# args: - $aTokenType: Type of token to process.
1661+# - $aTag: Tag of token.
1662+
1663+sub _processToken {
1664+ # Get arguments
1665+ my ($self, $aTokenType, $aTag) = @_;
1666+ # Update token
1667+ @${$self->{_token}}[HTML::TocGenerator::TT_TAG_TYPE_END] = $aTokenType;
1668+ @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] = $aTag;
1669+ # Indicate token type which has been processed
1670+ $self->{_lastAddedTokenType} = $aTokenType;
1671+} # _processToken()
1672+
1673+
1674+#--- HTML::_TokenTocEndParser::comment() --------------------------------------
1675+# function: Process comment.
1676+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
1677+
1678+sub comment {
1679+ # Get arguments
1680+ my ($self, $aComment) = @_;
1681+ # Process token
1682+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
1683+} # comment()
1684+
1685+
1686+#--- HTML::_TokenTocDeclarationParser::declaration() --------------------------
1687+# function: This function is called every time a markup declaration is
1688+# encountered by HTML::Parser.
1689+# args: - $aDeclaration: Markup declaration.
1690+
1691+sub declaration {
1692+ # Get arguments
1693+ my ($self, $aDeclaration) = @_;
1694+ # Process token
1695+ $self->_processToken(
1696+ HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
1697+ );
1698+} # declaration()
1699+
1700+
1701+#--- HTML::_TokenTocEndParser::end() ------------------------------------------
1702+# function: This function is called every time a closing tag is encountered
1703+# by HTML::Parser.
1704+# args: - $aTag: tag name (in lower case).
1705+
1706+sub end {
1707+ # Get arguments
1708+ my ($self, $aTag, $aOrigText) = @_;
1709+ # Process token
1710+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
1711+} # end()
1712+
1713+
1714+#--- HTML::_TokenTocEndParser::parse() ----------------------------------------
1715+# function: Parse token.
1716+# args: - $aString: 'toc token' to parse
1717+# - $aToken: Reference to token
1718+# - $aTokenTypeBegin: Type of begin token
1719+
1720+sub parse {
1721+ # Get arguments
1722+ my ($self, $aString, $aToken, $aTokenTypeBegin) = @_;
1723+ # Token argument specified?
1724+ if (defined($aToken)) {
1725+ # Yes, token argument is specified;
1726+ # Store token reference
1727+ $self->{_token} = $aToken;
1728+ }
1729+ # End tag defined?
1730+ if (! defined($aString)) {
1731+ # No, end tag isn't defined;
1732+ # Last added tokentype was of type 'start'?
1733+ if (
1734+ (defined($aTokenTypeBegin)) &&
1735+ ($aTokenTypeBegin == HTML::TocGenerator::TT_TOKENTYPE_START)
1736+ ) {
1737+ # Yes, last added tokentype was of type 'start';
1738+ # Assume end tag
1739+ $self->_processToken(
1740+ HTML::TocGenerator::TT_TAG_END,
1741+ @${$self->{_token}}[HTML::TocGenerator::TT_TAG_BEGIN]
1742+ );
1743+ }
1744+ }
1745+ else {
1746+ # Call ancestor
1747+ $self->SUPER::parse($aString);
1748+ }
1749+} # parse()
1750+
1751+
1752+#--- HTML::_TokenTocEndParser::start() ----------------------------------------
1753+# function: This function is called every time an opening tag is encountered.
1754+# args: - $aTag: tag name (in lower case).
1755+# - $aAttr: reference to hash containing all tag attributes (in lower
1756+# case).
1757+# - $aAttrSeq: reference to array containing all attribute keys (in
1758+# lower case) in the original order
1759+# - $aOrigText: the original HTML text
1760+
1761+sub start {
1762+ # Get arguments
1763+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1764+ # Process token
1765+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
1766+ # Process attributes
1767+ $self->_processAttributes($aAttr);
1768+} # start()
1769+
1770+
1771+#--- HTML::_TokenTocEndParser::text() -----------------------------------------
1772+# function: This function is called every time plain text is encountered.
1773+# args: - @_: array containing data.
1774+
1775+sub text {
1776+ # Get arguments
1777+ my ($self, $aText) = @_;
1778+
1779+ # Is token already created?
1780+ if (defined($self->{_lastAddedTokenType})) {
1781+ # Yes, token is already created;
1782+ # Add tag to existing token
1783+ @${$self->{_token}}[HTML::TocGenerator::TT_TAG_END] .= $aText;
1784+ }
1785+ else {
1786+ # No, token isn't created;
1787+ # Process token
1788+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
1789+ }
1790+} # text()
1791+
1792+
1793+1;
examples/includes/HTML-Toc-0.91/TocInsertor.pm+1066−0
@@ -0,0 +1,1066 @@
1+#--- TocInsertor.pm -----------------------------------------------------------
2+# function: Insert Table of Contents HTML::Toc, generated by
3+# HTML::TocGenerator.
4+# note: - The term 'propagate' is used as a shortcut for the process of
5+# both generating and inserting a ToC at the same time.
6+# - 'TIP' is an abbreviation of 'Toc Insertion Point'.
7+
8+
9+package HTML::TocInsertor;
10+
11+
12+use strict;
13+use FileHandle;
14+use HTML::TocGenerator;
15+
16+
17+BEGIN {
18+ use vars qw(@ISA $VERSION);
19+
20+ $VERSION = '0.91';
21+
22+ @ISA = qw(HTML::TocGenerator);
23+}
24+
25+ # TocInsertionPoint (TIP) constants
26+
27+use constant TIP_PREPOSITION_REPLACE => 'replace';
28+use constant TIP_PREPOSITION_BEFORE => 'before';
29+use constant TIP_PREPOSITION_AFTER => 'after';
30+
31+use constant TIP_TOKEN_ID => 0;
32+use constant TIP_PREPOSITION => 1;
33+use constant TIP_INCLUDE_ATTRIBUTES => 2;
34+use constant TIP_EXCLUDE_ATTRIBUTES => 3;
35+use constant TIP_TOC => 4;
36+
37+use constant MODE_DO_NOTHING => 0; # 0b00
38+use constant MODE_DO_INSERT => 1; # 0b01
39+use constant MODE_DO_PROPAGATE => 3; # 0b11
40+
41+END {}
42+
43+
44+#--- HTML::TocInsertor::new() -------------------------------------------------
45+# function: Constructor.
46+
47+sub new {
48+ # Get arguments
49+ my ($aType) = @_;
50+ my $self = $aType->SUPER::new;
51+ # TRUE if insertion point token must be output, FALSE if not
52+ $self->{_doOutputInsertionPointToken} = 1;
53+ # Reset batch variables
54+ $self->_resetBatchVariables;
55+ # Bias to not insert ToC
56+ $self->{hti__Mode} = MODE_DO_NOTHING;
57+
58+ # TODO: Initialize output
59+
60+ return $self;
61+} # new()
62+
63+
64+#--- HTML::TocInsertor::_deinitializeOutput() ---------------------------------
65+# function: Deinitialize output.
66+
67+sub _deinitializeOutput {
68+ # Get arguments
69+ my ($self) = @_;
70+ # Filehandle is defined?
71+ if (defined($self->{_outputFileHandle})) {
72+ # Yes, filehandle is defined;
73+ # Restore selected filehandle
74+ select($self->{_oldFileHandle});
75+ # Undefine filehandle, closing it automatically
76+ undef $self->{_outputFileHandle};
77+ }
78+} # _deinitializeOutput()
79+
80+
81+#--- HTML::TocInsertor::_initializeOutput() -----------------------------------
82+# function: Initialize output.
83+
84+sub _initializeOutput {
85+ # Get arguments
86+ my ($self) = @_;
87+ # Bias to write to outputfile
88+ my $doOutputToFile = 1;
89+
90+ # Is output specified?
91+ if (defined($self->{options}{'output'})) {
92+ # Yes, output is specified;
93+ # Indicate to not output to outputfile
94+ $doOutputToFile = 0;
95+ # Alias output reference
96+ $self->{_output} = $self->{options}{'output'};
97+ # Clear output
98+ ${$self->{_output}} = "";
99+ }
100+
101+ # Is output file specified?
102+ if (defined($self->{options}{'outputFile'})) {
103+ # Yes, output file is specified;
104+ # Indicate to output to outputfile
105+ $doOutputToFile = 1;
106+ # Open file
107+ $self->{_outputFileHandle} =
108+ new FileHandle ">" . $self->{options}{'outputFile'};
109+
110+ # Backup currently selected filehandle
111+ $self->{_oldFileHandle} = select;
112+ # Set new default filehandle
113+ select($self->{_outputFileHandle});
114+ }
115+
116+ # Alias output-to-file indicator
117+ $self->{_doOutputToFile} = $doOutputToFile;
118+} # _initializeOutput()
119+
120+
121+#--- HTML::TocInsertor::_deinitializeInsertorBatch() --------------------------
122+# function: Deinitialize insertor batch.
123+
124+sub _deinitializeInsertorBatch {
125+ # Get arguments
126+ my ($self) = @_;
127+ # Indicate ToC insertion has finished
128+ $self->{_isTocInsertionPointPassed} = 0;
129+ # Write buffered output
130+ $self->_writeBufferedOutput();
131+ # Propagate?
132+ if ($self->{hti__Mode} == MODE_DO_PROPAGATE) {
133+ # Yes, propagate;
134+ # Deinitialize generator batch
135+ $self->_deinitializeGeneratorBatch();
136+ }
137+ else {
138+ # No, insert only;
139+ # Do general batch deinitialization
140+ $self->_deinitializeBatch();
141+ }
142+ # Deinitialize output
143+ $self->_deinitializeOutput();
144+ # Indicate end of batch
145+ $self->{hti__Mode} = MODE_DO_NOTHING;
146+ # Reset batch variables
147+ $self->_resetBatchVariables();
148+} # _deinitializeInsertorBatch()
149+
150+
151+#--- HTML::TocInsertor::_initializeInsertorBatch() ----------------------------
152+# function: Initialize insertor batch.
153+# args: - $aTocs: Reference to array of tocs.
154+# - $aOptions: optional options
155+
156+sub _initializeInsertorBatch {
157+ # Get arguments
158+ my ($self, $aTocs, $aOptions) = @_;
159+ # Add invocation options
160+ $self->setOptions($aOptions);
161+ # Option 'doGenerateToc' specified?
162+ if (!defined($self->{options}{'doGenerateToc'})) {
163+ # No, options 'doGenerateToc' not specified;
164+ # Default to 'doGenerateToc'
165+ $self->{options}{'doGenerateToc'} = 1;
166+ }
167+ # Propagate?
168+ if ($self->{options}{'doGenerateToc'}) {
169+ # Yes, propagate;
170+ # Indicate mode
171+ $self->{hti__Mode} = MODE_DO_PROPAGATE;
172+ # Initialize generator batch
173+ # NOTE: This method takes care of calling '_initializeBatch()'
174+ $self->_initializeGeneratorBatch($aTocs);
175+ }
176+ else {
177+ # No, insert;
178+ # Indicate mode
179+ $self->{hti__Mode} = MODE_DO_INSERT;
180+ # Do general batch initialization
181+ $self->_initializeBatch($aTocs);
182+ }
183+ # Initialize output
184+ $self->_initializeOutput();
185+ # Parse ToC insertion points
186+ $self->_parseTocInsertionPoints();
187+} # _initializeInsertorBatch()
188+
189+
190+#--- HTML::TocInsertor::_insert() ---------------------------------------------
191+# function: Insert ToC in string.
192+# args: - $aString: Reference to string to parse.
193+# note: Used internally.
194+
195+sub _insert {
196+ # Get arguments
197+ my ($self, $aString) = @_;
198+ # Propagate?
199+ if ($self->{options}{'doGenerateToc'}) {
200+ # Yes, propagate;
201+ # Generate & insert ToC
202+ $self->_generate($aString);
203+ }
204+ else {
205+ # No, just insert ToC
206+ # Insert by parsing file
207+ $self->parse($aString);
208+ # Flush remaining buffered text
209+ $self->eof();
210+ }
211+} # _insert()
212+
213+
214+#--- HTML::TocInsertor::_insertIntoFile() -------------------------------------
215+# function: Do insert generated ToCs in file.
216+# args: - $aToc: (reference to array of) ToC object(s) to insert.
217+# - $aFile: (reference to array of) file(s) to parse for insertion
218+# points.
219+# - $aOptions: optional insertor options
220+# note: Used internally.
221+
222+sub _insertIntoFile {
223+ # Get arguments
224+ my ($self, $aFile) = @_;
225+ # Local variables;
226+ my ($file, @files);
227+ # Dereference array reference or make array of file specification
228+ @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
229+ # Loop through files
230+ foreach $file (@files) {
231+ # Propagate?
232+ if ($self->{options}{'doGenerateToc'}) {
233+ # Yes, propagate;
234+ # Generate and insert ToC
235+ $self->_generateFromFile($file);
236+ }
237+ else {
238+ # No, just insert ToC
239+ # Insert by parsing file
240+ $self->parse_file($file);
241+ }
242+ }
243+} # _insertIntoFile()
244+
245+
246+#--- HTML::TocInsertor::_parseTocInsertionPoints() ----------------------------
247+# function: Parse ToC insertion point specifier.
248+
249+sub _parseTocInsertionPoints {
250+ # Get arguments
251+ my ($self) = @_;
252+ # Local variables
253+ my ($tipPreposition, $tipToken, $toc, $tokenTipParser);
254+ # Create parser for TIP tokens
255+ $tokenTipParser = HTML::_TokenTipParser->new(
256+ $self->{_tokensTip}
257+ );
258+ # Loop through ToCs
259+ foreach $toc (@{$self->{_tocs}}) {
260+ # Split TIP in preposition and token
261+ ($tipPreposition, $tipToken) = split(
262+ '\s+', $toc->{options}{'insertionPoint'}, 2
263+ );
264+ # Known preposition?
265+ if (
266+ ($tipPreposition ne TIP_PREPOSITION_REPLACE) &&
267+ ($tipPreposition ne TIP_PREPOSITION_BEFORE) &&
268+ ($tipPreposition ne TIP_PREPOSITION_AFTER)
269+ ) {
270+ # No, unknown preposition;
271+ # Use default preposition
272+ $tipPreposition = TIP_PREPOSITION_AFTER;
273+ # Use entire 'insertionPoint' as token
274+ $tipToken = $toc->{options}{'insertionPoint'};
275+ }
276+ # Indicate current ToC to parser
277+ $tokenTipParser->setToc($toc);
278+ # Indicate current preposition to parser
279+ $tokenTipParser->setPreposition($tipPreposition);
280+ # Parse ToC Insertion Point
281+ $tokenTipParser->parse($tipToken);
282+ # Flush remaining buffered text
283+ $tokenTipParser->eof();
284+ }
285+} # _parseTocInsertionPoints()
286+
287+
288+#--- HTML::TocInsertor::_processTokenAsInsertionPoint() -----------------------
289+# function: Check for token being a ToC insertion point (Tip) token and
290+# process it accordingly.
291+# args: - $aTokenType: type of token: start, end, comment or text.
292+# - $aTokenId: token id of currently parsed token
293+# - $aTokenAttributes: attributes of currently parsed token
294+# - $aOrigText: complete token
295+# returns: 1 if successful -- token is processed as insertion point, 0
296+# if not.
297+
298+sub _processTokenAsInsertionPoint {
299+ # Get arguments
300+ my ($self, $aTokenType, $aTokenId, $aTokenAttributes, $aOrigText) = @_;
301+ # Local variables
302+ my ($i, $result, $tipToken, $tipTokenId, $tipTokens);
303+ # Bias to token not functioning as a ToC insertion point (Tip) token
304+ $result = 0;
305+ # Alias ToC insertion point (Tip) array of right type
306+ $tipTokens = $self->{_tokensTip}[$aTokenType];
307+ # Loop through tipTokens
308+ $i = 0;
309+ while ($i < scalar @{$tipTokens}) {
310+ # Aliases
311+ $tipToken = $tipTokens->[$i];
312+ $tipTokenId = $tipToken->[TIP_TOKEN_ID];
313+ # Id & attributes match?
314+ if (
315+ ($aTokenId =~ m/$tipTokenId/) && (
316+ HTML::TocGenerator::_doesHashContainHash(
317+ $aTokenAttributes, $tipToken->[TIP_INCLUDE_ATTRIBUTES], 0
318+ ) &&
319+ HTML::TocGenerator::_doesHashContainHash(
320+ $aTokenAttributes, $tipToken->[TIP_EXCLUDE_ATTRIBUTES], 1
321+ )
322+ )
323+ ) {
324+ # Yes, id and attributes match;
325+ # Process ToC insertion point
326+ $self->_processTocInsertionPoint($tipToken);
327+ # Indicate token functions as ToC insertion point
328+ $result = 1;
329+ # Remove Tip token, automatically advancing to next token
330+ splice(@$tipTokens, $i, 1);
331+ }
332+ else {
333+ # No, tag doesn't match ToC insertion point
334+ # Advance to next start token
335+ $i++;
336+ }
337+ }
338+ # Token functions as ToC insertion point?
339+ if ($result) {
340+ # Yes, token functions as ToC insertion point;
341+ # Process insertion point(s)
342+ $self->_processTocInsertionPoints($aOrigText);
343+ }
344+ # Return value
345+ return $result;
346+} # _processTokenAsInsertionPoint()
347+
348+
349+#--- HTML::TocInsertor::toc() -------------------------------------------------
350+# function: Toc processing method. Add toc reference to scenario.
351+# args: - $aScenario: Scenario to add ToC reference to.
352+# - $aToc: Reference to ToC to insert.
353+# note: The ToC hasn't been build yet; only a reference to the ToC to be
354+# build is inserted.
355+
356+sub toc {
357+ # Get arguments
358+ my ($self, $aScenario, $aToc) = @_;
359+ # Add toc to scenario
360+ push(@$aScenario, $aToc);
361+} # toc()
362+
363+
364+#--- HTML::TocInsertor::_processTocInsertionPoint() ----------------------------
365+# function: Process ToC insertion point.
366+# args: - $aTipToken: Reference to token array item which matches the ToC
367+# insertion point.
368+
369+sub _processTocInsertionPoint {
370+ # Get arguments
371+ my ($self, $aTipToken) = @_;
372+ # Local variables
373+ my ($tipToc, $tipPreposition);
374+
375+ # Aliases
376+ $tipToc = $aTipToken->[TIP_TOC];
377+ $tipPreposition = $aTipToken->[TIP_PREPOSITION];
378+
379+ SWITCH: {
380+ # Replace token with ToC?
381+ if ($tipPreposition eq TIP_PREPOSITION_REPLACE) {
382+ # Yes, replace token;
383+ # Indicate ToC insertion point has been passed
384+ $self->{_isTocInsertionPointPassed} = 1;
385+ # Add ToC reference to scenario reference by calling 'toc' method
386+ $self->toc($self->{_scenarioAfterToken}, $tipToc);
387+ #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
388+ # Indicate token itself must not be output
389+ $self->{_doOutputInsertionPointToken} = 0;
390+ last SWITCH;
391+ }
392+ # Output ToC before token?
393+ if ($tipPreposition eq TIP_PREPOSITION_BEFORE) {
394+ # Yes, output ToC before token;
395+ # Indicate ToC insertion point has been passed
396+ $self->{_isTocInsertionPointPassed} = 1;
397+ # Add ToC reference to scenario reference by calling 'toc' method
398+ $self->toc($self->{_scenarioBeforeToken}, $tipToc);
399+ #push(@{$self->{_scenarioBeforeToken}}, $tipTokenToc);
400+ last SWITCH;
401+ }
402+ # Output ToC after token?
403+ if ($tipPreposition eq TIP_PREPOSITION_AFTER) {
404+ # Yes, output ToC after token;
405+ # Indicate ToC insertion point has been passed
406+ $self->{_isTocInsertionPointPassed} = 1;
407+ # Add ToC reference to scenario reference by calling 'toc' method
408+ $self->toc($self->{_scenarioAfterToken}, $tipToc);
409+ #push(@{$self->{_scenarioAfterToken}}, $tipTokenToc);
410+ last SWITCH;
411+ }
412+ }
413+} # _processTocInsertionPoint()
414+
415+
416+#--- HTML::TocInsertor::_processTocInsertionPoints() --------------------------
417+# function: Process ToC insertion points
418+# args: - $aTokenText: Text of token which acts as insertion point for one
419+# or multiple ToCs.
420+
421+sub _processTocInsertionPoints {
422+ # Get arguments
423+ my ($self, $aTokenText) = @_;
424+ # Local variables
425+ my ($outputPrefix, $outputSuffix);
426+ # Extend scenario
427+ push(@{$self->{_scenario}}, @{$self->{_scenarioBeforeToken}});
428+
429+ if ($outputPrefix = $self->{_outputPrefix}) {
430+ push(@{$self->{_scenario}}, \$outputPrefix);
431+ $self->{_outputPrefix} = "";
432+ }
433+
434+ # Must insertion point token be output?
435+ if ($self->{_doOutputInsertionPointToken}) {
436+ # Yes, output insertion point token;
437+ push(@{$self->{_scenario}}, \$aTokenText);
438+ }
439+
440+ if ($outputSuffix = $self->{_outputSuffix}) {
441+ push(@{$self->{_scenario}}, \$outputSuffix);
442+ $self->{_outputSuffix} = "";
443+ }
444+
445+ push(@{$self->{_scenario}}, @{$self->{_scenarioAfterToken}});
446+ # Add new act to scenario for output to come
447+ my $output = "";
448+ push(@{$self->{_scenario}}, \$output);
449+ # Write output, processing possible '_outputSuffix'
450+ #$self->_writeOrBufferOutput("");
451+ # Reset helper scenario's
452+ $self->{_scenarioBeforeToken} = [];
453+ $self->{_scenarioAfterToken} = [];
454+ # Reset bias value to output insertion point token
455+ $self->{_doOutputInsertionPointToken} = 1;
456+
457+} # _processTocInsertionPoints()
458+
459+
460+#--- HTML::Toc::_resetBatchVariables() ----------------------------------------
461+# function: Reset batch variables.
462+
463+sub _resetBatchVariables {
464+ my ($self) = @_;
465+ # Call ancestor
466+ $self->SUPER::_resetBatchVariables();
467+ # Array containing references to scalars. This array depicts the order
468+ # in which output must be performed after the first ToC Insertion Point
469+ # has been passed.
470+ $self->{_scenario} = [];
471+ # Helper scenario
472+ $self->{_scenarioBeforeToken} = [];
473+ # Helper scenario
474+ $self->{_scenarioAfterToken} = [];
475+ # Arrays containing start, end, comment, text & declaration tokens which
476+ # must trigger the ToC insertion. Each array element may contain a
477+ # reference to an array containing the following elements:
478+ $self->{_tokensTip} = [
479+ [], # TT_TOKENTYPE_START
480+ [], # TT_TOKENTYPE_END
481+ [], # TT_TOKENTYPE_COMMENT
482+ [], # TT_TOKENTYPE_TEXT
483+ [] # TT_TOKENTYPE_DECLARATION
484+ ];
485+ # 1 if ToC insertion point has been passed, 0 if not
486+ $self->{_isTocInsertionPointPassed} = 0;
487+ # Tokens after ToC
488+ $self->{outputBuffer} = "";
489+ # Trailing text after parsed token
490+ $self->{_outputSuffix} = "";
491+ # Preceding text before parsed token
492+ $self->{_outputPrefix} = "";
493+} # _resetBatchVariables()
494+
495+
496+#--- HTML::TocInsertor::_writeBufferedOutput() --------------------------------
497+# function: Write buffered output to output device(s).
498+
499+sub _writeBufferedOutput {
500+ # Get arguments
501+ my ($self) = @_;
502+ # Local variables
503+ my ($scene);
504+ # Must ToC be parsed?
505+ if ($self->{options}{'parseToc'}) {
506+ # Yes, ToC must be parsed;
507+ # Parse ToC
508+ #$self->parse($self->{toc});
509+ # Output tokens after ToC
510+ #$self->_writeOrBufferOutput($self->{outputBuffer});
511+ }
512+ else {
513+ # No, ToC needn't be parsed;
514+ # Output scenario
515+ foreach $scene (@{$self->{_scenario}}) {
516+ # Is scene a reference to a scalar?
517+ if (ref($scene) eq "SCALAR") {
518+ # Yes, scene is a reference to a scalar;
519+ # Output scene
520+ $self->_writeOutput($$scene);
521+ }
522+ else {
523+ # No, scene must be reference to HTML::Toc;
524+ # Output toc
525+ $self->_writeOutput($scene->format());
526+ }
527+ }
528+ }
529+} # _writeBufferedOutput()
530+
531+
532+#--- HTML::TocInsertor::_writeOrBufferOutput() --------------------------------
533+# function: Write processed HTML to output device(s).
534+# args: - aOutput: scalar to write
535+# note: If '_isTocInsertionPointPassed' text is buffered before being
536+# output because the ToC has to be generated before it can be output.
537+# Only after the entire data has been parsed, the ToC and the
538+# following text will be output.
539+
540+sub _writeOrBufferOutput {
541+ # Get arguments
542+ my ($self, $aOutput) = @_;
543+
544+ # Add possible output prefix and suffix
545+ $aOutput = $self->{_outputPrefix} . $aOutput . $self->{_outputSuffix};
546+ # Clear output prefix and suffix
547+ $self->{_outputPrefix} = "";
548+ $self->{_outputSuffix} = "";
549+
550+ # Has ToC insertion point been passed?
551+ if ($self->{_isTocInsertionPointPassed}) {
552+ # Yes, ToC insertion point has been passed;
553+ # Buffer output; add output to last '_scenario' item
554+ my $index = scalar(@{$self->{_scenario}}) - 1;
555+ ${$self->{_scenario}[$index]} .= $aOutput;
556+ }
557+ else {
558+ # No, ToC insertion point hasn't been passed;
559+ # Write output
560+ $self->_writeOutput($aOutput);
561+ }
562+} # _writeOrBufferOutput()
563+
564+
565+#--- HTML::TocInsertor::_writeOutput() ----------------------------------------
566+# function: Write processed HTML to output device(s).
567+# args: - aOutput: scalar to write
568+
569+sub _writeOutput {
570+ # Get arguments
571+ my ($self, $aOutput) = @_;
572+ # Write output to scalar;
573+ ${$self->{_output}} .= $aOutput if (defined($self->{_output}));
574+ # Write output to output file
575+ print $aOutput if ($self->{_doOutputToFile})
576+} # _writeOutput()
577+
578+
579+#--- HTML::TocGenerator::anchorId() -------------------------------------------
580+# function: Anchor id processing method.
581+# args: - $aAnchorId
582+
583+sub anchorId {
584+ # Get arguments
585+ my ($self, $aAnchorId) = @_;
586+ # Indicate id must be added to start tag
587+ $self->{_doAddAnchorIdToStartTag} = 1;
588+ $self->{_anchorId} = $aAnchorId;
589+} # anchorId()
590+
591+
592+#--- HTML::TocInsertor::anchorNameBegin() -------------------------------------
593+# function: Process anchor name begin, generated by HTML::TocGenerator.
594+# args: - $aAnchorNameBegin: Anchor name begin tag to output.
595+# - $aToc: Reference to ToC to which anchorname belongs.
596+
597+sub anchorNameBegin {
598+ # Get arguments
599+ my ($self, $aAnchorNameBegin, $aToc) = @_;
600+ # Is another anchorName active?
601+ if (defined($self->{_activeAnchorName})) {
602+ # Yes, another anchorName is active;
603+ # Show warning
604+ print "Warn\n";
605+ $self->_showWarning(
606+ HTML::TocGenerator::WARNING_NESTED_ANCHOR_PS_WITHIN_PS,
607+ [$aAnchorNameBegin, $self->{_activeAnchorName}]
608+ );
609+ }
610+ # Store anchor name as output prefix
611+ $self->{_outputPrefix} = $aAnchorNameBegin;
612+ # Indicate active anchor name
613+ $self->{_activeAnchorName} = $aAnchorNameBegin;
614+ # Indicate anchor name end must be output
615+ $self->{_doOutputAnchorNameEnd} = 1;
616+} # anchorNameBegin()
617+
618+
619+#--- HTML::TocInsertor::anchorNameEnd() ---------------------------------------
620+# function: Process anchor name end, generated by HTML::TocGenerator.
621+# args: - $aAnchorNameEnd: Anchor name end tag to output.
622+# - $aToc: Reference to ToC to which anchorname belongs.
623+
624+sub anchorNameEnd {
625+ # Get arguments
626+ my ($self, $aAnchorNameEnd) = @_;
627+ # Store anchor name as output prefix
628+ $self->{_outputSuffix} .= $aAnchorNameEnd;
629+ # Indicate deactive anchor name
630+ $self->{_activeAnchorName} = undef;
631+} # anchorNameEnd()
632+
633+
634+#--- HTML::TocInsertor::comment() ---------------------------------------------
635+# function: Process comment.
636+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
637+
638+sub comment {
639+ # Get arguments
640+ my ($self, $aComment) = @_;
641+ # Local variables
642+ my ($tocInsertionPointToken, $doOutput, $origText);
643+ # Allow ancestor to process the comment tag
644+ $self->SUPER::comment($aComment);
645+ # Assemble original comment
646+ $origText = "<!--$aComment-->";
647+ # Must ToCs be inserted?
648+ if ($self->{hti__Mode} & MODE_DO_INSERT) {
649+ # Yes, ToCs must be inserted;
650+ # Processing comment as ToC insertion point is successful?
651+ if (! $self->_processTokenAsInsertionPoint(
652+ HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment, undef, $origText
653+ )) {
654+ # No, comment isn't a ToC insertion point;
655+ # Output comment normally
656+ $self->_writeOrBufferOutput($origText);
657+ }
658+ }
659+} # comment()
660+
661+
662+#--- HTML::TocInsertor::declaration() -----------------------------------------
663+# function: This function is called every time a declaration is encountered
664+# by HTML::Parser.
665+
666+sub declaration {
667+ # Get arguments
668+ my ($self, $aDeclaration) = @_;
669+ # Allow ancestor to process the declaration tag
670+ $self->SUPER::declaration($aDeclaration);
671+ # Must ToCs be inserted?
672+ if ($self->{hti__Mode} & MODE_DO_INSERT) {
673+ # Yes, ToCs must be inserted;
674+ # Processing declaration as ToC insertion point is successful?
675+ if (! $self->_processTokenAsInsertionPoint(
676+ HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration, undef,
677+ "<!$aDeclaration>"
678+ )) {
679+ # No, declaration isn't a ToC insertion point;
680+ # Output declaration normally
681+ $self->_writeOrBufferOutput("<!$aDeclaration>");
682+ }
683+ }
684+} # declaration()
685+
686+
687+#--- HTML::TocInsertor::end() -------------------------------------------------
688+# function: This function is called every time a closing tag is encountered
689+# by HTML::Parser.
690+# args: - $aTag: tag name (in lower case).
691+
692+sub end {
693+ # Get arguments
694+ my ($self, $aTag, $aOrigText) = @_;
695+ # Allow ancestor to process the end tag
696+ $self->SUPER::end($aTag, $aOrigText);
697+ # Must ToCs be inserted?
698+ if ($self->{hti__Mode} & MODE_DO_INSERT) {
699+ # Yes, ToCs must be inserted;
700+ # Processing end tag as ToC insertion point is successful?
701+ if (! $self->_processTokenAsInsertionPoint(
702+ HTML::TocGenerator::TT_TOKENTYPE_END, $aTag, undef, $aOrigText
703+ )) {
704+ # No, end tag isn't a ToC insertion point;
705+ # Output end tag normally
706+ $self->_writeOrBufferOutput($aOrigText);
707+ }
708+ }
709+} # end()
710+
711+
712+#--- HTML::TocInsertor::insert() ----------------------------------------------
713+# function: Insert ToC in string.
714+# args: - $aToc: (reference to array of) ToC object to insert
715+# - $aString: string to insert ToC in
716+# - $aOptions: hash reference with optional insertor options
717+
718+sub insert {
719+ # Get arguments
720+ my ($self, $aToc, $aString, $aOptions) = @_;
721+ # Initialize TocInsertor batch
722+ $self->_initializeInsertorBatch($aToc, $aOptions);
723+ # Do insert Toc
724+ $self->_insert($aString);
725+ # Deinitialize TocInsertor batch
726+ $self->_deinitializeInsertorBatch();
727+} # insert()
728+
729+
730+#--- HTML::TocInsertor::insertIntoFile() --------------------------------------
731+# function: Insert ToCs in file.
732+# args: - $aToc: (reference to array of) ToC object(s) to insert.
733+# - $aFile: (reference to array of) file(s) to parse for insertion
734+# points.
735+# - $aOptions: optional insertor options
736+
737+sub insertIntoFile {
738+ # Get arguments
739+ my ($self, $aToc, $aFile, $aOptions) = @_;
740+ # Initialize TocInsertor batch
741+ $self->_initializeInsertorBatch($aToc, $aOptions);
742+ # Do insert ToCs into file
743+ $self->_insertIntoFile($aFile);
744+ # Deinitialize TocInsertor batch
745+ $self->_deinitializeInsertorBatch();
746+} # insertIntoFile()
747+
748+
749+#--- HTML::TocInsertor::number() ----------------------------------------------
750+# function: Process heading number generated by HTML::Toc.
751+# args: - $aNumber
752+
753+sub number {
754+ # Get arguments
755+ my ($self, $aNumber) = @_;
756+ # Store heading number as output suffix
757+ $self->{_outputSuffix} .= $aNumber;
758+} # number()
759+
760+
761+#--- HTML::TocInsertor::propagateFile() ---------------------------------------
762+# function: Propagate ToC; generate & insert ToC, using file as input.
763+# args: - $aToc: (reference to array of) ToC object to insert
764+# - $aFile: (reference to array of) file to parse for insertion
765+# points.
766+# - $aOptions: optional insertor options
767+
768+sub propagateFile {
769+ # Get arguments
770+ my ($self, $aToc, $aFile, $aOptions) = @_;
771+ # Local variables;
772+ my ($file, @files);
773+ # Initialize TocInsertor batch
774+ $self->_initializeInsertorBatch($aToc, $aOptions);
775+ # Dereference array reference or make array of file specification
776+ @files = (ref($aFile) =~ m/ARRAY/) ? @$aFile : ($aFile);
777+ # Loop through files
778+ foreach $file (@files) {
779+ # Generate and insert ToC
780+ $self->_generateFromFile($file);
781+ }
782+ # Deinitialize TocInsertor batch
783+ $self->_deinitializeInsertorBatch();
784+} # propagateFile()
785+
786+
787+#--- HTML::TocInsertor::start() -----------------------------------------------
788+# function: This function is called every time an opening tag is encountered.
789+# args: - $aTag: tag name (in lower case).
790+# - $aAttr: reference to hash containing all tag attributes (in lower
791+# case).
792+# - $aAttrSeq: reference to array containing all tag attributes (in
793+# lower case) in the original order
794+# - $aOrigText: the original HTML text
795+
796+sub start {
797+ # Get arguments
798+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
799+ # Local variables
800+ my ($doOutput, $i, $tocToken, $tag, $anchorId);
801+ # Let ancestor process the start tag
802+ $self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText);
803+ # Must ToC be inserted?
804+ if ($self->{hti__Mode} & MODE_DO_INSERT) {
805+ # Yes, ToC must be inserted;
806+ # Processing start tag as ToC insertion point is successful?
807+ if (! $self->_processTokenAsInsertionPoint(
808+ HTML::TocGenerator::TT_TOKENTYPE_START, $aTag, $aAttr, $aOrigText
809+ )) {
810+ # No, start tag isn't a ToC insertion point;
811+ # Add anchor id?
812+ if ($self->{_doAddAnchorIdToStartTag}) {
813+ # Yes, anchor id must be added;
814+ # Reset indicator;
815+ $self->{_doAddAnchorIdToStartTag} = 0;
816+ # Alias anchor id
817+ $anchorId = $self->{_anchorId};
818+ # Attribute 'id' already exists?
819+ if (defined($aAttr->{id})) {
820+ # Yes, attribute 'id' already exists;
821+ # Show warning
822+ print STDERR "WARNING: Overwriting existing id attribute '" .
823+ $aAttr->{id} . "' of tag $aOrigText\n";
824+
825+ # Add anchor id to start tag
826+ $aOrigText =~ s/(id)=\S*([\s>])/$1=$anchorId$2/i;
827+ }
828+ else {
829+ # No, attribute 'id' doesn't exist;
830+ # Add anchor id to start tag
831+ $aOrigText =~ s/>/ id=$anchorId>/;
832+ }
833+ }
834+ # Output start tag normally
835+ $self->_writeOrBufferOutput($aOrigText);
836+ }
837+ }
838+} # start()
839+
840+
841+#--- HTML::TocInsertor::text() ------------------------------------------------
842+# function: This function is called every time plain text is encountered.
843+# args: - @_: array containing data.
844+
845+sub text {
846+ # Get arguments
847+ my ($self, $aText) = @_;
848+ # Let ancestor process the text
849+ $self->SUPER::text($aText);
850+ # Must ToC be inserted?
851+ if ($self->{hti__Mode} & MODE_DO_INSERT) {
852+ # Yes, ToC must be inserted;
853+ # Processing text as ToC insertion point is successful?
854+ if (! $self->_processTokenAsInsertionPoint(
855+ HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText, undef, $aText
856+ )) {
857+ # No, text isn't a ToC insertion point;
858+ # Output text normally
859+ $self->_writeOrBufferOutput($aText);
860+ }
861+ }
862+} # text()
863+
864+
865+
866+
867+#=== HTML::_TokenTipParser ====================================================
868+# function: Parse 'TIP tokens'. 'TIP tokens' mark HTML code which is to be
869+# used as the ToC Insertion Point.
870+# note: Used internally.
871+
872+package HTML::_TokenTipParser;
873+
874+
875+BEGIN {
876+ use vars qw(@ISA);
877+
878+ @ISA = qw(HTML::_TokenTocParser);
879+}
880+
881+
882+END {}
883+
884+
885+#--- HTML::_TokenTipParser::new() ---------------------------------------------
886+# function: Constructor
887+
888+sub new {
889+ # Get arguments
890+ my ($aType, $aTokenArray) = @_;
891+ # Create instance
892+ my $self = $aType->SUPER::new;
893+ # Reference token array
894+ $self->{tokens} = $aTokenArray;
895+ # Reference to last added token
896+ $self->{_lastAddedToken} = undef;
897+ $self->{_lastAddedTokenType} = undef;
898+ # Return instance
899+ return $self;
900+} # new()
901+
902+
903+#--- HTML::_TokenTipParser::_processAttributes() ------------------------------
904+# function: Process attributes.
905+# args: - $aAttributes: Attributes to parse.
906+
907+sub _processAttributes {
908+ # Get arguments
909+ my ($self, $aAttributes) = @_;
910+ # Local variables
911+ my (%includeAttributes, %excludeAttributes);
912+
913+ # Parse attributes
914+ $self->_parseAttributes(
915+ $aAttributes, \%includeAttributes, \%excludeAttributes
916+ );
917+ # Include attributes are specified?
918+ if (keys(%includeAttributes) > 0) {
919+ # Yes, include attributes are specified;
920+ # Store include attributes
921+ @${$self->{_lastAddedToken}}[
922+ HTML::TocInsertor::TIP_INCLUDE_ATTRIBUTES
923+ ] = \%includeAttributes;
924+ }
925+ # Exclude attributes are specified?
926+ if (keys(%excludeAttributes) > 0) {
927+ # Yes, exclude attributes are specified;
928+ # Store exclude attributes
929+ @${$self->{_lastAddedToken}}[
930+ HTML::TocInsertor::TIP_EXCLUDE_ATTRIBUTES
931+ ] = \%excludeAttributes;
932+ }
933+} # _processAttributes()
934+
935+
936+#--- HTML::_TokenTipParser::_processToken() -----------------------------------
937+# function: Process token.
938+# args: - $aTokenType: Type of token to process.
939+# - $aTag: Tag of token.
940+
941+sub _processToken {
942+ # Get arguments
943+ my ($self, $aTokenType, $aTag) = @_;
944+ # Local variables
945+ my ($tokenArray, $index);
946+ # Push element on array of update tokens
947+ $index = push(@{$self->{tokens}[$aTokenType]}, []) - 1;
948+ # Alias token array to add element to
949+ $tokenArray = $self->{tokens}[$aTokenType];
950+ # Indicate last updated token array element
951+ $self->{_lastAddedTokenType} = $aTokenType;
952+ $self->{_lastAddedToken} = \$$tokenArray[$index];
953+ # Add fields
954+ $$tokenArray[$index][HTML::TocInsertor::TIP_TOC] = $self->{_toc};
955+ $$tokenArray[$index][HTML::TocInsertor::TIP_TOKEN_ID] = $aTag;
956+ $$tokenArray[$index][HTML::TocInsertor::TIP_PREPOSITION] =
957+ $self->{_preposition};
958+} # _processToken()
959+
960+
961+#--- HTML::_TokenTipParser::comment() -----------------------------------------
962+# function: Process comment.
963+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
964+
965+sub comment {
966+ # Get arguments
967+ my ($self, $aComment) = @_;
968+ # Process token
969+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_COMMENT, $aComment);
970+} # comment()
971+
972+
973+#--- HTML::_TokenTipParser::declaration() --------------------------------
974+# function: This function is called every time a markup declaration is
975+# encountered by HTML::Parser.
976+# args: - $aDeclaration: Markup declaration.
977+
978+sub declaration {
979+ # Get arguments
980+ my ($self, $aDeclaration) = @_;
981+ # Process token
982+ $self->_processToken(
983+ HTML::TocGenerator::TT_TOKENTYPE_DECLARATION, $aDeclaration
984+ );
985+} # declaration()
986+
987+
988+#--- HTML::_TokenTipParser::end() ----------------------------------------
989+# function: This function is called every time a closing tag is encountered
990+# by HTML::Parser.
991+# args: - $aTag: tag name (in lower case).
992+
993+sub end {
994+ # Get arguments
995+ my ($self, $aTag, $aOrigText) = @_;
996+ # Process token
997+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_END, $aTag);
998+} # end()
999+
1000+
1001+#--- HTML::_TokenTipParser->setPreposition() ----------------------------------
1002+# function: Set current preposition.
1003+
1004+sub setPreposition {
1005+ # Get arguments
1006+ my ($self, $aPreposition) = @_;
1007+ # Set current ToC
1008+ $self->{_preposition} = $aPreposition;
1009+} # setPreposition()
1010+
1011+
1012+#--- HTML::_TokenTipParser->setToc() ------------------------------------------
1013+# function: Set current ToC.
1014+
1015+sub setToc {
1016+ # Get arguments
1017+ my ($self, $aToc) = @_;
1018+ # Set current ToC
1019+ $self->{_toc} = $aToc;
1020+} # setToc()
1021+
1022+
1023+#--- HTML::_TokenTipParser::start() --------------------------------------
1024+# function: This function is called every time an opening tag is encountered.
1025+# args: - $aTag: tag name (in lower case).
1026+# - $aAttr: reference to hash containing all tag attributes (in lower
1027+# case).
1028+# - $aAttrSeq: reference to array containing all attribute keys (in
1029+# lower case) in the original order
1030+# - $aOrigText: the original HTML text
1031+
1032+sub start {
1033+ # Get arguments
1034+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
1035+ # Process token
1036+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_START, $aTag);
1037+ # Process attributes
1038+ $self->_processAttributes($aAttr);
1039+} # start()
1040+
1041+
1042+#--- HTML::_TokenTipParser::text() ---------------------------------------
1043+# function: This function is called every time plain text is encountered.
1044+# args: - @_: array containing data.
1045+
1046+sub text {
1047+ # Get arguments
1048+ my ($self, $aText) = @_;
1049+ # Was token already created and is last added token of type 'text'?
1050+ if (
1051+ defined($self->{_lastAddedToken}) &&
1052+ $self->{_lastAddedTokenType} == HTML::TocGenerator::TT_TOKENTYPE_TEXT
1053+ ) {
1054+ # Yes, token is already created;
1055+ # Add tag to existing token
1056+ @${$self->{_lastAddedToken}}[HTML::TocGenerator::TT_TAG_BEGIN] .= $aText;
1057+ }
1058+ else {
1059+ # No, token isn't created;
1060+ # Process token
1061+ $self->_processToken(HTML::TocGenerator::TT_TOKENTYPE_TEXT, $aText);
1062+ }
1063+} # text()
1064+
1065+
1066+1;
examples/includes/HTML-Toc-0.91/TocUpdator.pm+693−0
@@ -0,0 +1,693 @@
1+#==== HTML::TocUpdator ========================================================
2+# function: Update 'HTML::Toc' table of contents.
3+# note: - 'TUT' is an abbreviation of 'Toc Update Token'.
4+
5+
6+package HTML::TocUpdator;
7+
8+
9+use strict;
10+use HTML::TocInsertor;
11+
12+
13+BEGIN {
14+ use vars qw(@ISA $VERSION);
15+
16+ $VERSION = '0.91';
17+
18+ @ISA = qw(HTML::TocInsertor);
19+}
20+
21+
22+use constant TUT_TOKENTYPE_START => 0;
23+use constant TUT_TOKENTYPE_END => 1;
24+use constant TUT_TOKENTYPE_TEXT => 2;
25+use constant TUT_TOKENTYPE_COMMENT => 3;
26+
27+use constant MODE_DO_NOTHING => 0; # 0b00
28+use constant MODE_DO_INSERT => 1; # 0b01
29+use constant MODE_DO_UPDATE => 3; # 0b11
30+
31+
32+END {}
33+
34+
35+#--- HTML::TocUpdator::new() --------------------------------------------------
36+# function: Constructor.
37+
38+sub new {
39+ # Get arguments
40+ my ($aType) = @_;
41+ my $self = $aType->SUPER::new;
42+ # Bias to not update ToC
43+ $self->{htu__Mode} = MODE_DO_NOTHING;
44+ # Bias to not delete tokens
45+ $self->{_doDeleteTokens} = 0;
46+ # Reset batch variables
47+ #$self->_resetBatchVariables;
48+
49+ $self->{options} = {};
50+
51+ # TODO: Initialize output
52+
53+ return $self;
54+} # new()
55+
56+
57+#--- HTML::TocUpdator::_deinitializeUpdatorBatch() --------------------------
58+# function: Deinitialize updator batch.
59+# args: - $aTocs: Reference to array of tocs.
60+
61+sub _deinitializeUpdatorBatch {
62+ # Get arguments
63+ my ($self, $aTocs) = @_;
64+ # Indicate end of ToC updating
65+ $self->{htu__Mode} = MODE_DO_NOTHING;
66+ # Deinitialize insertor batch
67+ $self->_deinitializeInsertorBatch();
68+} # _deinitializeUpdatorBatch()
69+
70+
71+#--- HTML::TokenUpdator::_doesHashEqualHash() ---------------------------------
72+# function: Determines whether hash1 equals hash2.
73+# args: - $aHash1
74+# - $aHash2
75+# returns: True (1) if hash1 equals hash2, 0 if not. For example, with the
76+# following hashes:
77+#
78+# %hash1 = { %hash2 = {
79+# 'class' => 'header', 'class' => 'header',
80+# 'id' => 'intro1' 'id' => 'intro2'
81+# } }
82+#
83+# the routine will return 0, cause the hash fields 'id' differ.
84+# note: Class function.
85+
86+sub _doesHashEqualHash {
87+ # Get arguments
88+ my ($aHash1, $aHash2) = @_;
89+ # Local variables
90+ my ($key1, $value1, $key2, $value2, $result);
91+ # Bias to success
92+ $result = 1;
93+ # Loop through hash1 while values available
94+ HASH1: while (($key1, $value1) = each %$aHash1) {
95+ # Yes, values are available;
96+ # Value1 differs from value2?
97+ if ($value1 ne $aHash2->{$key1}) {
98+ # Yes, hashes differ;
99+ # Indicate condition fails
100+ $result = 0;
101+ # Reset 'each' iterator which we're going to break
102+ keys %$aHash2;
103+ # Break loop
104+ last HASH1;
105+ }
106+ }
107+ # Return value
108+ return $result;
109+} # _doesHashEqualHash()
110+
111+
112+#--- HTML::TokenUpdator::_doesTagExistInArray() -------------------------------
113+# function: Check whether tag & attributes matches any of the tags & attributes
114+# in the specified array. The array must consist of elements with
115+# format:
116+#
117+# [$tag, \%attributes]
118+#
119+# args: - $aTag: tag to search for
120+# - $aAttributes: tag attributes to search for
121+# - $aArray: Array to search in.
122+# returns: 1 if tag does exist in array, 0 if not.
123+# note: Class function.
124+
125+sub _doesTagExistInArray {
126+ # Get arguments
127+ my ($aTag, $aAttributes, $aArray) = @_;
128+ # Local variables
129+ my ($tag, $result);
130+ # Bias to non-existing tag
131+ $result = 0;
132+ # Loop through existing tags
133+ TAG: foreach $tag (@{$aArray}) {
134+ if (defined(@{$tag}[0])) {
135+ # Does tag equals any existing tag?
136+ if ($aTag eq @{$tag}[0]) {
137+ # Yes, tag equals existing tag;
138+ # Do hashes equal?
139+ if (HTML::TocUpdator::_doesHashEqualHash(
140+ $aAttributes, @{$tag}[1]
141+ )) {
142+ # Yes, hashes are the same;
143+ # Indicate tag exists in array
144+ $result = 1;
145+ # Break loop
146+ last TAG;
147+ }
148+ }
149+ }
150+ }
151+ # Return value
152+ return $result;
153+} # _doesTagExistInArray()
154+
155+
156+#--- HTML::TocUpdator::_initializeUpdatorBatch() ----------------------------
157+# function: Initialize insertor batch.
158+# args: - $aMode: Mode. Can be either MODE_DO_INSERT or MODE_DO_UPDATE
159+# - $aTocs: Reference to array of tocs.
160+# - $aOptions: optional options
161+# note: Updating actually means: deleting the old ToC and inserting a new
162+# ToC. That's why we're calling 'insertor' methods here.
163+
164+sub _initializeUpdatorBatch {
165+ # Get arguments
166+ my ($self, $aMode, $aTocs, $aOptions) = @_;
167+ # Initialize insertor batch
168+ $self->_initializeInsertorBatch($aTocs, $aOptions);
169+ # Parse ToC update templates
170+ $self->_parseTocUpdateTokens();
171+ # Indicate start of ToC updating
172+ $self->{htu__Mode} = $aMode;
173+} # _initializeUpdatorBatch()
174+
175+
176+#--- HTML::TocUpdator::_parseTocUpdateTokens() --------------------------------
177+# function: Parse ToC insertion point specifier.
178+
179+sub _parseTocUpdateTokens {
180+ # Get arguments
181+ my ($self) = @_;
182+ # Local variables
183+ my ($toc, $tokenType, $tokenPreposition, $token);
184+ my ($tocInsertionPoint, $tocInsertionPointTokenAttributes);
185+ # Create parser for update begin tokens
186+ my $tokenUpdateBeginParser = HTML::_TokenUpdateParser->new(
187+ $self->{_tokensUpdateBegin}
188+ );
189+ # Create parser for update end tokens
190+ my $tokenUpdateEndParser = HTML::_TokenUpdateParser->new(
191+ $self->{_tokensUpdateEnd}
192+ );
193+
194+ # Loop through ToCs
195+ foreach $toc (@{$self->{_tocs}}) {
196+ # Parse update tokens
197+ $tokenUpdateBeginParser->parse(
198+ $toc->{_tokenUpdateBeginOfAnchorNameBegin}
199+ );
200+ $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginOfAnchorNameEnd});
201+ $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginNumber});
202+ $tokenUpdateBeginParser->parse($toc->{_tokenUpdateBeginToc});
203+
204+ $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameBegin});
205+ $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndOfAnchorNameEnd});
206+ $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndNumber});
207+ $tokenUpdateEndParser->parse($toc->{_tokenUpdateEndToc});
208+ }
209+} # _parseTocUpdateTokens()
210+
211+
212+#--- HTML::TocUpdator::_resetBatchVariables() ---------------------------------
213+# function: Reset batch variables
214+
215+sub _resetBatchVariables {
216+ # Get arguments
217+ my ($self) = @_;
218+ # Call ancestor
219+ $self->SUPER::_resetBatchVariables();
220+ # Arrays containing start, end, comment & text tokens which indicate
221+ # the begin of ToC tokens. The tokens are stored in keys of hashes to
222+ # avoid storing duplicates as an array would.
223+ $self->{_tokensUpdateBegin} = [
224+ [], # ['<start tag>', <attributes>]
225+ {}, # {'<end tag>' => ''}
226+ {}, # {'<text>' => ''}
227+ {} # {'<comment>' => ''}
228+ ];
229+ # Arrays containing start, end, comment & text tokens which indicate
230+ # the end of ToC tokens. The tokens are stored in keys of hashes to
231+ # avoid storing duplicates as an array would.
232+ $self->{_tokensUpdateEnd} = [
233+ [], # ['<start tag>', <attributes>]
234+ {}, # {'<end tag>' => ''}
235+ {}, # {'<text>' => ''}
236+ {} # {'<comment>' => ''}
237+ ];
238+} # _resetBatchVariables()
239+
240+
241+#--- HTML::TocUpdator::_setActiveAnchorName() ---------------------------------
242+# function: Set active anchor name.
243+# args: - aAnchorName: Name of anchor name to set active.
244+
245+sub _setActiveAnchorName {
246+ # Get arguments
247+ my ($self, $aAnchorName) = @_;
248+ # Are tokens being deleted?
249+ if (! $self->{_doDeleteTokens}) {
250+ # No, tokens aren't being deleted;
251+ # Call ancestor to set anchor name
252+ $self->SUPER::_setActiveAnchorName($aAnchorName);
253+ }
254+} # _setActiveAnchorName()
255+
256+
257+#--- HTML::TocUpdator::_update() ----------------------------------------------
258+# function: Update ToC in string.
259+# args: - $aMode: Mode. Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
260+# - $aToc: (reference to array of) ToC object to update
261+# - $aString: string to update ToC of
262+# - $aOptions: optional updator options
263+# note: Used internally.
264+
265+sub _update {
266+ # Get arguments
267+ my ($self, $aMode, $aToc, $aString, $aOptions) = @_;
268+ # Initialize TocUpdator batch
269+ $self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
270+ # Start updating ToC by starting ToC insertion
271+ $self->_insert($aString);
272+ # Deinitialize TocUpdator batch
273+ $self->_deinitializeUpdatorBatch();
274+} # update()
275+
276+
277+#--- HTML::TocUpdator::_updateFile() ------------------------------------------
278+# function: Update ToCs in file.
279+# args: - $aMode: Mode. Can be either MODE_DO_UPDATE or MODE_DO_INSERT.
280+# - $aToc: (reference to array of) ToC object to update
281+# - $aFile: (reference to array of) file to parse for updating.
282+# - $aOptions: optional updator options
283+# note: Used internally.
284+
285+sub _updateFile {
286+ # Get arguments
287+ my ($self, $aMode, $aToc, $aFile, $aOptions) = @_;
288+ # Initialize TocUpdator batch
289+ $self->_initializeUpdatorBatch($aMode, $aToc, $aOptions);
290+ # Start updating ToC by starting ToC insertion
291+ $self->_insertIntoFile($aFile);
292+ # Deinitialize TocUpdator batch
293+ $self->_deinitializeUpdatorBatch();
294+} # _updateFile()
295+
296+
297+#--- HTML::TocUpdator::_writeOrBufferOutput() ---------------------------------
298+# function: Write processed HTML to output device(s).
299+# args: - aOutput: scalar to write
300+
301+sub _writeOrBufferOutput {
302+ # Get arguments
303+ my ($self, $aOutput) = @_;
304+ # Delete output?
305+ if (! $self->{_doDeleteTokens}) {
306+ # No, don't delete output;
307+ # Call ancestor
308+ $self->SUPER::_writeOrBufferOutput($aOutput);
309+ }
310+} # _writeOrBufferOutput()
311+
312+
313+#--- HTML::TocUpdator::anchorNameBegin() --------------------------------------
314+# function: Process 'anchor name begin' generated by HTML::Toc.
315+# args: - $aAnchorName: Anchor name begin tag to output.
316+# - $aToc: Reference to ToC to which anchorname belongs.
317+
318+sub anchorNameBegin {
319+ # Get arguments
320+ my ($self, $aAnchorNameBegin, $aToc) = @_;
321+ # Call ancestor
322+ $self->SUPER::anchorNameBegin($aAnchorNameBegin);
323+ # Must ToC be inserted or updated?
324+ if ($self->{htu__Mode} != MODE_DO_NOTHING) {
325+ # Yes, ToC must be inserted or updated;
326+ # Surround anchor name with update tags
327+ $self->{_outputPrefix} =
328+ $aToc->{_tokenUpdateBeginOfAnchorNameBegin} .
329+ $self->{_outputPrefix} .
330+ $aToc->{_tokenUpdateEndOfAnchorNameBegin};
331+ }
332+} # anchorNameBegin()
333+
334+
335+#--- HTML::TocUpdator::anchorNameEnd() ----------------------------------------
336+# function: Process 'anchor name end' generated by HTML::Toc.
337+# args: - $aAnchorNameEnd: Anchor name end tag to output.
338+# - $aToc: Reference to ToC to which anchorname belongs.
339+
340+sub anchorNameEnd {
341+ # Get arguments
342+ my ($self, $aAnchorNameEnd, $aToc) = @_;
343+ # Call ancestor
344+ $self->SUPER::anchorNameEnd($aAnchorNameEnd);
345+ # Must ToC be inserted or updated?
346+ if ($self->{htu__Mode} != MODE_DO_NOTHING) {
347+ # Yes, ToC must be inserted or updated;
348+ # Surround anchor name with update tags
349+ $self->{_outputSuffix} =
350+ $aToc->{_tokenUpdateBeginOfAnchorNameEnd} .
351+ $self->{_outputSuffix} .
352+ $aToc->{_tokenUpdateEndOfAnchorNameEnd};
353+ }
354+} # anchorNameEnd()
355+
356+
357+#--- HTML::TocUpdator::comment() ----------------------------------------------
358+# function: Process comment.
359+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
360+
361+sub comment {
362+ # Get arguments
363+ my ($self, $aComment) = @_;
364+ # Must ToC be updated?
365+ if ($self->{htu__Mode} == MODE_DO_UPDATE) {
366+ # Yes, ToC must be updated;
367+ # Updator is currently deleting tokens?
368+ if ($self->{_doDeleteTokens}) {
369+ # Yes, tokens must be deleted;
370+ # Call ancestor
371+ $self->SUPER::comment($aComment);
372+
373+ # Look for update end token
374+
375+ # Does comment matches update end token?
376+ if (defined(
377+ $self->{_tokensUpdateEnd}[TUT_TOKENTYPE_COMMENT]{$aComment}
378+ )) {
379+ # Yes, comment matches update end token;
380+ # Indicate to stop deleting tokens
381+ $self->{_doDeleteTokens} = 0;
382+ }
383+ }
384+ else {
385+ # No, tokens mustn't be deleted;
386+
387+ # Look for update begin token
388+
389+ # Does comment matches update begin token?
390+ if (defined(
391+ $self->{_tokensUpdateBegin}[TUT_TOKENTYPE_COMMENT]{$aComment}
392+ )) {
393+ # Yes, comment matches update begin token;
394+ # Indicate to start deleting tokens
395+ $self->{_doDeleteTokens} = 1;
396+ }
397+ # Call ancestor
398+ $self->SUPER::comment($aComment);
399+ }
400+ }
401+ else {
402+ # No, ToC mustn't be updated;
403+ # Call ancestor
404+ $self->SUPER::comment($aComment);
405+ }
406+} # comment()
407+
408+
409+#--- HTML::TocUpdator::end() --------------------------------------------------
410+# function: This function is called every time a closing tag is encountered.
411+# args: - $aTag: tag name (in lower case).
412+# - $aOrigText: tag name including brackets.
413+
414+sub end {
415+ # Get arguments
416+ my ($self, $aTag, $aOrigText) = @_;
417+ # Call ancestor
418+ $self->SUPER::end($aTag, $aOrigText);
419+ # Must ToC be updated?
420+ if ($self->{htu__Mode} == MODE_DO_UPDATE) {
421+ # Yes, ToC must be updated;
422+ # Updator is currently deleting tokens?
423+ if ($self->{_doDeleteTokens}) {
424+ # Yes, tokens must be deleted;
425+ # Does end tag matches update end token?
426+ if (defined(
427+ $self->{_tokensUpdateEnd}[TUT_TOKENTYPE_END]{$aTag}
428+ )) {
429+ # Yes, end tag matches update end token;
430+ # Indicate to stop deleting tokens
431+ $self->{_doDeleteTokens} = 0;
432+ }
433+ }
434+ }
435+} # end()
436+
437+
438+#--- HTML::TocUpdator::insert() -----------------------------------------------
439+# function: Insert ToC in string.
440+# args: - $aToc: (reference to array of) ToC object to update
441+# - $aString: string to insert ToC in.
442+# - $aOptions: optional updator options
443+
444+sub insert {
445+ # Get arguments
446+ my ($self, $aToc, $aString, $aOptions) = @_;
447+ # Do start insert
448+ $self->_update(MODE_DO_INSERT, $aToc, $aString, $aOptions);
449+} # insert()
450+
451+
452+#--- HTML::TocUpdator::insertIntoFile() --------------------------------------
453+# function: Insert ToC in file.
454+# args: - $aToc: (reference to array of) ToC object to update
455+# - $aFile: File to insert ToC in.
456+# - $aOptions: optional updator options
457+
458+sub insertIntoFile {
459+ # Get arguments
460+ my ($self, $aToc, $aFile, $aOptions) = @_;
461+ # Do start insert
462+ $self->_updateFile(MODE_DO_INSERT, $aToc, $aFile, $aOptions);
463+} # insertIntoFile()
464+
465+
466+#--- HTML::TocUpdator::number() -----------------------------------------------
467+# function: Process heading number generated by HTML::Toc.
468+# args: - $aNumber
469+# - $aToc: Reference to ToC to which anchorname belongs.
470+
471+sub number {
472+ # Get arguments
473+ my ($self, $aNumber, $aToc) = @_;
474+ # Call ancestor
475+ $self->SUPER::number($aNumber);
476+ # Must ToC be inserted or updated?
477+ if ($self->{htu__Mode} != MODE_DO_NOTHING) {
478+ # Yes, ToC must be inserted or updated;
479+ # Surround number with update tags
480+ $self->{_outputSuffix} =
481+ $aToc->{_tokenUpdateBeginNumber} .
482+ $self->{_outputSuffix} .
483+ $aToc->{_tokenUpdateEndNumber};
484+ }
485+} # number()
486+
487+
488+#--- HTML::TocUpdator::start() ------------------------------------------------
489+# function: This function is called every time an opening tag is encountered.
490+# args: - $aTag: tag name (in lower case).
491+# - $aAttr: reference to hash containing all tag attributes (in lower
492+# case).
493+# - $aAttrSeq: reference to array containing all tag attributes (in
494+# lower case) in the original order
495+# - $aOrigText: the original HTML text
496+
497+sub start {
498+ # Get arguments
499+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
500+ # Must ToC be updated?
501+ if ($self->{htu__Mode} == MODE_DO_UPDATE) {
502+ # Yes, ToC must be updated;
503+ # Does start tag matches token update begin tag?
504+ if (HTML::TocUpdator::_doesTagExistInArray(
505+ $aTag, $aAttr, $self->{_tokensUpdateBegin}[TUT_TOKENTYPE_START]
506+ )) {
507+ # Yes, start tag matches token update tag;
508+ # Indicate to delete tokens
509+ $self->{_doDeleteTokens} = 1;
510+ }
511+ }
512+ # Let ancestor process the start tag
513+ $self->SUPER::start($aTag, $aAttr, $aAttrSeq, $aOrigText);
514+} # start()
515+
516+
517+#--- HTML::TocUpdator::toc() --------------------------------------------------
518+# function: Toc processing method. Add toc reference to scenario.
519+# args: - $aScenario: Scenario to add ToC reference to.
520+# - $aToc: Reference to ToC to insert.
521+# note: The ToC hasn't been build yet; only a reference to the ToC to be
522+# build is inserted.
523+
524+sub toc {
525+ # Get arguments
526+ my ($self, $aScenario, $aToc) = @_;
527+
528+ # Surround toc with update tokens
529+
530+ # Add update begin token
531+ push(@$aScenario, \$aToc->{_tokenUpdateBeginToc});
532+ # Call ancestor
533+ $self->SUPER::toc($aScenario, $aToc);
534+ # Add update end token
535+ push(@$aScenario, \$aToc->{_tokenUpdateEndToc});
536+} # toc()
537+
538+
539+#--- HTML::TocUpdator::_processTocText() --------------------------------------
540+# function: Toc text processing function.
541+# args: - $aText: Text to add to ToC.
542+# - $aToc: ToC to add text to.
543+
544+sub _processTocText {
545+ # Get arguments
546+ my ($self, $aText, $aToc) = @_;
547+ # Delete output?
548+ if (! $self->{_doDeleteTokens}) {
549+ # No, don't delete output;
550+ # Call ancestor
551+ $self->SUPER::_processTocText($aText, $aToc);
552+ }
553+} # _processTocText()
554+
555+
556+#--- HTML::TocUpdator::update() -----------------------------------------------
557+# function: Update ToC in string.
558+# args: - $aToc: (reference to array of) ToC object to update
559+# - $aString: string to update ToC of
560+# - $aOptions: optional updator options
561+
562+sub update {
563+ # Get arguments
564+ my ($self, $aToc, $aString, $aOptions) = @_;
565+ # Do start update
566+ $self->_update(MODE_DO_UPDATE, $aToc, $aString, $aOptions);
567+} # update()
568+
569+
570+#--- HTML::TocUpdator::updateFile() -------------------------------------------
571+# function: Update ToC of file.
572+# args: - $aToc: (reference to array of) ToC object to update
573+# - $aFile: (reference to array of) file to parse for updating.
574+# - $aOptions: optional updator options
575+
576+sub updateFile {
577+ # Get arguments
578+ my ($self, $aToc, $aFile, $aOptions) = @_;
579+ # Do start update
580+ $self->_updateFile(MODE_DO_UPDATE, $aToc, $aFile, $aOptions);
581+} # update()
582+
583+
584+
585+
586+#=== HTML::_TokenUpdateParser =================================================
587+# function: Parse 'update tokens'. 'Update tokens' mark HTML code which is
588+# inserted by 'HTML::TocInsertor'.
589+# note: Used internally.
590+
591+package HTML::_TokenUpdateParser;
592+
593+
594+BEGIN {
595+ use vars qw(@ISA);
596+
597+ @ISA = qw(HTML::Parser);
598+}
599+
600+END {}
601+
602+
603+#--- HTML::_TokenUpdateParser::new() ------------------------------------------
604+# function: Constructor
605+
606+sub new {
607+ # Get arguments
608+ my ($aType, $aTokenArray) = @_;
609+ # Create instance
610+ my $self = $aType->SUPER::new;
611+ # Reference token array
612+ $self->{tokens} = $aTokenArray;
613+ # Return instance
614+ return $self;
615+} # new()
616+
617+
618+#--- HTML::_TokenUpdateParser::comment() --------------------------------------
619+# function: Process comment.
620+# args: - $aComment: comment text with '<!--' and '-->' tags stripped off.
621+
622+sub comment {
623+ # Get arguments
624+ my ($self, $aComment) = @_;
625+ # Add token to array of update tokens
626+ $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_COMMENT]{$aComment} = '';
627+} # comment()
628+
629+
630+#--- HTML::_TokenUpdateParser::end() ------------------------------------------
631+# function: This function is called every time a closing tag is encountered
632+# by HTML::Parser.
633+# args: - $aTag: tag name (in lower case).
634+
635+sub end {
636+ # Get arguments
637+ my ($self, $aTag, $aOrigText) = @_;
638+ # Add token to array of update tokens
639+ $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_END]{$aTag} = '';
640+} # end()
641+
642+
643+#--- HTML::_TokenUpdateParser::parse() ----------------------------------------
644+# function: Parse token.
645+# args: - $aToken: 'update token' to parse
646+
647+sub parse {
648+ # Get arguments
649+ my ($self, $aString) = @_;
650+ # Call ancestor
651+ $self->SUPER::parse($aString);
652+} # parse()
653+
654+
655+#--- HTML::_TokenUpdateParser::start() ----------------------------------------
656+# function: This function is called every time an opening tag is encountered.
657+# args: - $aTag: tag name (in lower case).
658+# - $aAttr: reference to hash containing all tag attributes (in lower
659+# case).
660+# - $aAttrSeq: reference to array containing all tag attributes (in
661+# lower case) in the original order
662+# - $aOrigText: the original HTML text
663+
664+sub start {
665+ # Get arguments
666+ my ($self, $aTag, $aAttr, $aAttrSeq, $aOrigText) = @_;
667+ # Does token exist in array?
668+ if (! HTML::TocUpdator::_doesTagExistInArray(
669+ $aTag, $aAttr, $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]
670+ )) {
671+ # No, token doesn't exist in array;
672+ # Add token to array of update tokens
673+ push(
674+ @{$self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_START]},
675+ [$aTag, $aAttr]
676+ );
677+ }
678+} # start()
679+
680+
681+#--- HTML::_TokenUpdateParser::text() -----------------------------------------
682+# function: This function is called every time plain text is encountered.
683+# args: - @_: array containing data.
684+
685+sub text {
686+ # Get arguments
687+ my ($self, $aText) = @_;
688+ # Add token to array of update tokens
689+ $self->{tokens}[HTML::TocUpdator::TUT_TOKENTYPE_TEXT]{$aText} = '';
690+} # text()
691+
692+
693+1;
examples/includes/HTML-Toc-0.91/t/ManualTest/manualTest1.htm+92−0
@@ -0,0 +1,92 @@
1+<html>
2+<head>
3+ <title>Manual</title>
4+ <style type="text/css">
5+ ul.toc_appendix1 {
6+ list-style-type: none;
7+ margin-left: 0;
8+ margin-top: 1em;
9+ margin-bottom: 1em;
10+ }
11+ ul.toc_h1 {
12+ list-style-type: none;
13+ margin-left: 1;
14+ margin-top: 1em;
15+ margin-bottom: 1em;
16+ }
17+ ul.toc_h2 {
18+ list-style-type: none;
19+ }
20+ ul.toc_h3 {
21+ list-style-type: none;
22+ }
23+ ul.toc_part1 {
24+ list-style-type: none;
25+ margin-left: 1;
26+ margin-top: 1em;
27+ margin-bottom: 1em;
28+ }
29+ ul.toc_prelude1 {
30+ list-style: none;
31+ }
32+ p.captionFigure {
33+ font-style: italic;
34+ font-weight: bold;
35+ }
36+ p.captionTable {
37+ font-style: italic;
38+ font-weight: bold;
39+ }
40+ </style>
41+</head>
42+<body>
43+
44+<h1 class=prelude>Preface</h1>
45+Better C than never.
46+
47+<h1 class=hidden>Table of Contents</h1>
48+<!-- Table of Contents -->
49+
50+<h1 class=prelude>Table of Figures</h1>
51+<!-- Table of Figures -->
52+
53+<h1 class=prelude>Table of Tables</h1>
54+<!-- Table of Tables -->
55+
56+<h1 class=prelude>Introduction</h1>
57+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
58+<p class=captionTable>Compile Steps</p>
59+<ul><pre>
60+ Parser
61+ Compiler
62+ Linker
63+</pre></ul>
64+
65+<h1 class=part>Disks</h1>
66+<h1>Compiler Disk v1</h1>
67+<img src=img.gif alt="Contents Compiler Disk v1">
68+<p class=captionFigure>Contents Compiler Disk v1</p>
69+
70+<h2>System</h2>
71+<h2>Standard Library</h2>
72+
73+<h1>Compiler Disk v2</h1>
74+<img src=img.gif alt="Contents Compiler Disk v2">
75+<p class=captionFigure>Contents Compiler Disk v2</p>
76+
77+<h2>System</h2>
78+<h3>parser.com</h3>
79+<h3>compiler.com</h3>
80+<h3>linker.com</h3>
81+<h2>Standard Library</h2>
82+
83+<h1>Library System Disk</h1>
84+<h1 class=part>Personal</h1>
85+<h1>Tips & Tricks</h1>
86+<h1 class=part>Appendixes</h1>
87+<h1 class=appendix>Functions Standard Library v1</h1>
88+<h1 class=appendix>Functions Standard Library v2</h1>
89+<h1 class=appendix>Functions Graphic Library</h1>
90+<h1 class=prelude>Bibliography</h1>
91+</body>
92+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/SubSubDir1/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>SubSub1</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir1/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>Sub1</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir1/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>SubSub1</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/SubSubDir2/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>SubSub2</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir2/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>Sub2</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/SubDir3/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>Sub3</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/SiteMap/index.htm+5−0
@@ -0,0 +1,5 @@
1+<html>
2+<head>
3+<title>Main</title>
4+</head>
5+</html>
examples/includes/HTML-Toc-0.91/t/extend.t+87−0
@@ -0,0 +1,87 @@
1+#--- generate.t ---------------------------------------------------------------
2+# function: Test ToC generation.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 4; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+
12+my ($filename);
13+my $toc = HTML::Toc->new;
14+my $tocGenerator = HTML::TocGenerator->new;
15+
16+$toc->setOptions({
17+ 'doLinkToToken' => 0,
18+ 'levelIndent' => 0,
19+ 'header' => '',
20+ 'footer' => '',
21+});
22+
23+
24+BEGIN {
25+ # Create test file
26+ $filename = "file$$.htm";
27+ die "$filename is already there" if -e $filename;
28+ open(FILE, ">$filename") || die "Can't create $filename: $!";
29+ print FILE <<'EOT';
30+<h1>Header</h1>
31+EOT
32+ close(FILE);
33+}
34+
35+
36+END {
37+ # Remove test file
38+ unlink($filename) or warn "Can't unlink $filename: $!";
39+}
40+
41+
42+#--- 1. extend ----------------------------------------------------------------
43+
44+ # Generate ToC
45+$tocGenerator->generate($toc, "<h1>Header</h1>");
46+ # Extend ToC
47+$tocGenerator->extend($toc, "<h1>Header</h1>");
48+ # Test ToC
49+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
50+
51+
52+#--- 2. extendFromFile --------------------------------------------------------
53+
54+ # Generate ToC
55+$tocGenerator->generateFromFile($toc, $filename);
56+ # Extend ToC
57+$tocGenerator->extendFromFile($toc, $filename);
58+ # Test ToC
59+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
60+
61+
62+#--- 3. extendFromFiles -------------------------------------------------------
63+
64+ # Generate ToC
65+$tocGenerator->generateFromFile($toc, $filename);
66+ # Extend ToC
67+$tocGenerator->extendFromFile($toc, [$filename, $filename]);
68+ # Test ToC
69+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n<li>Header\n</ul>");
70+
71+
72+#--- 4. linkTocToToken --------------------------------------------------------
73+
74+$toc->setOptions({
75+ 'doLinkToToken' => 1,
76+});
77+ # Generate ToC
78+$tocGenerator->generate($toc, "<h1>Header</h1>");
79+ # Extend ToC
80+$tocGenerator->extend($toc, "<h1>Header</h1>");
81+ # Test ToC
82+ok($toc->format() . "\n", <<'EOT');
83+<ul>
84+<li><a href=#h-1>Header</a>
85+<li><a href=#h-2>Header</a>
86+</ul>
87+EOT
examples/includes/HTML-Toc-0.91/t/format.t+157−0
@@ -0,0 +1,157 @@
1+#--- format.t -----------------------------------------------------------------
2+# function: Test ToC formatting.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 6; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+use HTML::TocInsertor;
12+
13+my ($output, $content, $filename);
14+my $toc = HTML::Toc->new;
15+my $tocGenerator = HTML::TocGenerator->new;
16+my $tocInsertor = HTML::TocInsertor->new;
17+
18+$toc->setOptions({
19+ 'doLinkToToken' => 0,
20+ 'levelIndent' => 0,
21+ 'insertionPoint' => 'before <h1>',
22+ 'header' => '',
23+ 'footer' => '',
24+});
25+
26+
27+BEGIN {
28+ # Create test file
29+ $filename = "file$$.htm";
30+ die "$filename is already there" if -e $filename;
31+ open(FILE, ">$filename") || die "Can't create $filename: $!";
32+ print FILE <<'EOT'; close(FILE);
33+<h1>Header</h1>
34+EOT
35+}
36+
37+
38+END {
39+ # Remove test file
40+ unlink($filename) or warn "Can't unlink $filename: $!";
41+}
42+
43+
44+#--- 1. templateLevelBegin ----------------------------------------------------
45+
46+$toc->setOptions({
47+ 'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"'
48+});
49+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
50+ok($output, "<ul class=toc_h1>\n<li>Header\n</ul><h1>Header</h1>");
51+$toc->setOptions({'templateLevelBegin' => undef});
52+
53+
54+#--- 2. levelToToc -----------------------------------------------------------
55+
56+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
57+$toc->setOptions({'levelToToc' => '1'});
58+ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
59+$toc->setOptions({'levelToToc' => '.*'});
60+
61+
62+#--- 3. groupToToc -----------------------------------------------------------
63+
64+$toc->setOptions({
65+ 'tokenToToc' => [{
66+ 'level' => 1,
67+ 'tokenBegin' => '<h1 class=-foo>'
68+ }, {
69+ 'groupId' => 'foo',
70+ 'level' => 1,
71+ 'tokenBegin' => '<h1 class=foo>'
72+ }]
73+});
74+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h1 class=foo>Foo</h1>");
75+$toc->setOptions({'groupToToc' => 'foo'});
76+ok($toc->format(), "<ul>\n<li>Foo\n</ul>");
77+$toc->setOptions({'groupToToc' => '.*'});
78+
79+
80+#--- 4. header & footer -------------------------------------------------------
81+
82+$toc->setOptions({
83+ 'tokenToToc' => [{
84+ 'level' => 1,
85+ 'tokenBegin' => '<h1>'
86+ }],
87+ 'header' => '<!-- TocHeader -->',
88+ 'footer' => '<!-- TocFooter -->',
89+});
90+$tocInsertor->insert($toc, "<h1>Header1</h1>", {'output' => \$output});
91+ok("$output\n", <<EOT);
92+<!-- TocHeader --><ul>
93+<li>Header1
94+</ul><!-- TocFooter --><h1>Header1</h1>
95+EOT
96+
97+
98+ # Test 'doSingleStepLevel' => 1
99+TestSingleStepLevel1();
100+ # Test 'doSingleStepLevel' => 0
101+TestSingleStepLevel0();
102+
103+
104+#--- 5. TestSingleStepLevel1 --------------------------------------------------
105+
106+sub TestSingleStepLevel1 {
107+ my $toc = new HTML::Toc;
108+ my $tocGenerator = new HTML::TocGenerator;
109+
110+ # Generate ToC
111+ $tocGenerator->generate($toc, <<EOT);
112+<h1>Header 1</h1>
113+<h3>Header 3</h3>
114+EOT
115+ # Compare output
116+ ok($toc->format(), <<EOT);
117+
118+<!-- Table of Contents generated by Perl - HTML::Toc -->
119+<ul>
120+ <li><a href=#h-1>Header 1</a>
121+ <ul>
122+ <ul>
123+ <li><a href=#h-1.0.1>Header 3</a>
124+ </ul>
125+ </ul>
126+</ul>
127+<!-- End of generated Table of Contents -->
128+EOT
129+} # TestSingleStepLevel1()
130+
131+
132+#--- 6. TestSingleStepLevel0 --------------------------------------------------
133+
134+sub TestSingleStepLevel0 {
135+ my $toc = new HTML::Toc;
136+ my $tocGenerator = new HTML::TocGenerator;
137+
138+ # Set ToC options
139+ $toc->setOptions({'doSingleStepLevel' => 0});
140+ # Generate ToC
141+ $tocGenerator->generate($toc, <<EOT);
142+<h1>Header 1</h1>
143+<h3>Header 3</h3>
144+EOT
145+ # Compare output
146+ ok($toc->format(), <<EOT);
147+
148+<!-- Table of Contents generated by Perl - HTML::Toc -->
149+<ul>
150+ <li><a href=#h-1>Header 1</a>
151+ <ul>
152+ <li><a href=#h-1.0.1>Header 3</a>
153+ </ul>
154+</ul>
155+<!-- End of generated Table of Contents -->
156+EOT
157+} # TestSingleStepLevel0()
examples/includes/HTML-Toc-0.91/t/generate.t+200−0
@@ -0,0 +1,200 @@
1+#--- generate.t ---------------------------------------------------------------
2+# function: Test ToC generation.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 13; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+
12+my ($filename);
13+my $toc = HTML::Toc->new;
14+my $tocGenerator = HTML::TocGenerator->new;
15+
16+$toc->setOptions({
17+ 'doLinkToToken' => 0,
18+ 'levelIndent' => 0,
19+ 'header' => '',
20+ 'footer' => '',
21+});
22+
23+
24+BEGIN {
25+ # Create test file
26+ $filename = "file$$.htm";
27+ die "$filename is already there" if -e $filename;
28+ open(FILE, ">$filename") || die "Can't create $filename: $!";
29+ print FILE <<'EOT';
30+<h1>Header</h1>
31+EOT
32+ close(FILE);
33+}
34+
35+
36+END {
37+ # Remove test file
38+ unlink($filename) or warn "Can't unlink $filename: $!";
39+}
40+
41+
42+#--- 1. generate --------------------------------------------------------------
43+
44+$tocGenerator->generate($toc, "<h1>Header</h1>");
45+ok($toc->format(), "<ul>\n<li>Header\n</ul>");
46+
47+
48+#--- 2. generateFromFile ------------------------------------------------------
49+
50+$tocGenerator->generateFromFile($toc, $filename);
51+ok($toc->format(), "<ul>\n<li>Header\n</ul>");
52+
53+
54+#--- 3. generateFromFiles -----------------------------------------------------
55+
56+$tocGenerator->generateFromFile($toc, [$filename, $filename]);
57+ok($toc->format(), "<ul>\n<li>Header\n<li>Header\n</ul>");
58+
59+
60+#--- 4. doLinkToToken -----------------------------------------------------
61+
62+$toc->setOptions({'doLinkToToken' => 1});
63+$tocGenerator->generateFromFile($toc, $filename, {'globalGroups' => 1});
64+ok($toc->format(), "<ul>\n<li><a href=#h-1>Header</a>\n</ul>");
65+
66+
67+#--- 5. doLinkToFile -------------------------------------------------------
68+
69+$toc->setOptions({'doLinkToFile' => 1});
70+$tocGenerator->generateFromFile($toc, $filename);
71+ok($toc->format(), "<ul>\n<li><a href=$filename#h-1>Header</a>\n</ul>");
72+
73+
74+#--- 6. templateAnchorHrefBegin -----------------------------------------------
75+
76+ # Set options
77+$toc->setOptions({'templateAnchorHrefBegin' => '"test-$file"'});
78+ # Generate ToC
79+$tocGenerator->generateFromFile($toc, $filename);
80+ # Test ToC
81+ok($toc->format(), "<ul>\n<li>test-".$filename."Header</a>\n</ul>");
82+ # Reset options
83+$toc->setOptions({'templateAnchorHrefBegin' => undef});
84+
85+
86+#--- 7. templateAnchorHrefBegin function --------------------------------------
87+
88+sub AssembleAnchorHrefBegin {
89+ # Get arguments
90+ my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
91+ # Return value
92+ return $aFile . $aGroupId . $aLevel . $aNode;
93+} # AssembleAnchorHrefBegin()
94+
95+
96+ # Set options
97+$toc->setOptions({'templateAnchorHrefBegin' => \&AssembleAnchorHrefBegin});
98+ # Generate ToC
99+$tocGenerator->generateFromFile($toc, $filename);
100+ # Test ToC
101+ok($toc->format(), "<ul>\n<li>".$filename."h11Header</a>\n</ul>");
102+ # Reset options
103+$toc->setOptions({'templateAnchorHrefBegin' => undef});
104+
105+
106+#--- 8. levelToToc no levels available ---------------------------------------
107+
108+$toc->setOptions({'levelToToc' => '2'});
109+$tocGenerator->generate($toc, "<h1>Header</h1>");
110+ok($toc->format(), "");
111+
112+
113+#--- 9. levelToToc level 1 ---------------------------------------------------
114+
115+ # Set options
116+$toc->setOptions({
117+ 'levelToToc' => '1',
118+ 'doLinkToToken' => 0,
119+});
120+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
121+ok($toc->format(), "<ul>\n<li>Header1\n</ul>");
122+
123+
124+#--- 10. levelToToc level 2 --------------------------------------------------
125+
126+ # Set options
127+$toc->setOptions({
128+ 'levelToToc' => '2',
129+ 'doLinkToToken' => 0,
130+});
131+$tocGenerator->generate($toc, "<h1>Header1</h1>\n<h2>Header2</h2>");
132+ok($toc->format(), "<ul>\n<li>Header2\n</ul>");
133+ # Restore options
134+$toc->setOptions({
135+ 'levelToToc' => '.*',
136+});
137+
138+
139+#--- 11. tokenToToc empty array ----------------------------------------------
140+
141+ # Set options
142+$toc->setOptions({'tokenToToc' => []});
143+$tocGenerator->generate($toc, "<h1>Header</h1>");
144+ok($toc->format(), "");
145+
146+
147+#--- 12. groups nested --------------------------------------------------------
148+
149+$toc->setOptions({
150+ 'doNestGroup' => 1,
151+ 'tokenToToc' => [
152+ {
153+ 'level' => 1,
154+ 'tokenBegin' => '<h1 class=-appendix>'
155+ }, {
156+ 'groupId' => 'appendix',
157+ 'level' => 1,
158+ 'tokenBegin' => '<h1 class=appendix>'
159+ }
160+ ]
161+});
162+$tocGenerator->generate(
163+ $toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
164+);
165+ok($toc->format() . "\n", <<'EOT');
166+<ul>
167+<li>Header1
168+<ul>
169+<li>Appendix
170+</ul>
171+</ul>
172+EOT
173+
174+
175+#--- 13. groups not nested ----------------------------------------------------
176+
177+$toc->setOptions({
178+ 'doNestGroup' => 0,
179+ 'tokenToToc' => [
180+ {
181+ 'level' => 1,
182+ 'tokenBegin' => '<h1 class=-appendix>'
183+ }, {
184+ 'groupId' => 'appendix',
185+ 'level' => 1,
186+ 'tokenBegin' => '<h1 class=appendix>'
187+ }
188+ ]
189+});
190+$tocGenerator->generate(
191+ $toc, "<h1>Header1</h1>\n<h1 class=appendix>Appendix</h1>"
192+);
193+ok($toc->format() . "\n", <<'EOT');
194+<ul>
195+<li>Header1
196+</ul>
197+<ul>
198+<li>Appendix
199+</ul>
200+EOT
examples/includes/HTML-Toc-0.91/t/insert.t+336−0
@@ -0,0 +1,336 @@
1+#--- insert.t -----------------------------------------------------------------
2+# function: Test ToC insertion.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 10; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+use HTML::TocInsertor;
12+
13+my ($output, $content, $filename);
14+my $toc = HTML::Toc->new;
15+my $tocGenerator = HTML::TocGenerator->new;
16+my $tocInsertor = HTML::TocInsertor->new;
17+
18+$toc->setOptions({
19+ 'doLinkToToken' => 0,
20+ 'levelIndent' => 0,
21+ 'header' => "",
22+ 'footer' => "",
23+});
24+
25+
26+BEGIN {
27+ # Create test file
28+ $filename = "file$$.htm";
29+ die "$filename is already there" if -e $filename;
30+ open(FILE, ">$filename") || die "Can't create $filename: $!";
31+ print FILE <<'EOT'; close(FILE);
32+<h1>Header</h1>
33+EOT
34+}
35+
36+
37+END {
38+ # Remove test file
39+ unlink($filename) or warn "Can't unlink $filename: $!";
40+}
41+
42+
43+#--- 1. insert before start ---------------------------------------------------
44+
45+$toc->setOptions({'insertionPoint' => 'before <h1>'});
46+ # Generate ToC
47+$tocGenerator->generate($toc, "<h1>Header</h1>");
48+$tocInsertor->insert($toc, "<h1>Header</h1>", {
49+ 'output' => \$output,
50+ 'doGenerateToc' => 0
51+});
52+ # Test ToC
53+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
54+
55+
56+#--- 2. insert after start ----------------------------------------------------
57+
58+$toc->setOptions({'insertionPoint' => 'after <h1>'});
59+ # Generate ToC
60+$tocGenerator->generate($toc, "<h1>Header</h1>");
61+$tocInsertor->insert($toc, "<h1>Header</h1>", {
62+ 'output' => \$output,
63+ 'doGenerateToc' => 0
64+});
65+ # Test ToC
66+ok($output, "<h1><ul>\n<li>Header\n</ul>Header</h1>");
67+
68+
69+#--- 3. insert before end -----------------------------------------------------
70+
71+$toc->setOptions({'insertionPoint' => 'before </h1>'});
72+ # Generate ToC
73+$tocGenerator->generate($toc, "<h1>Header</h1>");
74+$tocInsertor->insert($toc, "<h1>Header</h1>", {
75+ 'output' => \$output,
76+ 'doGenerateToc' => 0
77+});
78+ # Test ToC
79+ok($output, "<h1>Header<ul>\n<li>Header\n</ul></h1>");
80+
81+
82+#--- 4. insert after end ------------------------------------------------------
83+
84+$toc->setOptions({'insertionPoint' => 'after </h1>'});
85+ # Generate ToC
86+$tocGenerator->generate($toc, "<h1>Header</h1>");
87+$tocInsertor->insert($toc, "<h1>Header</h1>", {
88+ 'output' => \$output,
89+ 'doGenerateToc' => 0
90+});
91+ # Test ToC
92+ok($output, "<h1>Header</h1><ul>\n<li>Header\n</ul>");
93+
94+
95+#--- 5. outputFile ------------------------------------------------------------
96+
97+$toc->setOptions({'insertionPoint' => 'before <h1>'});
98+ # Generate ToC
99+$tocGenerator->generate($toc, "<h1>Header</h1>");
100+ # Insert ToC, output to file
101+$tocInsertor->insert($toc, "<h1>Header</h1>", {
102+ 'outputFile' => $filename,
103+ 'doGenerateToc' => 0
104+});
105+ # Read outputfile
106+open(FILE, "<$filename") || die "Can't open $filename: $!";
107+$content = join('', <FILE>);
108+close(FILE);
109+ # Test ToC
110+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
111+
112+
113+#--- 6. empty toc -------------------------------------------------------------
114+
115+$tocGenerator->generate($toc, "");
116+$tocInsertor->insert($toc, "", {
117+ 'output' => \$output,
118+ 'doGenerateToc' => 0
119+});
120+ok($output, "");
121+
122+
123+#--- TestAfterDeclaration() ---------------------------------------------------
124+# function: Test putting HTML comment after declaration.
125+
126+sub TestAfterDeclaration {
127+ # Create objects
128+ my $toc = HTML::Toc->new();
129+ my $tocInsertor = HTML::TocInsertor->new();
130+ my $output;
131+
132+ # Set ToC options
133+ $toc->setOptions({
134+ 'insertionPoint' => "after <!ToC>",
135+ });
136+ # Generate ToC
137+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
138+<!ToC><body>
139+ <h1>Appendix</h1>
140+ <h2>Appendix Paragraph</h2>
141+ <h1>Appendix</h1>
142+ <h2>Appendix Paragraph</h2>
143+</body>
144+EOT
145+ # Test ToC
146+ ok($output, <<EOT);
147+<!ToC>
148+<!-- Table of Contents generated by Perl - HTML::Toc -->
149+<ul>
150+ <li><a href=#h-1>Appendix</a>
151+ <ul>
152+ <li><a href=#h-1.1>Appendix Paragraph</a>
153+ </ul>
154+ <li><a href=#h-2>Appendix</a>
155+ <ul>
156+ <li><a href=#h-2.1>Appendix Paragraph</a>
157+ </ul>
158+</ul>
159+<!-- End of generated Table of Contents -->
160+<body>
161+ <a name=h-1><h1>Appendix</h1></a>
162+ <a name=h-1.1><h2>Appendix Paragraph</h2></a>
163+ <a name=h-2><h1>Appendix</h1></a>
164+ <a name=h-2.1><h2>Appendix Paragraph</h2></a>
165+</body>
166+EOT
167+} # TestAfterDeclaration()
168+
169+
170+#--- TestNumberingStyle() -----------------------------------------------------
171+# function: Test numberingstyle.
172+
173+sub TestNumberingStyle {
174+ # Create objects
175+ my $toc = HTML::Toc->new();
176+ my $tocInsertor = HTML::TocInsertor->new();
177+ my $output;
178+
179+ # Set ToC options
180+ $toc->setOptions({
181+ 'numberingStyle' => 'lower-alpha',
182+ 'doNumberToken' => 1,
183+ 'tokenToToc' => [{
184+ 'tokenBegin' => '<h1>',
185+ }, {
186+ 'tokenBegin' => '<h2>',
187+ 'level' => 2,
188+ 'numberingStyle' => 'upper-alpha'
189+ }, {
190+ 'tokenBegin' => '<h3>',
191+ 'level' => 3,
192+ 'numberingStyle' => 'decimal'
193+ }]
194+ });
195+ # Generate ToC
196+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
197+<body>
198+ <h1>Chapter</h1>
199+ <h2>Paragraph</h2>
200+ <h3>Paragraph</h3>
201+ <h3>Paragraph</h3>
202+ <h3>Paragraph</h3>
203+</body>
204+EOT
205+ # Test ToC
206+ ok($output, <<EOT);
207+<body>
208+<!-- Table of Contents generated by Perl - HTML::Toc -->
209+<ul>
210+ <li><a href=#h-a>Chapter</a>
211+ <ul>
212+ <li><a href=#h-a.A>Paragraph</a>
213+ <ul>
214+ <li><a href=#h-a.A.1>Paragraph</a>
215+ <li><a href=#h-a.A.2>Paragraph</a>
216+ <li><a href=#h-a.A.3>Paragraph</a>
217+ </ul>
218+ </ul>
219+</ul>
220+<!-- End of generated Table of Contents -->
221+
222+ <a name=h-a><h1>a &nbsp;Chapter</h1></a>
223+ <a name=h-a.A><h2>a.A &nbsp;Paragraph</h2></a>
224+ <a name=h-a.A.1><h3>a.A.1 &nbsp;Paragraph</h3></a>
225+ <a name=h-a.A.2><h3>a.A.2 &nbsp;Paragraph</h3></a>
226+ <a name=h-a.A.3><h3>a.A.3 &nbsp;Paragraph</h3></a>
227+</body>
228+EOT
229+} # TestNumberingStyle()
230+
231+
232+#--- TestReplaceComment() -----------------------------------------------------
233+# function: Test replacing HTML comment with ToC.
234+
235+sub TestReplaceComment {
236+ # Create objects
237+ my $toc = HTML::Toc->new();
238+ my $tocInsertor = HTML::TocInsertor->new();
239+ my $output;
240+
241+ # Set ToC options
242+ $toc->setOptions({
243+ 'insertionPoint' => "replace <!-- ToC -->"
244+ });
245+ # Generate ToC
246+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
247+<!-- ToC -->
248+<body>
249+ <h1>Appendix</h1>
250+ <h2>Appendix Paragraph</h2>
251+ <h1>Appendix</h1>
252+ <h2>Appendix Paragraph</h2>
253+</body>
254+EOT
255+ # Test ToC
256+ ok($output, <<EOT);
257+
258+<!-- Table of Contents generated by Perl - HTML::Toc -->
259+<ul>
260+ <li><a href=#h-1>Appendix</a>
261+ <ul>
262+ <li><a href=#h-1.1>Appendix Paragraph</a>
263+ </ul>
264+ <li><a href=#h-2>Appendix</a>
265+ <ul>
266+ <li><a href=#h-2.1>Appendix Paragraph</a>
267+ </ul>
268+</ul>
269+<!-- End of generated Table of Contents -->
270+
271+<body>
272+ <a name=h-1><h1>Appendix</h1></a>
273+ <a name=h-1.1><h2>Appendix Paragraph</h2></a>
274+ <a name=h-2><h1>Appendix</h1></a>
275+ <a name=h-2.1><h2>Appendix Paragraph</h2></a>
276+</body>
277+EOT
278+} # TestReplaceComment()
279+
280+
281+#--- TestReplaceText() -----------------------------------------------------
282+# function: Test replacing HTML comment with ToC.
283+
284+sub TestReplaceText {
285+ # Create objects
286+ my $toc = HTML::Toc->new();
287+ my $tocInsertor = HTML::TocInsertor->new();
288+ my $output;
289+
290+ # Set ToC options
291+ $toc->setOptions({
292+ 'insertionPoint' => "replace ToC will be placed here[,]"
293+ });
294+ # Generate ToC
295+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
296+The ToC will be placed here, overnight.
297+<body>
298+ <h1>Appendix</h1>
299+ <h2>Appendix Paragraph</h2>
300+ <h1>Appendix</h1>
301+ <h2>Appendix Paragraph</h2>
302+</body>
303+EOT
304+ # Test ToC
305+ ok($output, <<EOT);
306+
307+<!-- Table of Contents generated by Perl - HTML::Toc -->
308+<ul>
309+ <li><a href=#h-1>Appendix</a>
310+ <ul>
311+ <li><a href=#h-1.1>Appendix Paragraph</a>
312+ </ul>
313+ <li><a href=#h-2>Appendix</a>
314+ <ul>
315+ <li><a href=#h-2.1>Appendix Paragraph</a>
316+ </ul>
317+</ul>
318+<!-- End of generated Table of Contents -->
319+<body>
320+ <a name=h-1><h1>Appendix</h1></a>
321+ <a name=h-1.1><h2>Appendix Paragraph</h2></a>
322+ <a name=h-2><h1>Appendix</h1></a>
323+ <a name=h-2.1><h2>Appendix Paragraph</h2></a>
324+</body>
325+EOT
326+} # TestReplaceText()
327+
328+
329+ # 7. Test 'numberingStyle'
330+TestNumberingStyle();
331+ # 8. Test replace comment
332+TestReplaceComment();
333+ # 9. Test after declaration
334+TestAfterDeclaration();
335+ # 10. Test replace text
336+TestReplaceText();
examples/includes/HTML-Toc-0.91/t/manualTest.t+768−0
@@ -0,0 +1,768 @@
1+#--- manual.t -----------------------------------------------------------------
2+# function: Test HTML::ToC generating a manual.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 3; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+use HTML::TocInsertor;
12+use HTML::TocUpdator;
13+
14+
15+#--- AssembleTocLine() --------------------------------------------------------
16+# function: Assemble ToC line.
17+
18+sub AssembleTocLine {
19+ # Get arguments
20+ my ($aLevel, $aGroupId, $aNode, $aSequenceNr, $aText) = @_;
21+ # Local variables
22+ my ($result);
23+
24+ # Assemble ToC line
25+ SWITCH: {
26+ if ($aGroupId eq "prelude") {
27+ $result = "<li>$aText\n";
28+ last SWITCH;
29+ }
30+ if ($aGroupId eq "part") {
31+ $result = "<li>Part $aNode &nbsp;$aText\n";
32+ last SWITCH;
33+ }
34+ if ($aGroupId eq "h") {
35+ $result = "<li>$aSequenceNr. &nbsp;$aText\n";
36+ last SWITCH;
37+ }
38+ else {
39+ $result = "<li>$aNode &nbsp;$aText\n";
40+ last SWITCH;
41+ }
42+ }
43+
44+ # Return value
45+ return $result;
46+} # AssembleTocLine()
47+
48+
49+#--- AssembleTokenNumber() ----------------------------------------------------
50+# function: Assemble token number.
51+
52+sub AssembleTokenNumber {
53+ # Get arguments
54+ my ($aNode, $aGroupId, $aFile, $aGroupLevel, $aLevel, $aToc) = @_;
55+ # Local variables
56+ my ($result);
57+ # Assemble token number
58+ SWITCH: {
59+ if ($aGroupId eq "part") {
60+ $result = "Part $aNode &nbsp;";
61+ last SWITCH;
62+ }
63+ else {
64+ $result = "$aNode &nbsp;";
65+ last SWITCH;
66+ }
67+ }
68+ # Return value
69+ return $result;
70+} # AssembleTokenNumber()
71+
72+
73+#--- TestInsertManualToc ------------------------------------------------------
74+# function: Test inserting ToC into manual.
75+
76+sub TestInsertManualToc {
77+ my $output;
78+ # Create objects
79+ my $toc = new HTML::Toc;
80+ my $tocOfFigures = new HTML::Toc;
81+ my $tocOfTables = new HTML::Toc;
82+ my $tocInsertor = new HTML::TocInsertor;
83+
84+ # Set ToC options
85+ $toc->setOptions({
86+ 'doNestGroup' => 1,
87+ 'doNumberToken' => 1,
88+ 'insertionPoint' => "replace <!-- Table of Contents -->",
89+ 'templateLevel' => \&AssembleTocLine,
90+ 'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
91+ 'templateLevelEnd' => '"</ul>\n"',
92+ 'templateTokenNumber' => \&AssembleTokenNumber,
93+ 'tokenToToc' => [{
94+ 'groupId' => 'part',
95+ 'doNumberToken' => 1,
96+ 'level' => 1,
97+ 'tokenBegin' => '<h1 class=part>',
98+ }, {
99+ 'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
100+ }, {
101+ 'tokenBegin' => '<h2>',
102+ 'level' => 2
103+ }, {
104+ 'tokenBegin' => '<h3>',
105+ 'level' => 3
106+ }, {
107+ 'groupId' => 'appendix',
108+ 'tokenBegin' => '<h1 class=appendix>',
109+ 'numberingStyle' => 'upper-alpha',
110+ }, {
111+ 'groupId' => 'appendix',
112+ 'tokenBegin' => '<h2 class=appendix>',
113+ 'level' => 2
114+ }, {
115+ 'groupId' => 'prelude',
116+ 'tokenBegin' => '<h1 class=prelude>',
117+ 'level' => 1,
118+ 'doNumberToken' => 0,
119+ }],
120+ });
121+ $tocOfFigures->setOptions({
122+ 'doNumberToken' => 1,
123+ 'insertionPoint' => "replace <!-- Table of Figures -->",
124+ 'templateLevelBegin' => '"<ol>\n"',
125+ 'templateLevelEnd' => '"</ol>\n"',
126+ 'templateTokenNumber' => '"Figure $node: &nbsp;"',
127+ 'tokenToToc' => [{
128+ 'groupId' => 'Figure',
129+ 'tokenBegin' => '<p class=captionFigure>'
130+ }]
131+ });
132+ $tocOfTables->setOptions({
133+ 'doNumberToken' => 1,
134+ 'insertionPoint' => "replace <!-- Table of Tables -->",
135+ 'templateLevelBegin' => '"<ol>\n"',
136+ 'templateLevelEnd' => '"</ol>\n"',
137+ 'templateTokenNumber' => '"Table $node: &nbsp;"',
138+ 'tokenToToc' => [{
139+ 'groupId' => 'Table',
140+ 'tokenBegin' => '<p class=captionTable>'
141+ }]
142+ });
143+ # Insert ToC
144+ $tocInsertor->insertIntoFile(
145+ [$toc, $tocOfFigures, $tocOfTables],
146+ 't/ManualTest/manualTest1.htm', {
147+ 'doUseGroupsGlobal' => 1,
148+ 'output' => \$output,
149+ 'outputFile' => 't/ManualTest/manualTest2.htm'
150+ }
151+ );
152+ ok($output, <<EOT);
153+<html>
154+<head>
155+ <title>Manual</title>
156+ <style type="text/css">
157+ ul.toc_appendix1 {
158+ list-style-type: none;
159+ margin-left: 0;
160+ margin-top: 1em;
161+ margin-bottom: 1em;
162+ }
163+ ul.toc_h1 {
164+ list-style-type: none;
165+ margin-left: 1;
166+ margin-top: 1em;
167+ margin-bottom: 1em;
168+ }
169+ ul.toc_h2 {
170+ list-style-type: none;
171+ }
172+ ul.toc_h3 {
173+ list-style-type: none;
174+ }
175+ ul.toc_part1 {
176+ list-style-type: none;
177+ margin-left: 1;
178+ margin-top: 1em;
179+ margin-bottom: 1em;
180+ }
181+ ul.toc_prelude1 {
182+ list-style: none;
183+ }
184+ p.captionFigure {
185+ font-style: italic;
186+ font-weight: bold;
187+ }
188+ p.captionTable {
189+ font-style: italic;
190+ font-weight: bold;
191+ }
192+ </style>
193+</head>
194+<body>
195+
196+<a name=prelude-1><h1 class=prelude>Preface</h1></a>
197+Better C than never.
198+
199+<h1 class=hidden>Table of Contents</h1>
200+
201+<!-- Table of Contents generated by Perl - HTML::Toc -->
202+<ul class=toc_prelude1>
203+ <li><a href=#prelude-1>Preface</a>
204+ <li><a href=#prelude-2>Table of Figures</a>
205+ <li><a href=#prelude-3>Table of Tables</a>
206+ <li><a href=#prelude-4>Introduction</a>
207+ <ul class=toc_part1>
208+ <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
209+ <ul class=toc_h1>
210+ <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
211+ <ul class=toc_h2>
212+ <li>1. &nbsp;<a href=#h-1.1>System</a>
213+ <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
214+ </ul>
215+ <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
216+ <ul class=toc_h2>
217+ <li>1. &nbsp;<a href=#h-2.1>System</a>
218+ <ul class=toc_h3>
219+ <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
220+ <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
221+ <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
222+ </ul>
223+ <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
224+ </ul>
225+ <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
226+ </ul>
227+ <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
228+ <ul class=toc_h1>
229+ <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
230+ </ul>
231+ <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
232+ <ul class=toc_appendix1>
233+ <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
234+ <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
235+ <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
236+ </ul>
237+ </ul>
238+ <li><a href=#prelude-5>Bibliography</a>
239+</ul>
240+<!-- End of generated Table of Contents -->
241+
242+
243+<a name=prelude-2><h1 class=prelude>Table of Figures</h1></a>
244+
245+<!-- Table of Contents generated by Perl - HTML::Toc -->
246+<ol>
247+ <li><a href=#Figure-1>Contents Compiler Disk v1</a>
248+ <li><a href=#Figure-2>Contents Compiler Disk v2</a>
249+</ol>
250+<!-- End of generated Table of Contents -->
251+
252+
253+<a name=prelude-3><h1 class=prelude>Table of Tables</h1></a>
254+
255+<!-- Table of Contents generated by Perl - HTML::Toc -->
256+<ol>
257+ <li><a href=#Table-1>Compile Steps</a>
258+</ol>
259+<!-- End of generated Table of Contents -->
260+
261+
262+<a name=prelude-4><h1 class=prelude>Introduction</h1></a>
263+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
264+<a name=Table-1><p class=captionTable>Table 1: &nbsp;Compile Steps</p></a>
265+<ul><pre>
266+ Parser
267+ Compiler
268+ Linker
269+</pre></ul>
270+
271+<a name=part-1><h1 class=part>Part 1 &nbsp;Disks</h1></a>
272+<a name=h-1><h1>1 &nbsp;Compiler Disk v1</h1></a>
273+<img src=img.gif alt="Contents Compiler Disk v1">
274+<a name=Figure-1><p class=captionFigure>Figure 1: &nbsp;Contents Compiler Disk v1</p></a>
275+
276+<a name=h-1.1><h2>1.1 &nbsp;System</h2></a>
277+<a name=h-1.2><h2>1.2 &nbsp;Standard Library</h2></a>
278+
279+<a name=h-2><h1>2 &nbsp;Compiler Disk v2</h1></a>
280+<img src=img.gif alt="Contents Compiler Disk v2">
281+<a name=Figure-2><p class=captionFigure>Figure 2: &nbsp;Contents Compiler Disk v2</p></a>
282+
283+<a name=h-2.1><h2>2.1 &nbsp;System</h2></a>
284+<a name=h-2.1.1><h3>2.1.1 &nbsp;parser.com</h3></a>
285+<a name=h-2.1.2><h3>2.1.2 &nbsp;compiler.com</h3></a>
286+<a name=h-2.1.3><h3>2.1.3 &nbsp;linker.com</h3></a>
287+<a name=h-2.2><h2>2.2 &nbsp;Standard Library</h2></a>
288+
289+<a name=h-3><h1>3 &nbsp;Library System Disk</h1></a>
290+<a name=part-2><h1 class=part>Part 2 &nbsp;Personal</h1></a>
291+<a name=h-4><h1>4 &nbsp;Tips & Tricks</h1></a>
292+<a name=part-3><h1 class=part>Part 3 &nbsp;Appendixes</h1></a>
293+<a name=appendix-A><h1 class=appendix>A &nbsp;Functions Standard Library v1</h1></a>
294+<a name=appendix-B><h1 class=appendix>B &nbsp;Functions Standard Library v2</h1></a>
295+<a name=appendix-C><h1 class=appendix>C &nbsp;Functions Graphic Library</h1></a>
296+<a name=prelude-5><h1 class=prelude>Bibliography</h1></a>
297+</body>
298+</html>
299+EOT
300+} # TestInsertManualToc()
301+
302+
303+#--- TestInsertManualForUpdating() --------------------------------------------
304+# function: Test inserting ToC into manual.
305+
306+sub TestInsertManualForUpdating {
307+ my $output;
308+ # Create objects
309+ my $toc = new HTML::Toc;
310+ my $tocOfFigures = new HTML::Toc;
311+ my $tocOfTables = new HTML::Toc;
312+ my $tocUpdator = new HTML::TocUpdator;
313+
314+ # Set ToC options
315+ $toc->setOptions({
316+ 'doNestGroup' => 1,
317+ 'doNumberToken' => 1,
318+ 'insertionPoint' => "after <!-- Table of Contents -->",
319+ 'templateLevel' => \&AssembleTocLine,
320+ 'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
321+ 'templateLevelEnd' => '"</ul>\n"',
322+ 'templateTokenNumber' => \&AssembleTokenNumber,
323+ 'tokenToToc' => [{
324+ 'groupId' => 'part',
325+ 'doNumberToken' => 1,
326+ 'level' => 1,
327+ 'tokenBegin' => '<h1 class=part>',
328+ }, {
329+ 'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
330+ }, {
331+ 'tokenBegin' => '<h2>',
332+ 'level' => 2
333+ }, {
334+ 'tokenBegin' => '<h3>',
335+ 'level' => 3
336+ }, {
337+ 'groupId' => 'appendix',
338+ 'tokenBegin' => '<h1 class=appendix>',
339+ 'numberingStyle' => 'upper-alpha',
340+ }, {
341+ 'groupId' => 'appendix',
342+ 'tokenBegin' => '<h2 class=appendix>',
343+ 'level' => 2
344+ }, {
345+ 'groupId' => 'prelude',
346+ 'tokenBegin' => '<h1 class=prelude>',
347+ 'level' => 1,
348+ 'doNumberToken' => 0,
349+ }],
350+ });
351+ $tocOfFigures->setOptions({
352+ 'doNumberToken' => 1,
353+ 'insertionPoint' => "after <!-- Table of Figures -->",
354+ 'templateLevelBegin' => '"<ol>\n"',
355+ 'templateLevelEnd' => '"</ol>\n"',
356+ 'templateTokenNumber' => '"Figure $node: &nbsp;"',
357+ 'tokenToToc' => [{
358+ 'groupId' => 'Figure',
359+ 'tokenBegin' => '<p class=captionFigure>'
360+ }]
361+ });
362+ $tocOfTables->setOptions({
363+ 'doNumberToken' => 1,
364+ 'insertionPoint' => "after <!-- Table of Tables -->",
365+ 'templateLevelBegin' => '"<ol>\n"',
366+ 'templateLevelEnd' => '"</ol>\n"',
367+ 'templateTokenNumber' => '"Table $node: &nbsp;"',
368+ 'tokenToToc' => [{
369+ 'groupId' => 'Table',
370+ 'tokenBegin' => '<p class=captionTable>'
371+ }]
372+ });
373+ # Insert ToC
374+ $tocUpdator->updateFile(
375+ [$toc, $tocOfFigures, $tocOfTables],
376+ 't/ManualTest/manualTest1.htm', {
377+ 'doUseGroupsGlobal' => 1,
378+ 'output' => \$output,
379+ 'outputFile' => 't/ManualTest/manualTest3.htm'
380+ }
381+ );
382+ ok($output, <<EOT);
383+<html>
384+<head>
385+ <title>Manual</title>
386+ <style type="text/css">
387+ ul.toc_appendix1 {
388+ list-style-type: none;
389+ margin-left: 0;
390+ margin-top: 1em;
391+ margin-bottom: 1em;
392+ }
393+ ul.toc_h1 {
394+ list-style-type: none;
395+ margin-left: 1;
396+ margin-top: 1em;
397+ margin-bottom: 1em;
398+ }
399+ ul.toc_h2 {
400+ list-style-type: none;
401+ }
402+ ul.toc_h3 {
403+ list-style-type: none;
404+ }
405+ ul.toc_part1 {
406+ list-style-type: none;
407+ margin-left: 1;
408+ margin-top: 1em;
409+ margin-bottom: 1em;
410+ }
411+ ul.toc_prelude1 {
412+ list-style: none;
413+ }
414+ p.captionFigure {
415+ font-style: italic;
416+ font-weight: bold;
417+ }
418+ p.captionTable {
419+ font-style: italic;
420+ font-weight: bold;
421+ }
422+ </style>
423+</head>
424+<body>
425+
426+<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
427+Better C than never.
428+
429+<h1 class=hidden>Table of Contents</h1>
430+<!-- Table of Contents --><!-- #BeginToc -->
431+<!-- Table of Contents generated by Perl - HTML::Toc -->
432+<ul class=toc_prelude1>
433+ <li><a href=#prelude-1>Preface</a>
434+ <li><a href=#prelude-2>Table of Figures</a>
435+ <li><a href=#prelude-3>Table of Tables</a>
436+ <li><a href=#prelude-4>Introduction</a>
437+ <ul class=toc_part1>
438+ <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
439+ <ul class=toc_h1>
440+ <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
441+ <ul class=toc_h2>
442+ <li>1. &nbsp;<a href=#h-1.1>System</a>
443+ <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
444+ </ul>
445+ <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
446+ <ul class=toc_h2>
447+ <li>1. &nbsp;<a href=#h-2.1>System</a>
448+ <ul class=toc_h3>
449+ <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
450+ <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
451+ <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
452+ </ul>
453+ <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
454+ </ul>
455+ <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
456+ </ul>
457+ <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
458+ <ul class=toc_h1>
459+ <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
460+ </ul>
461+ <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
462+ <ul class=toc_appendix1>
463+ <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
464+ <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
465+ <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
466+ </ul>
467+ </ul>
468+ <li><a href=#prelude-5>Bibliography</a>
469+</ul>
470+<!-- End of generated Table of Contents -->
471+<!-- #EndToc -->
472+
473+<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
474+<!-- Table of Figures --><!-- #BeginToc -->
475+<!-- Table of Contents generated by Perl - HTML::Toc -->
476+<ol>
477+ <li><a href=#Figure-1>Contents Compiler Disk v1</a>
478+ <li><a href=#Figure-2>Contents Compiler Disk v2</a>
479+</ol>
480+<!-- End of generated Table of Contents -->
481+<!-- #EndToc -->
482+
483+<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
484+<!-- Table of Tables --><!-- #BeginToc -->
485+<!-- Table of Contents generated by Perl - HTML::Toc -->
486+<ol>
487+ <li><a href=#Table-1>Compile Steps</a>
488+</ol>
489+<!-- End of generated Table of Contents -->
490+<!-- #EndToc -->
491+
492+<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
493+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
494+<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
495+<ul><pre>
496+ Parser
497+ Compiler
498+ Linker
499+</pre></ul>
500+
501+<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
502+<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
503+<img src=img.gif alt="Contents Compiler Disk v1">
504+<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
505+
506+<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
507+<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
508+
509+<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
510+<img src=img.gif alt="Contents Compiler Disk v2">
511+<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
512+
513+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
514+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
515+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
516+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
517+<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
518+
519+<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
520+<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
521+<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
522+<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
523+<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
524+<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
525+<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
526+<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
527+</body>
528+</html>
529+EOT
530+} # TestInsertManualForUpdating()
531+
532+
533+#--- TestUpdateManual() -------------------------------------------------------
534+# function: Test inserting ToC into manual.
535+
536+sub TestUpdateManual {
537+ my $output;
538+ # Create objects
539+ my $toc = new HTML::Toc;
540+ my $tocOfFigures = new HTML::Toc;
541+ my $tocOfTables = new HTML::Toc;
542+ my $tocUpdator = new HTML::TocUpdator;
543+
544+ # Set ToC options
545+ $toc->setOptions({
546+ 'doNestGroup' => 1,
547+ 'doNumberToken' => 1,
548+ 'insertionPoint' => "after <!-- Table of Contents -->",
549+ 'templateLevel' => \&AssembleTocLine,
550+ 'templateLevelBegin' => '"<ul class=toc_$groupId$level>\n"',
551+ 'templateLevelEnd' => '"</ul>\n"',
552+ 'templateTokenNumber' => \&AssembleTokenNumber,
553+ 'tokenToToc' => [{
554+ 'groupId' => 'part',
555+ 'doNumberToken' => 1,
556+ 'level' => 1,
557+ 'tokenBegin' => '<h1 class=part>',
558+ }, {
559+ 'tokenBegin' => '<h1 class=-[appendix|prelude|hidden|part]>'
560+ }, {
561+ 'tokenBegin' => '<h2>',
562+ 'level' => 2
563+ }, {
564+ 'tokenBegin' => '<h3>',
565+ 'level' => 3
566+ }, {
567+ 'groupId' => 'appendix',
568+ 'tokenBegin' => '<h1 class=appendix>',
569+ 'numberingStyle' => 'upper-alpha',
570+ }, {
571+ 'groupId' => 'appendix',
572+ 'tokenBegin' => '<h2 class=appendix>',
573+ 'level' => 2
574+ }, {
575+ 'groupId' => 'prelude',
576+ 'tokenBegin' => '<h1 class=prelude>',
577+ 'level' => 1,
578+ 'doNumberToken' => 0,
579+ }],
580+ });
581+ $tocOfFigures->setOptions({
582+ 'doNumberToken' => 1,
583+ 'insertionPoint' => "after <!-- Table of Figures -->",
584+ 'templateLevelBegin' => '"<ol>\n"',
585+ 'templateLevelEnd' => '"</ol>\n"',
586+ 'templateTokenNumber' => '"Figure $node: &nbsp;"',
587+ 'tokenToToc' => [{
588+ 'groupId' => 'Figure',
589+ 'tokenBegin' => '<p class=captionFigure>'
590+ }]
591+ });
592+ $tocOfTables->setOptions({
593+ 'doNumberToken' => 1,
594+ 'insertionPoint' => "after <!-- Table of Tables -->",
595+ 'templateLevelBegin' => '"<ol>\n"',
596+ 'templateLevelEnd' => '"</ol>\n"',
597+ 'templateTokenNumber' => '"Table $node: &nbsp;"',
598+ 'tokenToToc' => [{
599+ 'groupId' => 'Table',
600+ 'tokenBegin' => '<p class=captionTable>'
601+ }]
602+ });
603+ # Insert ToC
604+ $tocUpdator->updateFile(
605+ [$toc, $tocOfFigures, $tocOfTables],
606+ 't/ManualTest/manualTest3.htm', {
607+ 'doUseGroupsGlobal' => 1,
608+ 'output' => \$output,
609+ 'outputFile' => 't/ManualTest/manualTest4.htm'
610+ }
611+ );
612+ ok($output, <<EOT);
613+<html>
614+<head>
615+ <title>Manual</title>
616+ <style type="text/css">
617+ ul.toc_appendix1 {
618+ list-style-type: none;
619+ margin-left: 0;
620+ margin-top: 1em;
621+ margin-bottom: 1em;
622+ }
623+ ul.toc_h1 {
624+ list-style-type: none;
625+ margin-left: 1;
626+ margin-top: 1em;
627+ margin-bottom: 1em;
628+ }
629+ ul.toc_h2 {
630+ list-style-type: none;
631+ }
632+ ul.toc_h3 {
633+ list-style-type: none;
634+ }
635+ ul.toc_part1 {
636+ list-style-type: none;
637+ margin-left: 1;
638+ margin-top: 1em;
639+ margin-bottom: 1em;
640+ }
641+ ul.toc_prelude1 {
642+ list-style: none;
643+ }
644+ p.captionFigure {
645+ font-style: italic;
646+ font-weight: bold;
647+ }
648+ p.captionTable {
649+ font-style: italic;
650+ font-weight: bold;
651+ }
652+ </style>
653+</head>
654+<body>
655+
656+<!-- #BeginTocAnchorNameBegin --><a name=prelude-1><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Preface</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
657+Better C than never.
658+
659+<h1 class=hidden>Table of Contents</h1>
660+<!-- Table of Contents --><!-- #BeginToc -->
661+<!-- Table of Contents generated by Perl - HTML::Toc -->
662+<ul class=toc_prelude1>
663+ <li><a href=#prelude-1>Preface</a>
664+ <li><a href=#prelude-2>Table of Figures</a>
665+ <li><a href=#prelude-3>Table of Tables</a>
666+ <li><a href=#prelude-4>Introduction</a>
667+ <ul class=toc_part1>
668+ <li>Part 1 &nbsp;<a href=#part-1>Disks</a>
669+ <ul class=toc_h1>
670+ <li>1. &nbsp;<a href=#h-1>Compiler Disk v1</a>
671+ <ul class=toc_h2>
672+ <li>1. &nbsp;<a href=#h-1.1>System</a>
673+ <li>2. &nbsp;<a href=#h-1.2>Standard Library</a>
674+ </ul>
675+ <li>2. &nbsp;<a href=#h-2>Compiler Disk v2</a>
676+ <ul class=toc_h2>
677+ <li>1. &nbsp;<a href=#h-2.1>System</a>
678+ <ul class=toc_h3>
679+ <li>1. &nbsp;<a href=#h-2.1.1>parser.com</a>
680+ <li>2. &nbsp;<a href=#h-2.1.2>compiler.com</a>
681+ <li>3. &nbsp;<a href=#h-2.1.3>linker.com</a>
682+ </ul>
683+ <li>2. &nbsp;<a href=#h-2.2>Standard Library</a>
684+ </ul>
685+ <li>3. &nbsp;<a href=#h-3>Library System Disk</a>
686+ </ul>
687+ <li>Part 2 &nbsp;<a href=#part-2>Personal</a>
688+ <ul class=toc_h1>
689+ <li>4. &nbsp;<a href=#h-4>Tips & Tricks</a>
690+ </ul>
691+ <li>Part 3 &nbsp;<a href=#part-3>Appendixes</a>
692+ <ul class=toc_appendix1>
693+ <li>A &nbsp;<a href=#appendix-A>Functions Standard Library v1</a>
694+ <li>B &nbsp;<a href=#appendix-B>Functions Standard Library v2</a>
695+ <li>C &nbsp;<a href=#appendix-C>Functions Graphic Library</a>
696+ </ul>
697+ </ul>
698+ <li><a href=#prelude-5>Bibliography</a>
699+</ul>
700+<!-- End of generated Table of Contents -->
701+<!-- #EndToc -->
702+
703+<!-- #BeginTocAnchorNameBegin --><a name=prelude-2><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Figures</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
704+<!-- Table of Figures --><!-- #BeginToc -->
705+<!-- Table of Contents generated by Perl - HTML::Toc -->
706+<ol>
707+ <li><a href=#Figure-1>Contents Compiler Disk v1</a>
708+ <li><a href=#Figure-2>Contents Compiler Disk v2</a>
709+</ol>
710+<!-- End of generated Table of Contents -->
711+<!-- #EndToc -->
712+
713+<!-- #BeginTocAnchorNameBegin --><a name=prelude-3><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Table of Tables</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
714+<!-- Table of Tables --><!-- #BeginToc -->
715+<!-- Table of Contents generated by Perl - HTML::Toc -->
716+<ol>
717+ <li><a href=#Table-1>Compile Steps</a>
718+</ol>
719+<!-- End of generated Table of Contents -->
720+<!-- #EndToc -->
721+
722+<!-- #BeginTocAnchorNameBegin --><a name=prelude-4><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Introduction</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
723+Thanks to standardisation and the excellent work of the QWERTY corporation it is possible to learn C with almost any C manual.
724+<!-- #BeginTocAnchorNameBegin --><a name=Table-1><!-- #EndTocAnchorNameBegin --><p class=captionTable><!-- #BeginTocNumber -->Table 1: &nbsp;<!-- #EndTocNumber -->Compile Steps</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
725+<ul><pre>
726+ Parser
727+ Compiler
728+ Linker
729+</pre></ul>
730+
731+<!-- #BeginTocAnchorNameBegin --><a name=part-1><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 1 &nbsp;<!-- #EndTocNumber -->Disks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
732+<!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Compiler Disk v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
733+<img src=img.gif alt="Contents Compiler Disk v1">
734+<!-- #BeginTocAnchorNameBegin --><a name=Figure-1><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 1: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v1</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
735+
736+<!-- #BeginTocAnchorNameBegin --><a name=h-1.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
737+<!-- #BeginTocAnchorNameBegin --><a name=h-1.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->1.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
738+
739+<!-- #BeginTocAnchorNameBegin --><a name=h-2><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->2 &nbsp;<!-- #EndTocNumber -->Compiler Disk v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
740+<img src=img.gif alt="Contents Compiler Disk v2">
741+<!-- #BeginTocAnchorNameBegin --><a name=Figure-2><!-- #EndTocAnchorNameBegin --><p class=captionFigure><!-- #BeginTocNumber -->Figure 2: &nbsp;<!-- #EndTocNumber -->Contents Compiler Disk v2</p><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
742+
743+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.1 &nbsp;<!-- #EndTocNumber -->System</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
744+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.1><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.1 &nbsp;<!-- #EndTocNumber -->parser.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
745+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.2><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.2 &nbsp;<!-- #EndTocNumber -->compiler.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
746+<!-- #BeginTocAnchorNameBegin --><a name=h-2.1.3><!-- #EndTocAnchorNameBegin --><h3><!-- #BeginTocNumber -->2.1.3 &nbsp;<!-- #EndTocNumber -->linker.com</h3><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
747+<!-- #BeginTocAnchorNameBegin --><a name=h-2.2><!-- #EndTocAnchorNameBegin --><h2><!-- #BeginTocNumber -->2.2 &nbsp;<!-- #EndTocNumber -->Standard Library</h2><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
748+
749+<!-- #BeginTocAnchorNameBegin --><a name=h-3><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->3 &nbsp;<!-- #EndTocNumber -->Library System Disk</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
750+<!-- #BeginTocAnchorNameBegin --><a name=part-2><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 2 &nbsp;<!-- #EndTocNumber -->Personal</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
751+<!-- #BeginTocAnchorNameBegin --><a name=h-4><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->4 &nbsp;<!-- #EndTocNumber -->Tips & Tricks</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
752+<!-- #BeginTocAnchorNameBegin --><a name=part-3><!-- #EndTocAnchorNameBegin --><h1 class=part><!-- #BeginTocNumber -->Part 3 &nbsp;<!-- #EndTocNumber -->Appendixes</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
753+<!-- #BeginTocAnchorNameBegin --><a name=appendix-A><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->A &nbsp;<!-- #EndTocNumber -->Functions Standard Library v1</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
754+<!-- #BeginTocAnchorNameBegin --><a name=appendix-B><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->B &nbsp;<!-- #EndTocNumber -->Functions Standard Library v2</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
755+<!-- #BeginTocAnchorNameBegin --><a name=appendix-C><!-- #EndTocAnchorNameBegin --><h1 class=appendix><!-- #BeginTocNumber -->C &nbsp;<!-- #EndTocNumber -->Functions Graphic Library</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
756+<!-- #BeginTocAnchorNameBegin --><a name=prelude-5><!-- #EndTocAnchorNameBegin --><h1 class=prelude>Bibliography</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
757+</body>
758+</html>
759+EOT
760+} # TestUpdateManual()
761+
762+
763+ # Test inserting ToC into manual
764+TestInsertManualToc();
765+ # Test inserting ToC with update tokens into manual
766+TestInsertManualForUpdating();
767+ # Test updating ToC
768+TestUpdateManual();
examples/includes/HTML-Toc-0.91/t/options.t+194−0
@@ -0,0 +1,194 @@
1+#--- options.t ----------------------------------------------------------------
2+# function: Test HTML::ToC. In particular test the available options.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 5; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+use HTML::TocInsertor;
12+use HTML::TocUpdator;
13+
14+my ($filename);
15+
16+BEGIN {
17+ # Create test file
18+ $filename = "file$$.htm";
19+ die "$filename is already there" if -e $filename;
20+}
21+
22+
23+END {
24+ # Remove test file
25+ unlink($filename) or warn "Can't unlink $filename: $!";
26+}
27+
28+
29+#--- TestAttributeToExcludeToken() --------------------------------------------
30+# function: Test 'HTML::Toc' option 'attributeToExcludeToken'
31+
32+sub TestAttributeToExcludeToken {
33+ # Assemble test file
34+ open(FILE, ">$filename") || die "Can't create $filename: $!";
35+ print FILE <<'EOT'; close(FILE);
36+<body>
37+ <h1>Chapter 1</h1>
38+ <h1 class=appendix>Appendix</h1>
39+</body>
40+EOT
41+
42+ # Create objects
43+ my $toc = HTML::Toc->new();
44+ my $tocGenerator = HTML::TocGenerator->new();
45+
46+ $toc->setOptions({
47+ 'attributeToExcludeToken' => 'foo',
48+ 'tokenToToc' => [{
49+ 'tokenBegin' => '<h1 class=foodix>'
50+ }]
51+ });
52+ # Generate ToC
53+ $tocGenerator->generateFromFile($toc, $filename);
54+ # Test ToC
55+ ok($toc->format(), <<EOT);
56+
57+<!-- Table of Contents generated by Perl - HTML::Toc -->
58+<ul>
59+ <li><a href=#h-1>Chapter 1</a>
60+</ul>
61+<!-- End of generated Table of Contents -->
62+EOT
63+} # TestAttributeToExcludeToken()
64+
65+
66+#--- TestAttributeToTocToken() ------------------------------------------------
67+# function: Test 'HTML::Toc' option 'attributeToTocToken'
68+
69+sub TestAttributeToTocToken {
70+ # Assemble test file
71+ open(FILE, ">$filename") || die "Can't create $filename: $!";
72+ print FILE <<'EOT'; close(FILE);
73+<body>
74+ <img src=test.gif alt=Picture>
75+</body>
76+</html>
77+EOT
78+
79+ # Create objects
80+ my $toc = HTML::Toc->new();
81+ my $tocGenerator = HTML::TocGenerator->new();
82+
83+ $toc->setOptions({
84+ 'attributeToTocToken' => 'foo',
85+ 'tokenToToc' => [{
86+ 'groupId' => 'image',
87+ 'tokenBegin' => '<img alt=foo>'
88+ }],
89+ });
90+ # Generate ToC
91+ $tocGenerator->generateFromFile($toc, $filename);
92+ # Test ToC
93+ ok($toc->format(), <<EOT);
94+
95+<!-- Table of Contents generated by Perl - HTML::Toc -->
96+<ul>
97+ <li><a href=#image-1>Picture</a>
98+</ul>
99+<!-- End of generated Table of Contents -->
100+EOT
101+} # TestAttributeToTocToken()
102+
103+
104+#--- TestNumberingStyleDecimal ------------------------------------------------
105+# function: Test 'decimal' numbering style.
106+
107+sub TestNumberingStyleDecimal {
108+ # Local variables
109+ my $output;
110+ # Create objects
111+ my $toc = HTML::Toc->new();
112+ my $tocInsertor = HTML::TocInsertor->new();
113+
114+ $toc->setOptions({
115+ 'doNumberToken' => 1,
116+ 'tokenToToc' => [{
117+ 'level' => 1,
118+ 'tokenBegin' => '<h1>',
119+ 'numberingStyle' => 'decimal'
120+ }],
121+ });
122+ # Generate ToC
123+ $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
124+ # Test ToC
125+ ok("$output\n", <<EOT);
126+<a name=h-1><h1>1 &nbsp;Header</h1></a>
127+EOT
128+} # TestNumberingStyleDecimal()
129+
130+
131+#--- TestNumberingStyleLowerAlpha ---------------------------------------------
132+# function: Test 'lower-alpha' numbering style.
133+
134+sub TestNumberingStyleLowerAlpha {
135+ # Local variables
136+ my $output;
137+ # Create objects
138+ my $toc = HTML::Toc->new();
139+ my $tocInsertor = HTML::TocInsertor->new();
140+
141+ $toc->setOptions({
142+ 'doNumberToken' => 1,
143+ 'tokenToToc' => [{
144+ 'level' => 1,
145+ 'tokenBegin' => '<h1>',
146+ 'numberingStyle' => 'lower-alpha'
147+ }],
148+ });
149+ # Generate ToC
150+ $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
151+ # Test ToC
152+ ok("$output\n", <<EOT);
153+<a name=h-a><h1>a &nbsp;Header</h1></a>
154+EOT
155+} # TestNumberingStyleLowerAlpha()
156+
157+
158+#--- TestNumberingStyleUpperAlpha ---------------------------------------------
159+# function: Test 'upper-alpha' numbering style.
160+
161+sub TestNumberingStyleUpperAlpha {
162+ # Local variables
163+ my $output;
164+ # Create objects
165+ my $toc = HTML::Toc->new();
166+ my $tocInsertor = HTML::TocInsertor->new();
167+
168+ $toc->setOptions({
169+ 'doNumberToken' => 1,
170+ 'tokenToToc' => [{
171+ 'level' => 1,
172+ 'tokenBegin' => '<h1>',
173+ 'numberingStyle' => 'upper-alpha'
174+ }],
175+ });
176+ # Generate ToC
177+ $tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
178+ # Test ToC
179+ ok("$output\n", <<EOT);
180+<a name=h-A><h1>A &nbsp;Header</h1></a>
181+EOT
182+} # TestNumberingStyleUpperAlpha()
183+
184+
185+ # Test 'attributeToTocToken'
186+TestAttributeToTocToken();
187+ # Test 'attributeToExcludeToken'
188+TestAttributeToExcludeToken();
189+ # Test 'numberingStyleDecimal'
190+TestNumberingStyleDecimal();
191+ # Test 'numberingStyleLowerAlpha'
192+TestNumberingStyleLowerAlpha();
193+ # Test 'numberingStyleUpperAlpha'
194+TestNumberingStyleUpperAlpha();
examples/includes/HTML-Toc-0.91/t/podExamples.t+709−0
@@ -0,0 +1,709 @@
1+#--- podExamples.t ------------------------------------------------------------
2+# function: Test HTML::ToC. In particular test the examples as described in
3+# the POD documentation.
4+
5+use strict;
6+use Test;
7+
8+BEGIN { plan tests => 13; }
9+
10+use HTML::Toc;
11+use HTML::TocGenerator;
12+use HTML::TocInsertor;
13+use HTML::TocUpdator;
14+
15+my ($filename, $filename2);
16+
17+
18+BEGIN {
19+ # Create test file
20+ $filename = "tmp.htm";
21+ die "$filename is already there" if -e $filename;
22+ # Create test file 2
23+ $filename2 = "tmp2.htm";
24+ die "$filename2 is already there" if -e $filename2;
25+}
26+
27+
28+END {
29+ # Remove test file
30+ unlink($filename) or warn "Can't unlink $filename: $!";
31+ # Remove test file 2
32+ unlink($filename2) or warn "Can't unlink $filename2: $!";
33+}
34+
35+
36+#--- TestExtendFromFile() --------------------------------------------------
37+# function: Test 'HTML::TocGenerator->extendFromFile()
38+
39+sub TestExtendFromFile {
40+ # Assemble test file
41+ open(FILE, ">$filename") || die "Can't create $filename: $!";
42+ print FILE <<'EOT'; close(FILE);
43+<body>
44+ <h1>Chapter of document 1</h1>
45+</body>
46+EOT
47+
48+ # Assemble test file 2
49+ open(FILE, ">$filename2") || die "Can't create $filename2: $!";
50+ print FILE <<'EOT'; close(FILE);
51+<html>
52+<body>
53+ <h1>Chapter of document 2</h1>
54+</body>
55+</html>
56+EOT
57+
58+ # Create objects
59+ my $toc = HTML::Toc->new();
60+ my $tocGenerator = HTML::TocGenerator->new();
61+
62+ # Set ToC options
63+ $toc->setOptions({'doLinkToFile' => 1});
64+ # Generate ToC
65+ $tocGenerator->generateFromFile($toc, $filename);
66+ $tocGenerator->extendFromFile($toc, $filename2);
67+ # Test ToC
68+ ok($toc->format(), <<EOT);
69+
70+<!-- Table of Contents generated by Perl - HTML::Toc -->
71+<ul>
72+ <li><a href=tmp.htm#h-1>Chapter of document 1</a>
73+ <li><a href=tmp2.htm#h-2>Chapter of document 2</a>
74+</ul>
75+<!-- End of generated Table of Contents -->
76+EOT
77+} # TestExtendFromFile()
78+
79+
80+#--- TestGenerateFromFiles() --------------------------------------------------
81+# function: Test 'HTML::TocGenerator->generateFromFile()
82+
83+sub TestGenerateFromFiles {
84+ # Assemble test file
85+ open(FILE, ">$filename") || die "Can't create $filename: $!";
86+ print FILE <<'EOT'; close(FILE);
87+<body>
88+ <h1>Chapter of document 1</h1>
89+</body>
90+EOT
91+
92+ # Assemble test file 2
93+ open(FILE, ">$filename2") || die "Can't create $filename2: $!";
94+ print FILE <<'EOT'; close(FILE);
95+<html>
96+<body>
97+ <h1>Chapter of document 2</h1>
98+</body>
99+</html>
100+EOT
101+
102+ # Create objects
103+ my $toc = HTML::Toc->new();
104+ my $tocGenerator = HTML::TocGenerator->new();
105+
106+ # Set ToC options
107+ $toc->setOptions({'doLinkToFile' => 1});
108+ # Generate ToC
109+ $tocGenerator->generateFromFile($toc, [$filename, $filename2]);
110+ # Test ToC
111+ ok($toc->format(), <<EOT);
112+
113+<!-- Table of Contents generated by Perl - HTML::Toc -->
114+<ul>
115+ <li><a href=tmp.htm#h-1>Chapter of document 1</a>
116+ <li><a href=tmp2.htm#h-2>Chapter of document 2</a>
117+</ul>
118+<!-- End of generated Table of Contents -->
119+EOT
120+} # TestGenerateFromFiles()
121+
122+
123+#--- TestGenerateFromFiles() --------------------------------------------------
124+# function: Test 'HTML::TocGenerator->generateFromFile() using multiple files.
125+
126+sub TestGenerateFromFile {
127+ # Assemble test file 1
128+ open(FILE, ">$filename") || die "Can't create $filename: $!";
129+ print FILE <<'EOT'; close(FILE);
130+<html>
131+<body>
132+ <h1>Chapter</h1>
133+</body>
134+</html>
135+EOT
136+
137+ # Create objects
138+ my $toc = HTML::Toc->new();
139+ my $tocGenerator = HTML::TocGenerator->new();
140+
141+ # Generate ToC
142+ $tocGenerator->generateFromFile($toc, $filename);
143+ # Test ToC
144+ ok($toc->format(), <<EOT);
145+
146+<!-- Table of Contents generated by Perl - HTML::Toc -->
147+<ul>
148+ <li><a href=#h-1>Chapter</a>
149+</ul>
150+<!-- End of generated Table of Contents -->
151+EOT
152+} # TestGenerateFromFile()
153+
154+
155+#--- TestInsertIntoFile() -----------------------------------------------------
156+# function: Test 'HTML::TocInsertor->insertIntoFile()
157+
158+sub TestInsertIntoFile {
159+ # Assemble test file
160+ open(FILE, ">$filename") || die "Can't create $filename: $!";
161+ print FILE <<'EOT'; close(FILE);
162+<html>
163+<body>
164+ <h1>Chapter</h1>
165+</body>
166+</html>
167+EOT
168+
169+ # Create objects
170+ my $toc = HTML::Toc->new();
171+ my $tocInsertor = HTML::TocInsertor->new();
172+ my $output;
173+
174+ # Generate ToC
175+ $tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
176+ # Test ToC
177+ ok($output, <<EOT);
178+<html>
179+<body>
180+<!-- Table of Contents generated by Perl - HTML::Toc -->
181+<ul>
182+ <li><a href=#h-1>Chapter</a>
183+</ul>
184+<!-- End of generated Table of Contents -->
185+
186+ <a name=h-1><h1>Chapter</h1></a>
187+</body>
188+</html>
189+EOT
190+} # TestInsertIntoFile()
191+
192+
193+#--- TestInsertIntoFileUsingTocUpdator() --------------------------------------
194+# function: Test 'HTML::TocUpdator->insertIntoFile()
195+
196+sub TestInsertIntoFileUsingTocUpdator {
197+ # Assemble test file
198+ open(FILE, ">$filename") || die "Can't create $filename: $!";
199+ print FILE <<'EOT'; close(FILE);
200+<html>
201+<body>
202+ <h1>
203+ Chapter
204+ </h1>
205+</body>
206+</html>
207+EOT
208+
209+ # Create objects
210+ my $toc = HTML::Toc->new();
211+ my $tocUpdator = HTML::TocUpdator->new();
212+ my $output;
213+
214+ # Generate ToC
215+ $tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
216+ # Test ToC
217+ ok($output, <<EOT);
218+<html>
219+<body><!-- #BeginToc -->
220+<!-- Table of Contents generated by Perl - HTML::Toc -->
221+<ul>
222+ <li><a href=#h-1> Chapter </a>
223+</ul>
224+<!-- End of generated Table of Contents -->
225+<!-- #EndToc -->
226+ <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
227+ Chapter
228+ </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
229+</body>
230+</html>
231+EOT
232+} # TestInsertIntoFileUsingTocUpdator()
233+
234+
235+#--- TestGlobalGroups0() ------------------------------------------------------
236+# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
237+
238+sub TestGlobalGroups0 {
239+ # Assemble test file
240+ open(FILE, ">$filename") || die "Can't create $filename: $!";
241+ print FILE <<'EOT'; close(FILE);
242+<h1>Chapter</h1>
243+<h2>Paragraph</h2>
244+EOT
245+
246+ # Create objects
247+ my $toc1 = HTML::Toc->new();
248+ my $toc2 = HTML::Toc->new();
249+ my $tocGenerator = HTML::TocGenerator->new();
250+
251+ # Set options
252+ $toc1->setOptions({
253+ 'header' => '',
254+ 'footer' => '',
255+ 'tokenToToc' => [{'tokenBegin' => '<h1>'}]
256+ });
257+ $toc2->setOptions({
258+ 'header' => '',
259+ 'footer' => '',
260+ 'tokenToToc' => [{'tokenBegin' => '<h2>'}]
261+ });
262+ # Generate ToC
263+ $tocGenerator->generateFromFile([$toc1, $toc2], $filename);
264+ # Test ToC
265+ ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
266+<ul>
267+ <li><a href=#h-1>Chapter</a>
268+</ul><ul>
269+ <li><a href=#h-1>Paragraph</a>
270+</ul>
271+EOT
272+} # TestGlobalGroups0()
273+
274+
275+#--- TestGlobalGroups1() ------------------------------------------------------
276+# function: Test 'HTML::TocGenerator' option 'doUseGroupsGlobal = 0'.
277+
278+sub TestGlobalGroups1 {
279+ # Assemble test file
280+ open(FILE, ">$filename") || die "Can't create $filename: $!";
281+ print FILE <<'EOT';
282+<h1>Chapter</h1>
283+<h2>Paragraph</h2>
284+EOT
285+ close(FILE);
286+
287+ # Create objects
288+ my $toc1 = HTML::Toc->new();
289+ my $toc2 = HTML::Toc->new();
290+ my $tocGenerator = HTML::TocGenerator->new();
291+
292+ # Set options
293+ $toc1->setOptions({
294+ 'header' => '',
295+ 'footer' => '',
296+ 'tokenToToc' => [{'tokenBegin' => '<h1>'}]
297+ });
298+ $toc2->setOptions({
299+ 'header' => '',
300+ 'footer' => '',
301+ 'tokenToToc' => [{'tokenBegin' => '<h2>'}]
302+ });
303+ # Generate ToC
304+ $tocGenerator->generateFromFile(
305+ [$toc1, $toc2], $filename, {'doUseGroupsGlobal' => 1}
306+ );
307+ # Test ToC
308+ ok($toc1->format() . $toc2->format() . "\n", <<'EOT');
309+<ul>
310+ <li><a href=#h-1>Chapter</a>
311+</ul><ul>
312+ <li><a href=#h-2>Paragraph</a>
313+</ul>
314+EOT
315+} # TestGlobalGroups1()
316+
317+
318+#--- TestMultipleGroupsAppendix() ---------------------------------------------
319+# function: Test multiple ToCs
320+
321+sub TestMultipleGroupsAppendix() {
322+ # Create objects
323+ my $toc = HTML::Toc->new();
324+ my $tocInsertor = HTML::TocInsertor->new();
325+ my $output;
326+
327+ # Set ToC options
328+ $toc->setOptions({
329+ 'tokenToToc' => [{
330+ 'tokenBegin' => '<h1 class=-appendix>'
331+ }, {
332+ 'tokenBegin' => '<h2 class=-appendix>',
333+ 'level' => 2
334+ }, {
335+ 'groupId' => 'appendix',
336+ 'tokenBegin' => '<h1 class=appendix>',
337+ }, {
338+ 'groupId' => 'appendix',
339+ 'tokenBegin' => '<h2 class=appendix>',
340+ 'level' => 2
341+ }],
342+ });
343+ # Generate ToC
344+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
345+<body>
346+ <h1>Chapter</h1>
347+ <h2>Paragraph</h2>
348+ <h3>Subparagraph</h3>
349+ <h1>Chapter</h1>
350+ <h1 class=appendix>Appendix Chapter</h1>
351+ <h2 class=appendix>Appendix Paragraph</h2>
352+</body>
353+EOT
354+ # Test ToC
355+ ok($output, <<EOT);
356+<body>
357+<!-- Table of Contents generated by Perl - HTML::Toc -->
358+<ul>
359+ <li><a href=#h-1>Chapter</a>
360+ <ul>
361+ <li><a href=#h-1.1>Paragraph</a>
362+ </ul>
363+ <li><a href=#h-2>Chapter</a>
364+</ul>
365+<ul>
366+ <li><a href=#appendix-1>Appendix Chapter</a>
367+ <ul>
368+ <li><a href=#appendix-1.1>Appendix Paragraph</a>
369+ </ul>
370+</ul>
371+<!-- End of generated Table of Contents -->
372+
373+ <a name=h-1><h1>Chapter</h1></a>
374+ <a name=h-1.1><h2>Paragraph</h2></a>
375+ <h3>Subparagraph</h3>
376+ <a name=h-2><h1>Chapter</h1></a>
377+ <a name=appendix-1><h1 class=appendix>Appendix Chapter</h1></a>
378+ <a name=appendix-1.1><h2 class=appendix>Appendix Paragraph</h2></a>
379+</body>
380+EOT
381+} # TestMultipleGroupsAppendix()
382+
383+
384+#--- TestMultipleGroupsPart() -------------------------------------------------
385+# function: Test multiple ToCs
386+
387+sub TestMultipleGroupsPart() {
388+ # Create objects
389+ my $toc = HTML::Toc->new();
390+ my $tocInsertor = HTML::TocInsertor->new();
391+ my $output;
392+
393+ # Set ToC options
394+ $toc->setOptions({
395+ 'tokenToToc' => [{
396+ 'tokenBegin' => '<h1 class=-part>'
397+ }, {
398+ 'tokenBegin' => '<h2 class=-part>',
399+ 'level' => 2,
400+ }, {
401+ 'groupId' => 'part',
402+ 'tokenBegin' => '<h1 class=part>',
403+ 'level' => 1,
404+ 'doNumberToken' => 1,
405+ 'numberingStyle' => 'upper-alpha'
406+ }]
407+ });
408+ # Generate ToC
409+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
410+<body>
411+ <h1 class=part>First Part</h1>
412+ <h1>Chapter</h1>
413+ <h2>Paragraph</h2>
414+ <h1 class=part>Second Part</h1>
415+ <h1>Chapter</h1>
416+ <h2>Paragraph</h2>
417+</body>
418+EOT
419+ # Test ToC
420+ ok($output, <<EOT);
421+<body>
422+<!-- Table of Contents generated by Perl - HTML::Toc -->
423+<ul>
424+ <li><a href=#part-A>First Part</a>
425+</ul>
426+<ul>
427+ <li><a href=#h-1>Chapter</a>
428+ <ul>
429+ <li><a href=#h-1.1>Paragraph</a>
430+ </ul>
431+</ul>
432+<ul>
433+ <li><a href=#part-B>Second Part</a>
434+</ul>
435+<ul>
436+ <li><a href=#h-2>Chapter</a>
437+ <ul>
438+ <li><a href=#h-2.1>Paragraph</a>
439+ </ul>
440+</ul>
441+<!-- End of generated Table of Contents -->
442+
443+ <a name=part-A><h1 class=part>A &nbsp;First Part</h1></a>
444+ <a name=h-1><h1>Chapter</h1></a>
445+ <a name=h-1.1><h2>Paragraph</h2></a>
446+ <a name=part-B><h1 class=part>B &nbsp;Second Part</h1></a>
447+ <a name=h-2><h1>Chapter</h1></a>
448+ <a name=h-2.1><h2>Paragraph</h2></a>
449+</body>
450+EOT
451+} # TestMultipleGroupsPart()
452+
453+
454+#--- TestMultipleTocs() -------------------------------------------------------
455+# function: Test multiple ToCs
456+
457+sub TestMultipleTocs() {
458+ # Assemble test file
459+ open(FILE, ">$filename") || die "Can't create $filename: $!";
460+ print FILE <<'EOT'; close(FILE);
461+<body>
462+ <h1>Header One</h1>
463+ <img src=test1.gif alt="First picture">
464+ <h2>Paragraph One</h2>
465+ <img src=test2.gif alt="Second picture">
466+</body>
467+EOT
468+
469+ # Create objects
470+ my $toc1 = HTML::Toc->new();
471+ my $toc2 = HTML::Toc->new();
472+ my $tocInsertor = HTML::TocInsertor->new();
473+ my $output;
474+
475+ # Set ToC options
476+ $toc2->setOptions({
477+ 'tokenToToc' => [{
478+ 'groupId' => 'image',
479+ 'tokenBegin' => '<img alt=@>'
480+ }],
481+ });
482+ # Generate ToC
483+ $tocInsertor->insertIntoFile(
484+ [$toc1, $toc2], $filename, {'output' => \$output}
485+ );
486+ # Test ToC
487+ ok($output, <<EOT);
488+<body>
489+<!-- Table of Contents generated by Perl - HTML::Toc -->
490+<ul>
491+ <li><a href=#h-1>Header One</a>
492+ <ul>
493+ <li><a href=#h-1.1>Paragraph One</a>
494+ </ul>
495+</ul>
496+<!-- End of generated Table of Contents -->
497+
498+<!-- Table of Contents generated by Perl - HTML::Toc -->
499+<ul>
500+ <li><a href=#image-1>First picture</a>
501+ <li><a href=#image-2>Second picture</a>
502+</ul>
503+<!-- End of generated Table of Contents -->
504+
505+ <a name=h-1><h1>Header One</h1></a>
506+ <a name=image-1><img src=test1.gif alt="First picture"></a>
507+ <a name=h-1.1><h2>Paragraph One</h2></a>
508+ <a name=image-2><img src=test2.gif alt="Second picture"></a>
509+</body>
510+EOT
511+} # TestMultipleTocs()
512+
513+
514+#--- TestSpecifyNumberedList() ------------------------------------------------
515+# function: Test specifying numbered list.
516+
517+sub TestSpecifyNumberedList {
518+ # Assemble test file
519+ open(FILE, ">$filename") || die "Can't create $filename: $!";
520+ print FILE <<'EOT'; close(FILE);
521+<body>
522+ <h1>Chapter</h1>
523+ <h2>Paragraph</h2>
524+</body>
525+EOT
526+
527+ # Create objects
528+ my $toc = HTML::Toc->new();
529+ my $tocGenerator = HTML::TocGenerator->new();
530+
531+ # Set ToC options
532+ $toc->setOptions({
533+ 'templateLevelBegin' => '"<ol>\n"',
534+ 'templateLevelEnd' => '"</ol>\n"',
535+ });
536+ # Generate ToC
537+ $tocGenerator->generateFromFile($toc, $filename);
538+ # Test ToC
539+ ok($toc->format(), <<EOT);
540+
541+<!-- Table of Contents generated by Perl - HTML::Toc -->
542+<ol>
543+ <li><a href=#h-1>Chapter</a>
544+ <ol>
545+ <li><a href=#h-1.1>Paragraph</a>
546+ </ol>
547+</ol>
548+<!-- End of generated Table of Contents -->
549+EOT
550+} # TestSpecifyNumberedList()
551+
552+
553+#--- TestUpdateFile() ---------------------------------------------------------
554+# function: Test 'HTML::TocUpdator->updateFile()'
555+
556+sub TestUpdateFile {
557+ # Assemble test file
558+ open(FILE, ">$filename") || die "Can't create $filename: $!";
559+ print FILE <<'EOT'; close(FILE);
560+<html>
561+<body><!-- #BeginToc -->
562+foo
563+<!-- #EndToc -->
564+ <!-- #BeginTocAnchorNameBegin -->bar<!-- #EndTocAnchorNameBegin --><h1>
565+ Chapter
566+ </h1><!-- #BeginTocAnchorNameEnd -->foo<!-- #EndTocAnchorNameEnd -->
567+</body>
568+</html>
569+EOT
570+
571+ # Create objects
572+ my $toc = HTML::Toc->new();
573+ my $tocUpdator = HTML::TocUpdator->new();
574+ my $output;
575+
576+ # Generate ToC
577+ $tocUpdator->updateFile($toc, $filename, {'output' => \$output});
578+ # Test ToC
579+ ok($output, <<EOT);
580+<html>
581+<body><!-- #BeginToc -->
582+<!-- Table of Contents generated by Perl - HTML::Toc -->
583+<ul>
584+ <li><a href=#h-1> Chapter </a>
585+</ul>
586+<!-- End of generated Table of Contents -->
587+<!-- #EndToc -->
588+ <!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1>
589+ Chapter
590+ </h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
591+</body>
592+</html>
593+EOT
594+} # TestUpdateFile()
595+
596+
597+#--- TestUsingCSS() -----------------------------------------------------------
598+# function: Test multiple ToCs
599+
600+sub TestUsingCSS() {
601+
602+ # Create objects
603+ my $toc = new HTML::Toc;
604+ my $tocInsertor = new HTML::TocInsertor;
605+ my $output;
606+
607+ $toc->setOptions({
608+ 'templateLevelBegin' => '"<ol class=toc_$groupId$level>\n"',
609+ 'templateLevelEnd' => '"</ol>\n"',
610+ 'doNumberToken' => 1,
611+ 'tokenToToc' => [{
612+ 'groupId' => 'appendix',
613+ 'tokenBegin' => '<h1>',
614+ 'numberingStyle' => 'upper-alpha'
615+ }, {
616+ 'groupId' => 'appendix',
617+ 'tokenBegin' => '<h2>',
618+ 'level' => 2,
619+ }]
620+ });
621+ $tocInsertor->insert($toc, <<EOT);
622+<html>
623+<head>
624+ <style type="text/css">
625+ ol.toc_appendix1 { list-style-type: upper-alpha }
626+ </style>
627+</head>
628+<body>
629+ <h1>Appendix</h1>
630+ <h2>Appendix Paragraph</h2>
631+ <h1>Appendix</h1>
632+ <h2>Appendix Paragraph</h2>
633+</body>
634+</html>
635+EOT
636+ # Insert ToC
637+ $tocInsertor->insert($toc, <<EOT, {'output' => \$output});
638+<html>
639+<head>
640+ <style type="text/css">
641+ ol.toc_appendix1 { list-style-type: upper-alpha }
642+ </style>
643+</head>
644+<body>
645+ <h1>Appendix</h1>
646+ <h2>Appendix Paragraph</h2>
647+ <h1>Appendix</h1>
648+ <h2>Appendix Paragraph</h2>
649+</body>
650+</html>
651+EOT
652+ # Test ToC
653+ ok($output, <<EOT);
654+<html>
655+<head>
656+ <style type="text/css">
657+ ol.toc_appendix1 { list-style-type: upper-alpha }
658+ </style>
659+</head>
660+<body>
661+<!-- Table of Contents generated by Perl - HTML::Toc -->
662+<ol class=toc_appendix1>
663+ <li><a href=#appendix-A>Appendix</a>
664+ <ol class=toc_appendix2>
665+ <li><a href=#appendix-A.1>Appendix Paragraph</a>
666+ </ol>
667+ <li><a href=#appendix-B>Appendix</a>
668+ <ol class=toc_appendix2>
669+ <li><a href=#appendix-B.1>Appendix Paragraph</a>
670+ </ol>
671+</ol>
672+<!-- End of generated Table of Contents -->
673+
674+ <a name=appendix-A><h1>A &nbsp;Appendix</h1></a>
675+ <a name=appendix-A.1><h2>A.1 &nbsp;Appendix Paragraph</h2></a>
676+ <a name=appendix-B><h1>B &nbsp;Appendix</h1></a>
677+ <a name=appendix-B.1><h2>B.1 &nbsp;Appendix Paragraph</h2></a>
678+</body>
679+</html>
680+EOT
681+} # TestUsingCSS()
682+
683+
684+ # Test 'extendFromFile()'
685+TestExtendFromFile();
686+ # Test 'generateFromFile()'
687+TestGenerateFromFile();
688+ # Test 'generateFromFiles()'
689+TestGenerateFromFiles();
690+ # Test 'doUseGroupsGlobal = 0'
691+TestGlobalGroups0();
692+ # Test 'doUseGroupsGlobal = 1'
693+TestGlobalGroups1();
694+ # Test 'tocInsertor->insertIntoFile'
695+TestInsertIntoFile();
696+ # Test 'tocUpdator->insertIntoFile'
697+TestInsertIntoFileUsingTocUpdator();
698+ # Test additional 'appendix' group
699+TestMultipleGroupsAppendix();
700+ # Test additional 'part' group
701+TestMultipleGroupsPart();
702+ # Test multiple ToCs
703+TestMultipleTocs();
704+ # Test specifying numbered list
705+TestSpecifyNumberedList();
706+ # Test 'updateFile()'
707+TestUpdateFile();
708+ # Test using CSS
709+TestUsingCSS();
examples/includes/HTML-Toc-0.91/t/propagate.t+176−0
@@ -0,0 +1,176 @@
1+#--- propagate.t --------------------------------------------------------------
2+# function: Test ToC propagation.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 10; }
8+
9+use HTML::Toc;
10+use HTML::TocGenerator;
11+use HTML::TocInsertor;
12+
13+my ($output, $content, $filename);
14+my $toc = HTML::Toc->new;
15+my $tocGenerator = HTML::TocGenerator->new;
16+my $tocInsertor = HTML::TocInsertor->new;
17+
18+$toc->setOptions({
19+ 'doLinkToToken' => 0,
20+ 'levelIndent' => 0,
21+ 'insertionPoint' => 'before <h1>',
22+ 'header' => '',
23+ 'footer' => '',
24+});
25+
26+
27+BEGIN {
28+ # Create test file
29+ $filename = "file$$.htm";
30+ die "$filename is already there" if -e $filename;
31+ open(FILE, ">$filename") || die "Can't create $filename: $!";
32+ print FILE <<'EOT'; close(FILE);
33+<h1>Header</h1>
34+EOT
35+}
36+
37+
38+END {
39+ # Remove test file
40+ unlink($filename) or warn "Can't unlink $filename: $!";
41+}
42+
43+
44+#--- 1. propagate -------------------------------------------------------------
45+
46+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
47+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>");
48+
49+
50+#--- 2. propagateFile ---------------------------------------------------------
51+
52+$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
53+ok($output, "<ul>\n<li>Header\n</ul><h1>Header</h1>\n");
54+
55+
56+#--- 3. doLinkToToken -----------------------------------------------------
57+
58+$toc->setOptions({'doLinkToToken' => 1});
59+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
60+ok("$output\n", <<'EOT');
61+<ul>
62+<li><a href=#h-1>Header</a>
63+</ul><a name=h-1><h1>Header</h1></a>
64+EOT
65+
66+
67+#--- 4. templateAnchorHrefBegin -----------------------------------------------
68+
69+$toc->setOptions(
70+ {'templateAnchorHrefBegin' => '"<$node${file}test${groupId}>"'}
71+);
72+$tocInsertor->insertIntoFile($toc, $filename, {'output' => \$output});
73+ok($output, "<ul>\n<li><1${filename}testh>Header</a>\n</ul><a name=h-1><h1>Header</h1></a>\n");
74+$toc->setOptions({'templateAnchorHrefBegin' => undef});
75+
76+
77+#--- 5. templateAnchorNameBegin -----------------------------------------------
78+
79+$toc->setOptions({
80+ 'templateAnchorName' => '"$node$groupId"',
81+ 'templateAnchorNameBegin' => '"<$anchorName>"'
82+});
83+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
84+ok($output, "<ul>\n<li><a href=#1h>Header</a>\n</ul><1h><h1>Header</h1></a>");
85+$toc->setOptions({'templateAnchorName' => undef});
86+
87+
88+#--- 6. templateAnchorName function -------------------------------------------
89+
90+sub AssembleAnchorName {
91+ # Get arguments
92+ my ($aFile, $aGroupId, $aLevel, $aNode) = @_;
93+ # Return value
94+ return $aFile . $aGroupId . $aLevel . $aNode;
95+} # AssembleAnchorName()
96+
97+ # Set options
98+$toc->setOptions({'templateAnchorNameBegin' => \&AssembleAnchorName});
99+ # Propagate ToC
100+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
101+ # Test ToC
102+ok($output, "<ul>\n<li><a href=#h-1>Header</a>\n</ul>h11<h1>Header</h1></a>");
103+ # Restore options
104+$toc->setOptions({'templateAnchorNameBegin' => undef});
105+
106+
107+#--- 7. doNumberToken --------------------------------------------------------
108+
109+ # Set options
110+$toc->setOptions({'doNumberToken' => 1});
111+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
112+ok("$output\n", <<'EOT');
113+<ul>
114+<li><a href=#h-1>Header</a>
115+</ul><a name=h-1><h1>1 &nbsp;Header</h1></a>
116+EOT
117+ # Reset options
118+$toc->setOptions({
119+ 'templateTokenNumber' => undef,
120+ 'doNumberToken' => 0
121+});
122+
123+
124+#--- 8. templateTokenNumber ---------------------------------------------------
125+
126+ # Set options
127+$toc->setOptions({
128+ 'templateTokenNumber' => '"-$node-"',
129+ 'doNumberToken' => 1
130+});
131+ # Propagate ToC
132+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
133+ # Test ToC
134+ok("$output\n", <<'EOT');
135+<ul>
136+<li><a href=#h-1>Header</a>
137+</ul><a name=h-1><h1>-1-Header</h1></a>
138+EOT
139+ # Reset options
140+$toc->setOptions({
141+ 'doNumberToken' => 0,
142+ 'templateTokenNumber' => undef
143+});
144+
145+
146+#--- 9. numberingStyle --------------------------------------------------------
147+
148+ # Set options
149+$toc->setOptions({
150+ 'doNumberToken' => 1,
151+ 'tokenToToc' => [{
152+ 'level' => 1,
153+ 'tokenBegin' => '<h1>',
154+ 'numberingStyle' => 'lower-alpha'
155+ }]
156+});
157+ # Propagate ToC
158+$tocInsertor->insert($toc, "<h1>Header</h1>", {'output' => \$output});
159+ # Test ToC
160+ok("$output\n", <<'EOT');
161+<ul>
162+<li><a href=#h-a>Header</a>
163+</ul><a name=h-a><h1>a &nbsp;Header</h1></a>
164+EOT
165+ # Reset options
166+$toc->setOptions({
167+ 'doNumberToken' => 0,
168+ 'tokenToToc' => undef,
169+});
170+
171+
172+#--- 10. declaration pass through ---------------------------------------------
173+
174+$tocInsertor->insert($toc, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>', {'output' => \$output});
175+ # Test ToC
176+ok($output, '<! DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><h1>Header</h1>');
examples/includes/HTML-Toc-0.91/t/siteMap.t+97−0
@@ -0,0 +1,97 @@
1+#--- manual.t -----------------------------------------------------------------
2+# function: Test HTML::ToC generating a manual.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 1; }
8+
9+use Data::Dumper;
10+use File::Find;
11+use HTML::Toc;
12+use HTML::TocGenerator;
13+use HTML::TocInsertor;
14+use HTML::TocUpdator;
15+
16+
17+ # Create objects
18+my $toc = HTML::Toc->new();
19+my $tocGenerator = HTML::TocGenerator->new();
20+my @fileList;
21+
22+
23+#--- TestSiteMap() ------------------------------------------------------------
24+# function: Test specifying numbered list.
25+
26+sub TestSiteMap {
27+ # Set ToC options
28+ $toc->setOptions({
29+ 'doLinkToFile' => 1,
30+ 'templateAnchorName' => '""',
31+ 'templateAnchorHref' => '"<a href=$file"."#".$groupId.$level.">"',
32+ 'doLinkTocToToken' => 1,
33+ 'tokenToToc' => [{
34+ 'groupId' => 'dir',
35+ 'level' => 1,
36+ 'tokenBegin' => '<title>',
37+ 'tokenEnd' => '</title>',
38+ 'fileSpec' => '\./[^/]+$'
39+ }, {
40+ 'groupId' => 'dir',
41+ 'level' => 2,
42+ 'tokenBegin' => '<title>',
43+ 'tokenEnd' => '</title>',
44+ 'fileSpec' => '\./[^/]+?/[^/]+$'
45+ }, {
46+ 'groupId' => 'dir',
47+ 'level' => 3,
48+ 'tokenBegin' => '<title>',
49+ 'tokenEnd' => '</title>',
50+ 'fileSpec' => '\./[^/]+?/[^/]+?/[^/]+$'
51+ }]
52+ });
53+ # Change current directory
54+ chdir("t/SiteMap");
55+ # Find files, filling 'fileList'
56+ find({wanted => \&WantedSiteMap, no_chdir => 1}, '.');
57+ # Generate ToC of case-insensitively sorted file list
58+ $tocGenerator->extendFromFile(
59+ $toc, [sort {uc($a) cmp uc($b)} @fileList]
60+ );
61+ # Restore current directory
62+ chdir("../..");
63+ # Test ToC
64+ ok($toc->format(), <<EOT);
65+
66+<!-- Table of Contents generated by Perl - HTML::Toc -->
67+<ul>
68+ <li><a href=./index.htm#>Main</a>
69+ <ul>
70+ <li><a href=./SubDir1/index.htm#>Sub1</a>
71+ <ul>
72+ <li><a href=./SubDir1/SubSubDir1/index.htm#>SubSub1</a>
73+ </ul>
74+ <li><a href=./SubDir2/index.htm#>Sub2</a>
75+ <ul>
76+ <li><a href=./SubDir2/SubSubDir1/index.htm#>SubSub1</a>
77+ <li><a href=./SubDir2/SubSubDir2/index.htm#>SubSub2</a>
78+ </ul>
79+ <li><a href=./SubDir3/index.htm#>Sub3</a>
80+ </ul>
81+</ul>
82+<!-- End of generated Table of Contents -->
83+EOT
84+} # TestSiteMap()
85+
86+
87+#--- WantedSiteMap() ----------------------------------------------------------
88+# function: 'Wanted' function, used by File::Find of 'TestSiteMap()'.
89+
90+sub WantedSiteMap {
91+ # Add file to 'fileList' if extension matches '.htm'
92+ push (@fileList, $File::Find::name) if (m/\.htm$/);
93+} # WantedSiteMap()
94+
95+
96+ # Test site map
97+TestSiteMap();
examples/includes/HTML-Toc-0.91/t/update.t+114−0
@@ -0,0 +1,114 @@
1+#--- update.t -----------------------------------------------------------------
2+# function: Test ToC updating.
3+
4+use strict;
5+use Test;
6+
7+BEGIN { plan tests => 6; }
8+
9+use HTML::Toc;
10+use HTML::TocUpdator;
11+
12+my ($output, $output2, $content, $filename);
13+my $toc = HTML::Toc->new;
14+my $tocUpdator = HTML::TocUpdator->new;
15+
16+$toc->setOptions({
17+ 'doLinkToToken' => 1,
18+ 'doNumberToken' => 1,
19+ 'levelIndent' => 0,
20+ 'insertionPoint' => 'before <h1>',
21+ 'header' => '',
22+ 'footer' => '',
23+});
24+
25+
26+BEGIN {
27+ # Create test file
28+ $filename = "file$$.htm";
29+ die "$filename is already there" if -e $filename;
30+ open(FILE, ">$filename") || die "Can't create $filename: $!";
31+ print FILE <<'EOT'; close(FILE);
32+<h1>Header</h1>
33+EOT
34+}
35+
36+
37+END {
38+ # Remove test file
39+ unlink($filename) or warn "Can't unlink $filename: $!";
40+}
41+
42+
43+#--- 1. update ----------------------------------------------------------------
44+
45+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
46+ok("$output\n", <<'EOT');
47+<!-- #BeginToc --><ul>
48+<li><a href=#h-1>Header</a>
49+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
50+EOT
51+
52+#--- 2. updateFile ------------------------------------------------------------
53+
54+$tocUpdator->updateFile($toc, $filename, {'output' => \$output});
55+ open(FILE, ">a.out1") || die "Can't create a.out1: $!";
56+ print FILE $output; close(FILE);
57+$output2 = <<'EOT';
58+<!-- #BeginToc --><ul>
59+<li><a href=#h-1>Header</a>
60+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
61+EOT
62+ open(FILE, ">a.out2") || die "Can't create a.out2: $!";
63+ print FILE $output2; close(FILE);
64+ok($output, $output2);
65+
66+
67+#--- 3. insert ----------------------------------------------------------------
68+
69+$tocUpdator->insert($toc, "<h1>Header</h1>", {'output' => \$output});
70+ok("$output\n", <<'EOT');
71+<!-- #BeginToc --><ul>
72+<li><a href=#h-1>Header</a>
73+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
74+EOT
75+
76+#--- 4. insertIntoFile --------------------------------------------------------
77+
78+$tocUpdator->insertIntoFile($toc, $filename, {'output' => \$output});
79+ok($output, <<'EOT');
80+<!-- #BeginToc --><ul>
81+<li><a href=#h-1>Header</a>
82+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
83+EOT
84+
85+
86+#--- 5. update twice ----------------------------------------------------------
87+
88+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
89+$tocUpdator->update($toc, $output, {'output' => \$output2});
90+ok("$output\n", <<'EOT');
91+<!-- #BeginToc --><ul>
92+<li><a href=#h-1>Header</a>
93+</ul><!-- #EndToc --><!-- #BeginTocAnchorNameBegin --><a name=h-1><!-- #EndTocAnchorNameBegin --><h1><!-- #BeginTocNumber -->1 &nbsp;<!-- #EndTocNumber -->Header</h1><!-- #BeginTocAnchorNameEnd --></a><!-- #EndTocAnchorNameEnd -->
94+EOT
95+
96+
97+#--- 6. tokens update begin & end ---------------------------------------------
98+
99+$toc->setOptions({
100+ 'tokenUpdateBeginOfAnchorNameBegin' => '<tocAnchorNameBegin>',
101+ 'tokenUpdateEndOfAnchorNameBegin' => '</tocAnchorNameBegin>',
102+ 'tokenUpdateBeginOfAnchorNameEnd' => '<tocAnchorNameEnd>',
103+ 'tokenUpdateEndOfAnchorNameEnd' => '</tocAnchorNameEnd>',
104+ 'tokenUpdateBeginNumber' => '<tocNumber>',
105+ 'tokenUpdateEndNumber' => '</tocNumber>',
106+ 'tokenUpdateBeginToc' => '<toc>',
107+ 'tokenUpdateEndToc', => '</toc>'
108+});
109+$tocUpdator->update($toc, "<h1>Header</h1>", {'output' => \$output});
110+ok("$output\n", <<'EOT');
111+<toc><ul>
112+<li><a href=#h-1>Header</a>
113+</ul></toc><tocAnchorNameBegin><a name=h-1></tocAnchorNameBegin><h1><tocNumber>1 &nbsp;</tocNumber>Header</h1><tocAnchorNameEnd></a></tocAnchorNameEnd>
114+EOT
examples/includes/PHP-Markdown-Extra-1.2.3/License.text+36−0
@@ -0,0 +1,36 @@
1+PHP Markdown & Extra
2+Copyright (c) 2004-2008 Michel Fortin
3+<http://www.michelf.com/>
4+All rights reserved.
5+
6+Based on Markdown
7+Copyright (c) 2003-2006 John Gruber
8+<http://daringfireball.net/>
9+All rights reserved.
10+
11+Redistribution and use in source and binary forms, with or without
12+modification, are permitted provided that the following conditions are
13+met:
14+
15+* Redistributions of source code must retain the above copyright notice,
16+ this list of conditions and the following disclaimer.
17+
18+* Redistributions in binary form must reproduce the above copyright
19+ notice, this list of conditions and the following disclaimer in the
20+ documentation and/or other materials provided with the distribution.
21+
22+* Neither the name "Markdown" nor the names of its contributors may
23+ be used to endorse or promote products derived from this software
24+ without specific prior written permission.
25+
26+This software is provided by the copyright holders and contributors "as
27+is" and any express or implied warranties, including, but not limited
28+to, the implied warranties of merchantability and fitness for a
29+particular purpose are disclaimed. In no event shall the copyright owner
30+or contributors be liable for any direct, indirect, incidental, special,
31+exemplary, or consequential damages (including, but not limited to,
32+procurement of substitute goods or services; loss of use, data, or
33+profits; or business interruption) however caused and on any theory of
34+liability, whether in contract, strict liability, or tort (including
35+negligence or otherwise) arising in any way out of the use of this
36+software, even if advised of the possibility of such damage.
examples/includes/PHP-Markdown-Extra-1.2.3/PHP Markdown Extra Readme.text+731−0
@@ -0,0 +1,731 @@
1+PHP Markdown Extra
2+==================
3+
4+Version 1.2.3 - Wed 31 Dec 2008
5+
6+by Michel Fortin
7+<http://www.michelf.com/>
8+
9+based on Markdown by John Gruber
10+<http://daringfireball.net/>
11+
12+
13+Introduction
14+------------
15+
16+This is a special version of PHP Markdown with extra features. See
17+<http://www.michelf.com/projects/php-markdown/extra/> for details.
18+
19+Markdown is a text-to-HTML conversion tool for web writers. Markdown
20+allows you to write using an easy-to-read, easy-to-write plain text
21+format, then convert it to structurally valid XHTML (or HTML).
22+
23+"Markdown" is two things: a plain text markup syntax, and a software
24+tool, written in Perl, that converts the plain text markup to HTML.
25+PHP Markdown is a port to PHP of the original Markdown program by
26+John Gruber.
27+
28+PHP Markdown can work as a plug-in for WordPress and bBlog, as a
29+modifier for the Smarty templating engine, or as a remplacement for
30+textile formatting in any software that support textile.
31+
32+Full documentation of Markdown's syntax is available on John's
33+Markdown page: <http://daringfireball.net/projects/markdown/>
34+
35+
36+Installation and Requirement
37+----------------------------
38+
39+PHP Markdown requires PHP version 4.0.5 or later.
40+
41+
42+### WordPress ###
43+
44+PHP Markdown works with [WordPress][wp], version 1.2 or later.
45+
46+ [wp]: http://wordpress.org/
47+
48+1. To use PHP Markdown with WordPress, place the "makrdown.php" file
49+ in the "plugins" folder. This folder is located inside
50+ "wp-content" at the root of your site:
51+
52+ (site home)/wp-content/plugins/
53+
54+2. Activate the plugin with the administrative interface of
55+ WordPress. In the "Plugins" section you will now find Markdown.
56+ To activate the plugin, click on the "Activate" button on the
57+ same line than Markdown. Your entries will now be formatted by
58+ PHP Markdown.
59+
60+3. To post Markdown content, you'll first have to disable the
61+ "visual" editor in the User section of WordPress.
62+
63+You can configure PHP Markdown to not apply to the comments on your
64+WordPress weblog. See the "Configuration" section below.
65+
66+It is not possible at this time to apply a different set of
67+filters to different entries. All your entries will be formated by
68+PHP Markdown. This is a limitation of WordPress. If your old entries
69+are written in HTML (as opposed to another formatting syntax, like
70+Textile), they'll probably stay fine after installing Markdown.
71+
72+
73+### bBlog ###
74+
75+PHP Markdown also works with [bBlog][bb].
76+
77+ [bb]: http://www.bblog.com/
78+
79+To use PHP Markdown with bBlog, rename "markdown.php" to
80+"modifier.markdown.php" and place the file in the "bBlog_plugins"
81+folder. This folder is located inside the "bblog" directory of
82+your site, like this:
83+
84+ (site home)/bblog/bBlog_plugins/modifier.markdown.php
85+
86+Select "Markdown" as the "Entry Modifier" when you post a new
87+entry. This setting will only apply to the entry you are editing.
88+
89+
90+### Replacing Textile in TextPattern ###
91+
92+[TextPattern][tp] use [Textile][tx] to format your text. You can
93+replace Textile by Markdown in TextPattern without having to change
94+any code by using the *Texitle Compatibility Mode*. This may work
95+with other software that expect Textile too.
96+
97+ [tx]: http://www.textism.com/tools/textile/
98+ [tp]: http://www.textpattern.com/
99+
100+1. Rename the "markdown.php" file to "classTextile.php". This will
101+ make PHP Markdown behave as if it was the actual Textile parser.
102+
103+2. Replace the "classTextile.php" file TextPattern installed in your
104+ web directory. It can be found in the "lib" directory:
105+
106+ (site home)/textpattern/lib/
107+
108+Contrary to Textile, Markdown does not convert quotes to curly ones
109+and does not convert multiple hyphens (`--` and `---`) into en- and
110+em-dashes. If you use PHP Markdown in Textile Compatibility Mode, you
111+can solve this problem by installing the "smartypants.php" file from
112+[PHP SmartyPants][psp] beside the "classTextile.php" file. The Textile
113+Compatibility Mode function will use SmartyPants automatically without
114+further modification.
115+
116+ [psp]: http://www.michelf.com/projects/php-smartypants/
117+
118+
119+### In Your Own Programs ###
120+
121+You can use PHP Markdown easily in your current PHP program. Simply
122+include the file and then call the Markdown function on the text you
123+want to convert:
124+
125+ include_once "markdown.php";
126+ $my_html = Markdown($my_text);
127+
128+If you wish to use PHP Markdown with another text filter function
129+built to parse HTML, you should filter the text *after* the Markdown
130+function call. This is an example with [PHP SmartyPants][psp]:
131+
132+ $my_html = SmartyPants(Markdown($my_text));
133+
134+
135+### With Smarty ###
136+
137+If your program use the [Smarty][sm] template engine, PHP Markdown
138+can now be used as a modifier for your templates. Rename "markdown.php"
139+to "modifier.markdown.php" and put it in your smarty plugins folder.
140+
141+ [sm]: http://smarty.php.net/
142+
143+If you are using MovableType 3.1 or later, the Smarty plugin folder is
144+located at `(MT CGI root)/php/extlib/smarty/plugins`. This will allow
145+Markdown to work on dynamic pages.
146+
147+
148+### Updating Markdown in Other Programs ###
149+
150+Many web applications now ship with PHP Markdown, or have plugins to
151+perform the conversion to HTML. You can update PHP Markdown -- or
152+replace it with PHP Markdown Extra -- in many of these programs by
153+swapping the old "markdown.php" file for the new one.
154+
155+Here is a short non-exhaustive list of some programs and where they
156+hide the "markdown.php" file.
157+
158+| Program | Path to Markdown
159+| ------- | ----------------
160+| [Pivot][] | `(site home)/pivot/includes/markdown/`
161+
162+If you're unsure if you can do this with your application, ask the
163+developer, or wait for the developer to update his application or
164+plugin with the new version of PHP Markdown.
165+
166+ [Pivot]: http://pivotlog.net/
167+
168+
169+Configuration
170+-------------
171+
172+By default, PHP Markdown produces XHTML output for tags with empty
173+elements. E.g.:
174+
175+ <br />
176+
177+Markdown can be configured to produce HTML-style tags; e.g.:
178+
179+ <br>
180+
181+To do this, you must edit the "MARKDOWN_EMPTY_ELEMENT_SUFFIX"
182+definition below the "Global default settings" header at the start of
183+the "markdown.php" file.
184+
185+
186+### WordPress-Specific Settings ###
187+
188+By default, the Markdown plugin applies to both posts and comments on
189+your WordPress weblog. To deactivate one or the other, edit the
190+`MARKDOWN_WP_POSTS` or `MARKDOWN_WP_COMMENTS` definitions under the
191+"WordPress settings" header at the start of the "markdown.php" file.
192+
193+
194+Bugs
195+----
196+
197+To file bug reports please send email to:
198+<michel.fortin@michelf.com>
199+
200+Please include with your report: (1) the example input; (2) the output you
201+expected; (3) the output PHP Markdown actually produced.
202+
203+
204+Version History
205+---------------
206+
207+Extra 1.2.3 (31 Dec 2008):
208+
209+* In WordPress pages featuring more than one post, footnote id prefixes are
210+ now automatically applied with the current post ID to avoid clashes
211+ between footnotes belonging to different posts.
212+
213+* Fix for a bug introduced in Extra 1.2 where block-level HTML tags where
214+ not detected correctly, thus the addition of erroneous `<p>` tags and
215+ interpretation of their content as Markdown-formatted instead of
216+ HTML-formatted.
217+
218+
219+Extra 1.2.2 (21 Jun 2008):
220+
221+* Fixed a problem where abbreviation definitions, footnote
222+ definitions and link references were stripped inside
223+ fenced code blocks.
224+
225+* Fixed a bug where characters such as `"` in abbreviation
226+ definitions weren't properly encoded to HTML entities.
227+
228+* Fixed a bug where double quotes `"` were not correctly encoded
229+ as HTML entities when used inside a footnote reference id.
230+
231+
232+1.0.1m (21 Jun 2008):
233+
234+* Lists can now have empty items.
235+
236+* Rewrote the emphasis and strong emphasis parser to fix some issues
237+ with odly placed and overlong markers.
238+
239+
240+Extra 1.2.1 (27 May 2008):
241+
242+* Fixed a problem where Markdown headers and horizontal rules were
243+ transformed into their HTML equivalent inside fenced code blocks.
244+
245+
246+Extra 1.2 (11 May 2008):
247+
248+* Added fenced code block syntax which don't require indentation
249+ and can start and end with blank lines. A fenced code block
250+ starts with a line of consecutive tilde (~) and ends on the
251+ next line with the same number of consecutive tilde. Here's an
252+ example:
253+
254+ ~~~~~~~~~~~~
255+ Hello World!
256+ ~~~~~~~~~~~~
257+
258+* Rewrote parts of the HTML block parser to better accomodate
259+ fenced code blocks.
260+
261+* Footnotes may now be referenced from within another footnote.
262+
263+* Added programatically-settable parser property `predef_attr` for
264+ predefined attribute definitions.
265+
266+* Fixed an issue where an indented code block preceded by a blank
267+ line containing some other whitespace would confuse the HTML
268+ block parser into creating an HTML block when it should have
269+ been code.
270+
271+
272+1.0.1l (11 May 2008):
273+
274+* Now removing the UTF-8 BOM at the start of a document, if present.
275+
276+* Now accepting capitalized URI schemes (such as HTTP:) in automatic
277+ links, such as `<HTTP://EXAMPLE.COM/>`.
278+
279+* Fixed a problem where `<hr@example.com>` was seen as a horizontal
280+ rule instead of an automatic link.
281+
282+* Fixed an issue where some characters in Markdown-generated HTML
283+ attributes weren't properly escaped with entities.
284+
285+* Fix for code blocks as first element of a list item. Previously,
286+ this didn't create any code block for item 2:
287+
288+ * Item 1 (regular paragraph)
289+
290+ * Item 2 (code block)
291+
292+* A code block starting on the second line of a document wasn't seen
293+ as a code block. This has been fixed.
294+
295+* Added programatically-settable parser properties `predef_urls` and
296+ `predef_titles` for predefined URLs and titles for reference-style
297+ links. To use this, your PHP code must call the parser this way:
298+
299+ $parser = new Markdwon_Parser;
300+ $parser->predef_urls = array('linkref' => 'http://example.com');
301+ $html = $parser->transform($text);
302+
303+ You can then use the URL as a normal link reference:
304+
305+ [my link][linkref]
306+ [my link][linkRef]
307+
308+ Reference names in the parser properties *must* be lowercase.
309+ Reference names in the Markdown source may have any case.
310+
311+* Added `setup` and `teardown` methods which can be used by subclassers
312+ as hook points to arrange the state of some parser variables before and
313+ after parsing.
314+
315+
316+Extra 1.1.7 (26 Sep 2007):
317+
318+1.0.1k (26 Sep 2007):
319+
320+* Fixed a problem introduced in 1.0.1i where three or more identical
321+ uppercase letters, as well as a few other symbols, would trigger
322+ a horizontal line.
323+
324+
325+Extra 1.1.6 (4 Sep 2007):
326+
327+1.0.1j (4 Sep 2007):
328+
329+* Fixed a problem introduced in 1.0.1i where the closing `code` and
330+ `pre` tags at the end of a code block were appearing in the wrong
331+ order.
332+
333+* Overriding configuration settings by defining constants from an
334+ external before markdown.php is included is now possible without
335+ producing a PHP warning.
336+
337+
338+Extra 1.1.5 (31 Aug 2007):
339+
340+1.0.1i (31 Aug 2007):
341+
342+* Fixed a problem where an escaped backslash before a code span
343+ would prevent the code span from being created. This should now
344+ work as expected:
345+
346+ Litteral backslash: \\`code span`
347+
348+* Overall speed improvements, especially with long documents.
349+
350+
351+Extra 1.1.4 (3 Aug 2007):
352+
353+1.0.1h (3 Aug 2007):
354+
355+* Added two properties (`no_markup` and `no_entities`) to the parser
356+ allowing HTML tags and entities to be disabled.
357+
358+* Fix for a problem introduced in 1.0.1g where posting comments in
359+ WordPress would trigger PHP warnings and cause some markup to be
360+ incorrectly filtered by the kses filter in WordPress.
361+
362+
363+Extra 1.1.3 (3 Jul 2007):
364+
365+* Fixed a performance problem when parsing some invalid HTML as an HTML
366+ block which was resulting in too much recusion and a segmentation fault
367+ for long documents.
368+
369+* The markdown="" attribute now accepts unquoted values.
370+
371+* Fixed an issue where underscore-emphasis didn't work when applied on the
372+ first or the last word of an element having the markdown="1" or
373+ markdown="span" attribute set unless there was some surrounding whitespace.
374+ This didn't work:
375+
376+ <p markdown="1">_Hello_ _world_</p>
377+
378+ Now it does produce emphasis as expected.
379+
380+* Fixed an issue preventing footnotes from working when the parser's
381+ footnote id prefix variable (fn_id_prefix) is not empty.
382+
383+* Fixed a performance problem where the regular expression for strong
384+ emphasis introduced in version 1.1 could sometime be long to process,
385+ give slightly wrong results, and in some circumstances could remove
386+ entirely the content for a whole paragraph.
387+
388+* Fixed an issue were abbreviations tags could be incorrectly added
389+ inside URLs and title of links.
390+
391+* Placing footnote markers inside a link, resulting in two nested links, is
392+ no longer allowed.
393+
394+
395+1.0.1g (3 Jul 2007):
396+
397+* Fix for PHP 5 compiled without the mbstring module. Previous fix to
398+ calculate the length of UTF-8 strings in `detab` when `mb_strlen` is
399+ not available was only working with PHP 4.
400+
401+* Fixed a problem with WordPress 2.x where full-content posts in RSS feeds
402+ were not processed correctly by Markdown.
403+
404+* Now supports URLs containing literal parentheses for inline links
405+ and images, such as:
406+
407+ [WIMP](http://en.wikipedia.org/wiki/WIMP_(computing))
408+
409+ Such parentheses may be arbitrarily nested, but must be
410+ balanced. Unbalenced parentheses are allowed however when the URL
411+ when escaped or when the URL is enclosed in angle brakets `<>`.
412+
413+* Fixed a performance problem where the regular expression for strong
414+ emphasis introduced in version 1.0.1d could sometime be long to process,
415+ give slightly wrong results, and in some circumstances could remove
416+ entirely the content for a whole paragraph.
417+
418+* Some change in version 1.0.1d made possible the incorrect nesting of
419+ anchors within each other. This is now fixed.
420+
421+* Fixed a rare issue where certain MD5 hashes in the content could
422+ be changed to their corresponding text. For instance, this:
423+
424+ The MD5 value for "+" is "26b17225b626fb9238849fd60eabdf60".
425+
426+ was incorrectly changed to this in previous versions of PHP Markdown:
427+
428+ <p>The MD5 value for "+" is "+".</p>
429+
430+* Now convert escaped characters to their numeric character
431+ references equivalent.
432+
433+ This fix an integration issue with SmartyPants and backslash escapes.
434+ Since Markdown and SmartyPants have some escapable characters in common,
435+ it was sometime necessary to escape them twice. Previously, two
436+ backslashes were sometime required to prevent Markdown from "eating" the
437+ backslash before SmartyPants sees it:
438+
439+ Here are two hyphens: \\--
440+
441+ Now, only one backslash will do:
442+
443+ Here are two hyphens: \--
444+
445+
446+Extra 1.1.2 (7 Feb 2007)
447+
448+* Fixed an issue where headers preceded too closely by a paragraph
449+ (with no blank line separating them) where put inside the paragraph.
450+
451+* Added the missing TextileRestricted method that was added to regular
452+ PHP Markdown since 1.0.1d but which I forgot to add to Extra.
453+
454+
455+1.0.1f (7 Feb 2007):
456+
457+* Fixed an issue with WordPress where manually-entered excerpts, but
458+ not the auto-generated ones, would contain nested paragraphs.
459+
460+* Fixed an issue introduced in 1.0.1d where headers and blockquotes
461+ preceded too closely by a paragraph (not separated by a blank line)
462+ where incorrectly put inside the paragraph.
463+
464+* Fixed an issue introduced in 1.0.1d in the tokenizeHTML method where
465+ two consecutive code spans would be merged into one when together they
466+ form a valid tag in a multiline paragraph.
467+
468+* Fixed an long-prevailing issue where blank lines in code blocks would
469+ be doubled when the code block is in a list item.
470+
471+ This was due to the list processing functions relying on artificially
472+ doubled blank lines to correctly determine when list items should
473+ contain block-level content. The list item processing model was thus
474+ changed to avoid the need for double blank lines.
475+
476+* Fixed an issue with `<% asp-style %>` instructions used as inline
477+ content where the opening `<` was encoded as `&lt;`.
478+
479+* Fixed a parse error occuring when PHP is configured to accept
480+ ASP-style delimiters as boundaries for PHP scripts.
481+
482+* Fixed a bug introduced in 1.0.1d where underscores in automatic links
483+ got swapped with emphasis tags.
484+
485+
486+Extra 1.1.1 (28 Dec 2006)
487+
488+* Fixed a problem where whitespace at the end of the line of an atx-style
489+ header would cause tailing `#` to appear as part of the header's content.
490+ This was caused by a small error in the regex that handles the definition
491+ for the id attribute in PHP Markdown Extra.
492+
493+* Fixed a problem where empty abbreviations definitions would eat the
494+ following line as its definition.
495+
496+* Fixed an issue with calling the Markdown parser repetitivly with text
497+ containing footnotes. The footnote hashes were not reinitialized properly.
498+
499+
500+1.0.1e (28 Dec 2006)
501+
502+* Added support for internationalized domain names for email addresses in
503+ automatic link. Improved the speed at which email addresses are converted
504+ to entities. Thanks to Milian Wolff for his optimisations.
505+
506+* Made deterministic the conversion to entities of email addresses in
507+ automatic links. This means that a given email address will always be
508+ encoded the same way.
509+
510+* PHP Markdown will now use its own function to calculate the length of an
511+ UTF-8 string in `detab` when `mb_strlen` is not available instead of
512+ giving a fatal error.
513+
514+
515+Extra 1.1 (1 Dec 2006)
516+
517+* Added a syntax for footnotes.
518+
519+* Added an experimental syntax to define abbreviations.
520+
521+
522+1.0.1d (1 Dec 2006)
523+
524+* Fixed a bug where inline images always had an empty title attribute. The
525+ title attribute is now present only when explicitly defined.
526+
527+* Link references definitions can now have an empty title, previously if the
528+ title was defined but left empty the link definition was ignored. This can
529+ be useful if you want an empty title attribute in images to hide the
530+ tooltip in Internet Explorer.
531+
532+* Made `detab` aware of UTF-8 characters. UTF-8 multi-byte sequences are now
533+ correctly mapped to one character instead of the number of bytes.
534+
535+* Fixed a small bug with WordPress where WordPress' default filter `wpautop`
536+ was not properly deactivated on comment text, resulting in hard line breaks
537+ where Markdown do not prescribes them.
538+
539+* Added a `TextileRestrited` method to the textile compatibility mode. There
540+ is no restriction however, as Markdown does not have a restricted mode at
541+ this point. This should make PHP Markdown work again in the latest
542+ versions of TextPattern.
543+
544+* Converted PHP Markdown to a object-oriented design.
545+
546+* Changed span and block gamut methods so that they loop over a
547+ customizable list of methods. This makes subclassing the parser a more
548+ interesting option for creating syntax extensions.
549+
550+* Also added a "document" gamut loop which can be used to hook document-level
551+ methods (like for striping link definitions).
552+
553+* Changed all methods which were inserting HTML code so that they now return
554+ a hashed representation of the code. New methods `hashSpan` and `hashBlock`
555+ are used to hash respectivly span- and block-level generated content. This
556+ has a couple of significant effects:
557+
558+ 1. It prevents invalid nesting of Markdown-generated elements which
559+ could occur occuring with constructs like `*something [link*][1]`.
560+ 2. It prevents problems occuring with deeply nested lists on which
561+ paragraphs were ill-formed.
562+ 3. It removes the need to call `hashHTMLBlocks` twice during the the
563+ block gamut.
564+
565+ Hashes are turned back to HTML prior output.
566+
567+* Made the block-level HTML parser smarter using a specially-crafted regular
568+ expression capable of handling nested tags.
569+
570+* Solved backtick issues in tag attributes by rewriting the HTML tokenizer to
571+ be aware of code spans. All these lines should work correctly now:
572+
573+ <span attr='`ticks`'>bar</span>
574+ <span attr='``double ticks``'>bar</span>
575+ `<test a="` content of attribute `">`
576+
577+* Changed the parsing of HTML comments to match simply from `<!--` to `-->`
578+ instead using of the more complicated SGML-style rule with paired `--`.
579+ This is how most browsers parse comments and how XML defines them too.
580+
581+* `<address>` has been added to the list of block-level elements and is now
582+ treated as an HTML block instead of being wrapped within paragraph tags.
583+
584+* Now only trim trailing newlines from code blocks, instead of trimming
585+ all trailing whitespace characters.
586+
587+* Fixed bug where this:
588+
589+ [text](http://m.com "title" )
590+
591+ wasn't working as expected, because the parser wasn't allowing for spaces
592+ before the closing paren.
593+
594+* Filthy hack to support markdown='1' in div tags.
595+
596+* _DoAutoLinks() now supports the 'dict://' URL scheme.
597+
598+* PHP- and ASP-style processor instructions are now protected as
599+ raw HTML blocks.
600+
601+ <? ... ?>
602+ <% ... %>
603+
604+* Fix for escaped backticks still triggering code spans:
605+
606+ There are two raw backticks here: \` and here: \`, not a code span
607+
608+
609+Extra 1.0 - 5 September 2005
610+
611+* Added support for setting the id attributes for headers like this:
612+
613+ Header 1 {#header1}
614+ ========
615+
616+ ## Header 2 ## {#header2}
617+
618+ This only work only for headers for now.
619+
620+* Tables will now work correctly as the first element of a definition
621+ list. For example, this input:
622+
623+ Term
624+
625+ : Header | Header
626+ ------- | -------
627+ Cell | Cell
628+
629+ used to produce no definition list and a table where the first
630+ header was named ": Header". This is now fixed.
631+
632+* Fix for a problem where a paragraph following a table was not
633+ placed between `<p>` tags.
634+
635+
636+Extra 1.0b4 - 1 August 2005
637+
638+* Fixed some issues where whitespace around HTML blocks were trigging
639+ empty paragraph tags.
640+
641+* Fixed an HTML block parsing issue that would cause a block element
642+ following a code span or block with unmatched opening bracket to be
643+ placed inside a paragraph.
644+
645+* Removed some PHP notices that could appear when parsing definition
646+ lists and tables with PHP notice reporting flag set.
647+
648+
649+Extra 1.0b3 - 29 July 2005
650+
651+* Definition lists now require a blank line before each term. Solves
652+ an ambiguity where the last line of lazy-indented definitions could
653+ be mistaken by PHP Markdown as a new term in the list.
654+
655+* Definition lists now support multiple terms per definition.
656+
657+* Some special tags were replaced in the output by their md5 hash
658+ key. Things such as this now work as expected:
659+
660+ ## Header <?php echo $number ?> ##
661+
662+
663+Extra 1.0b2 - 26 July 2005
664+
665+* Definition lists can now take two or more definitions for one term.
666+ This should have been the case before, but a bug prevented this
667+ from working right.
668+
669+* Fixed a problem where single column table with a pipe only at the
670+ end where not parsed as table. Here is such a table:
671+
672+ | header
673+ | ------
674+ | cell
675+
676+* Fixed problems with empty cells in the first column of a table with
677+ no leading pipe, like this one:
678+
679+ header | header
680+ ------ | ------
681+ | cell
682+
683+* Code spans containing pipes did not within a table. This is now
684+ fixed by parsing code spans before splitting rows into cells.
685+
686+* Added the pipe character to the backlash escape character lists.
687+
688+Extra 1.0b1 (25 Jun 2005)
689+
690+* First public release of PHP Markdown Extra.
691+
692+
693+Copyright and License
694+---------------------
695+
696+Copyright (c) 2004-2005 Michel Fortin
697+<http://www.michelf.com/>
698+All rights reserved.
699+
700+Based on Markdown
701+Copyright (c) 2003-2005 John Gruber
702+<http://daringfireball.net/>
703+All rights reserved.
704+
705+Redistribution and use in source and binary forms, with or without
706+modification, are permitted provided that the following conditions are
707+met:
708+
709+* Redistributions of source code must retain the above copyright
710+ notice, this list of conditions and the following disclaimer.
711+
712+* Redistributions in binary form must reproduce the above copyright
713+ notice, this list of conditions and the following disclaimer in the
714+ documentation and/or other materials provided with the
715+ distribution.
716+
717+* Neither the name "Markdown" nor the names of its contributors may
718+ be used to endorse or promote products derived from this software
719+ without specific prior written permission.
720+
721+This software is provided by the copyright holders and contributors "as
722+is" and any express or implied warranties, including, but not limited
723+to, the implied warranties of merchantability and fitness for a
724+particular purpose are disclaimed. In no event shall the copyright owner
725+or contributors be liable for any direct, indirect, incidental, special,
726+exemplary, or consequential damages (including, but not limited to,
727+procurement of substitute goods or services; loss of use, data, or
728+profits; or business interruption) however caused and on any theory of
729+liability, whether in contract, strict liability, or tort (including
730+negligence or otherwise) arising in any way out of the use of this
731+software, even if advised of the possibility of such damage.
examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php+2909−0
@@ -0,0 +1,2909 @@
1+<?php
2+#
3+# Markdown Extra - A text-to-HTML conversion tool for web writers
4+#
5+# PHP Markdown & Extra
6+# Copyright (c) 2004-2008 Michel Fortin
7+# <http://www.michelf.com/projects/php-markdown/>
8+#
9+# Original Markdown
10+# Copyright (c) 2004-2006 John Gruber
11+# <http://daringfireball.net/projects/markdown/>
12+#
13+
14+
15+define( 'MARKDOWN_VERSION', "1.0.1m" ); # Sat 21 Jun 2008
16+define( 'MARKDOWNEXTRA_VERSION', "1.2.3" ); # Wed 31 Dec 2008
17+
18+
19+#
20+# Global default settings:
21+#
22+
23+# Change to ">" for HTML output
24+@define( 'MARKDOWN_EMPTY_ELEMENT_SUFFIX', " />");
25+
26+# Define the width of a tab for code blocks.
27+@define( 'MARKDOWN_TAB_WIDTH', 4 );
28+
29+# Optional title attribute for footnote links and backlinks.
30+@define( 'MARKDOWN_FN_LINK_TITLE', "" );
31+@define( 'MARKDOWN_FN_BACKLINK_TITLE', "" );
32+
33+# Optional class attribute for footnote links and backlinks.
34+@define( 'MARKDOWN_FN_LINK_CLASS', "" );
35+@define( 'MARKDOWN_FN_BACKLINK_CLASS', "" );
36+
37+
38+#
39+# WordPress settings:
40+#
41+
42+# Change to false to remove Markdown from posts and/or comments.
43+@define( 'MARKDOWN_WP_POSTS', true );
44+@define( 'MARKDOWN_WP_COMMENTS', true );
45+
46+
47+
48+### Standard Function Interface ###
49+
50+@define( 'MARKDOWN_PARSER_CLASS', 'MarkdownExtra_Parser' );
51+
52+function Markdown($text) {
53+#
54+# Initialize the parser and return the result of its transform method.
55+#
56+ # Setup static parser variable.
57+ static $parser;
58+ if (!isset($parser)) {
59+ $parser_class = MARKDOWN_PARSER_CLASS;
60+ $parser = new $parser_class;
61+ }
62+
63+ # Transform text using parser.
64+ return $parser->transform($text);
65+}
66+
67+
68+### WordPress Plugin Interface ###
69+
70+/*
71+Plugin Name: Markdown Extra
72+Plugin URI: http://www.michelf.com/projects/php-markdown/
73+Description: <a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>
74+Version: 1.2.2
75+Author: Michel Fortin
76+Author URI: http://www.michelf.com/
77+*/
78+
79+if (isset($wp_version)) {
80+ # More details about how it works here:
81+ # <http://www.michelf.com/weblog/2005/wordpress-text-flow-vs-markdown/>
82+
83+ # Post content and excerpts
84+ # - Remove WordPress paragraph generator.
85+ # - Run Markdown on excerpt, then remove all tags.
86+ # - Add paragraph tag around the excerpt, but remove it for the excerpt rss.
87+ if (MARKDOWN_WP_POSTS) {
88+ remove_filter('the_content', 'wpautop');
89+ remove_filter('the_content_rss', 'wpautop');
90+ remove_filter('the_excerpt', 'wpautop');
91+ add_filter('the_content', 'mdwp_MarkdownPost', 6);
92+ add_filter('the_content_rss', 'mdwp_MarkdownPost', 6);
93+ add_filter('get_the_excerpt', 'mdwp_MarkdownPost', 6);
94+ add_filter('get_the_excerpt', 'trim', 7);
95+ add_filter('the_excerpt', 'mdwp_add_p');
96+ add_filter('the_excerpt_rss', 'mdwp_strip_p');
97+
98+ remove_filter('content_save_pre', 'balanceTags', 50);
99+ remove_filter('excerpt_save_pre', 'balanceTags', 50);
100+ add_filter('the_content', 'balanceTags', 50);
101+ add_filter('get_the_excerpt', 'balanceTags', 9);
102+ }
103+
104+ # Add a footnote id prefix to posts when inside a loop.
105+ function mdwp_MarkdownPost($text) {
106+ static $parser;
107+ if (!$parser) {
108+ $parser_class = MARKDOWN_PARSER_CLASS;
109+ $parser = new $parser_class;
110+ }
111+ if (is_single() || is_page() || is_feed()) {
112+ $parser->fn_id_prefix = "";
113+ } else {
114+ $parser->fn_id_prefix = get_the_ID() . ".";
115+ }
116+ return $parser->transform($text);
117+ }
118+
119+ # Comments
120+ # - Remove WordPress paragraph generator.
121+ # - Remove WordPress auto-link generator.
122+ # - Scramble important tags before passing them to the kses filter.
123+ # - Run Markdown on excerpt then remove paragraph tags.
124+ if (MARKDOWN_WP_COMMENTS) {
125+ remove_filter('comment_text', 'wpautop', 30);
126+ remove_filter('comment_text', 'make_clickable');
127+ add_filter('pre_comment_content', 'Markdown', 6);
128+ add_filter('pre_comment_content', 'mdwp_hide_tags', 8);
129+ add_filter('pre_comment_content', 'mdwp_show_tags', 12);
130+ add_filter('get_comment_text', 'Markdown', 6);
131+ add_filter('get_comment_excerpt', 'Markdown', 6);
132+ add_filter('get_comment_excerpt', 'mdwp_strip_p', 7);
133+
134+ global $mdwp_hidden_tags, $mdwp_placeholders;
135+ $mdwp_hidden_tags = explode(' ',
136+ '<p> </p> <pre> </pre> <ol> </ol> <ul> </ul> <li> </li>');
137+ $mdwp_placeholders = explode(' ', str_rot13(
138+ 'pEj07ZbbBZ U1kqgh4w4p pre2zmeN6K QTi31t9pre ol0MP1jzJR '.
139+ 'ML5IjmbRol ulANi1NsGY J7zRLJqPul liA8ctl16T K9nhooUHli'));
140+ }
141+
142+ function mdwp_add_p($text) {
143+ if (!preg_match('{^$|^<(p|ul|ol|dl|pre|blockquote)>}i', $text)) {
144+ $text = '<p>'.$text.'</p>';
145+ $text = preg_replace('{\n{2,}}', "</p>\n\n<p>", $text);
146+ }
147+ return $text;
148+ }
149+
150+ function mdwp_strip_p($t) { return preg_replace('{</?p>}i', '', $t); }
151+
152+ function mdwp_hide_tags($text) {
153+ global $mdwp_hidden_tags, $mdwp_placeholders;
154+ return str_replace($mdwp_hidden_tags, $mdwp_placeholders, $text);
155+ }
156+ function mdwp_show_tags($text) {
157+ global $mdwp_hidden_tags, $mdwp_placeholders;
158+ return str_replace($mdwp_placeholders, $mdwp_hidden_tags, $text);
159+ }
160+}
161+
162+
163+### bBlog Plugin Info ###
164+
165+function identify_modifier_markdown() {
166+ return array(
167+ 'name' => 'markdown',
168+ 'type' => 'modifier',
169+ 'nicename' => 'PHP Markdown Extra',
170+ 'description' => 'A text-to-HTML conversion tool for web writers',
171+ 'authors' => 'Michel Fortin and John Gruber',
172+ 'licence' => 'GPL',
173+ 'version' => MARKDOWNEXTRA_VERSION,
174+ 'help' => '<a href="http://daringfireball.net/projects/markdown/syntax">Markdown syntax</a> allows you to write using an easy-to-read, easy-to-write plain text format. Based on the original Perl version by <a href="http://daringfireball.net/">John Gruber</a>. <a href="http://www.michelf.com/projects/php-markdown/">More...</a>',
175+ );
176+}
177+
178+
179+### Smarty Modifier Interface ###
180+
181+function smarty_modifier_markdown($text) {
182+ return Markdown($text);
183+}
184+
185+
186+### Textile Compatibility Mode ###
187+
188+# Rename this file to "classTextile.php" and it can replace Textile everywhere.
189+
190+if (strcasecmp(substr(__FILE__, -16), "classTextile.php") == 0) {
191+ # Try to include PHP SmartyPants. Should be in the same directory.
192+ @include_once 'smartypants.php';
193+ # Fake Textile class. It calls Markdown instead.
194+ class Textile {
195+ function TextileThis($text, $lite='', $encode='') {
196+ if ($lite == '' && $encode == '') $text = Markdown($text);
197+ if (function_exists('SmartyPants')) $text = SmartyPants($text);
198+ return $text;
199+ }
200+ # Fake restricted version: restrictions are not supported for now.
201+ function TextileRestricted($text, $lite='', $noimage='') {
202+ return $this->TextileThis($text, $lite);
203+ }
204+ # Workaround to ensure compatibility with TextPattern 4.0.3.
205+ function blockLite($text) { return $text; }
206+ }
207+}
208+
209+
210+
211+#
212+# Markdown Parser Class
213+#
214+
215+class Markdown_Parser {
216+
217+ # Regex to match balanced [brackets].
218+ # Needed to insert a maximum bracked depth while converting to PHP.
219+ var $nested_brackets_depth = 6;
220+ var $nested_brackets_re;
221+
222+ var $nested_url_parenthesis_depth = 4;
223+ var $nested_url_parenthesis_re;
224+
225+ # Table of hash values for escaped characters:
226+ var $escape_chars = '\`*_{}[]()>#+-.!';
227+ var $escape_chars_re;
228+
229+ # Change to ">" for HTML output.
230+ var $empty_element_suffix = MARKDOWN_EMPTY_ELEMENT_SUFFIX;
231+ var $tab_width = MARKDOWN_TAB_WIDTH;
232+
233+ # Change to `true` to disallow markup or entities.
234+ var $no_markup = false;
235+ var $no_entities = false;
236+
237+ # Predefined urls and titles for reference links and images.
238+ var $predef_urls = array();
239+ var $predef_titles = array();
240+
241+
242+ function Markdown_Parser() {
243+ #
244+ # Constructor function. Initialize appropriate member variables.
245+ #
246+ $this->_initDetab();
247+ $this->prepareItalicsAndBold();
248+
249+ $this->nested_brackets_re =
250+ str_repeat('(?>[^\[\]]+|\[', $this->nested_brackets_depth).
251+ str_repeat('\])*', $this->nested_brackets_depth);
252+
253+ $this->nested_url_parenthesis_re =
254+ str_repeat('(?>[^()\s]+|\(', $this->nested_url_parenthesis_depth).
255+ str_repeat('(?>\)))*', $this->nested_url_parenthesis_depth);
256+
257+ $this->escape_chars_re = '['.preg_quote($this->escape_chars).']';
258+
259+ # Sort document, block, and span gamut in ascendent priority order.
260+ asort($this->document_gamut);
261+ asort($this->block_gamut);
262+ asort($this->span_gamut);
263+ }
264+
265+
266+ # Internal hashes used during transformation.
267+ var $urls = array();
268+ var $titles = array();
269+ var $html_hashes = array();
270+
271+ # Status flag to avoid invalid nesting.
272+ var $in_anchor = false;
273+
274+
275+ function setup() {
276+ #
277+ # Called before the transformation process starts to setup parser
278+ # states.
279+ #
280+ # Clear global hashes.
281+ $this->urls = $this->predef_urls;
282+ $this->titles = $this->predef_titles;
283+ $this->html_hashes = array();
284+
285+ $in_anchor = false;
286+ }
287+
288+ function teardown() {
289+ #
290+ # Called after the transformation process to clear any variable
291+ # which may be taking up memory unnecessarly.
292+ #
293+ $this->urls = array();
294+ $this->titles = array();
295+ $this->html_hashes = array();
296+ }
297+
298+
299+ function transform($text) {
300+ #
301+ # Main function. Performs some preprocessing on the input text
302+ # and pass it through the document gamut.
303+ #
304+ $this->setup();
305+
306+ # Remove UTF-8 BOM and marker character in input, if present.
307+ $text = preg_replace('{^\xEF\xBB\xBF|\x1A}', '', $text);
308+
309+ # Standardize line endings:
310+ # DOS to Unix and Mac to Unix
311+ $text = preg_replace('{\r\n?}', "\n", $text);
312+
313+ # Make sure $text ends with a couple of newlines:
314+ $text .= "\n\n";
315+
316+ # Convert all tabs to spaces.
317+ $text = $this->detab($text);
318+
319+ # Turn block-level HTML blocks into hash entries
320+ $text = $this->hashHTMLBlocks($text);
321+
322+ # Strip any lines consisting only of spaces and tabs.
323+ # This makes subsequent regexen easier to write, because we can
324+ # match consecutive blank lines with /\n+/ instead of something
325+ # contorted like /[ ]*\n+/ .
326+ $text = preg_replace('/^[ ]+$/m', '', $text);
327+
328+ # Run document gamut methods.
329+ foreach ($this->document_gamut as $method => $priority) {
330+ $text = $this->$method($text);
331+ }
332+
333+ $this->teardown();
334+
335+ return $text . "\n";
336+ }
337+
338+ var $document_gamut = array(
339+ # Strip link definitions, store in hashes.
340+ "stripLinkDefinitions" => 20,
341+
342+ "runBasicBlockGamut" => 30,
343+ );
344+
345+
346+ function stripLinkDefinitions($text) {
347+ #
348+ # Strips link definitions from text, stores the URLs and titles in
349+ # hash references.
350+ #
351+ $less_than_tab = $this->tab_width - 1;
352+
353+ # Link defs are in the form: ^[id]: url "optional title"
354+ $text = preg_replace_callback('{
355+ ^[ ]{0,'.$less_than_tab.'}\[(.+)\][ ]?: # id = $1
356+ [ ]*
357+ \n? # maybe *one* newline
358+ [ ]*
359+ <?(\S+?)>? # url = $2
360+ [ ]*
361+ \n? # maybe one newline
362+ [ ]*
363+ (?:
364+ (?<=\s) # lookbehind for whitespace
365+ ["(]
366+ (.*?) # title = $3
367+ [")]
368+ [ ]*
369+ )? # title is optional
370+ (?:\n+|\Z)
371+ }xm',
372+ array(&$this, '_stripLinkDefinitions_callback'),
373+ $text);
374+ return $text;
375+ }
376+ function _stripLinkDefinitions_callback($matches) {
377+ $link_id = strtolower($matches[1]);
378+ $this->urls[$link_id] = $matches[2];
379+ $this->titles[$link_id] =& $matches[3];
380+ return ''; # String that will replace the block
381+ }
382+
383+
384+ function hashHTMLBlocks($text) {
385+ if ($this->no_markup) return $text;
386+
387+ $less_than_tab = $this->tab_width - 1;
388+
389+ # Hashify HTML blocks:
390+ # We only want to do this for block-level HTML tags, such as headers,
391+ # lists, and tables. That's because we still want to wrap <p>s around
392+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
393+ # phrase emphasis, and spans. The list of tags we're looking for is
394+ # hard-coded:
395+ #
396+ # * List "a" is made of tags which can be both inline or block-level.
397+ # These will be treated block-level when the start tag is alone on
398+ # its line, otherwise they're not matched here and will be taken as
399+ # inline later.
400+ # * List "b" is made of tags which are always block-level;
401+ #
402+ $block_tags_a_re = 'ins|del';
403+ $block_tags_b_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|'.
404+ 'script|noscript|form|fieldset|iframe|math';
405+
406+ # Regular expression for the content of a block tag.
407+ $nested_tags_level = 4;
408+ $attr = '
409+ (?> # optional tag attributes
410+ \s # starts with whitespace
411+ (?>
412+ [^>"/]+ # text outside quotes
413+ |
414+ /+(?!>) # slash not followed by ">"
415+ |
416+ "[^"]*" # text inside double quotes (tolerate ">")
417+ |
418+ \'[^\']*\' # text inside single quotes (tolerate ">")
419+ )*
420+ )?
421+ ';
422+ $content =
423+ str_repeat('
424+ (?>
425+ [^<]+ # content without tag
426+ |
427+ <\2 # nested opening tag
428+ '.$attr.' # attributes
429+ (?>
430+ />
431+ |
432+ >', $nested_tags_level). # end of opening tag
433+ '.*?'. # last level nested tag content
434+ str_repeat('
435+ </\2\s*> # closing nested tag
436+ )
437+ |
438+ <(?!/\2\s*> # other tags with a different name
439+ )
440+ )*',
441+ $nested_tags_level);
442+ $content2 = str_replace('\2', '\3', $content);
443+
444+ # First, look for nested blocks, e.g.:
445+ # <div>
446+ # <div>
447+ # tags for inner block must be indented.
448+ # </div>
449+ # </div>
450+ #
451+ # The outermost tags must start at the left margin for this to match, and
452+ # the inner nested divs must be indented.
453+ # We need to do this before the next, more liberal match, because the next
454+ # match will start at the first `<div>` and stop at the first `</div>`.
455+ $text = preg_replace_callback('{(?>
456+ (?>
457+ (?<=\n\n) # Starting after a blank line
458+ | # or
459+ \A\n? # the beginning of the doc
460+ )
461+ ( # save in $1
462+
463+ # Match from `\n<tag>` to `</tag>\n`, handling nested tags
464+ # in between.
465+
466+ [ ]{0,'.$less_than_tab.'}
467+ <('.$block_tags_b_re.')# start tag = $2
468+ '.$attr.'> # attributes followed by > and \n
469+ '.$content.' # content, support nesting
470+ </\2> # the matching end tag
471+ [ ]* # trailing spaces/tabs
472+ (?=\n+|\Z) # followed by a newline or end of document
473+
474+ | # Special version for tags of group a.
475+
476+ [ ]{0,'.$less_than_tab.'}
477+ <('.$block_tags_a_re.')# start tag = $3
478+ '.$attr.'>[ ]*\n # attributes followed by >
479+ '.$content2.' # content, support nesting
480+ </\3> # the matching end tag
481+ [ ]* # trailing spaces/tabs
482+ (?=\n+|\Z) # followed by a newline or end of document
483+
484+ | # Special case just for <hr />. It was easier to make a special
485+ # case than to make the other regex more complicated.
486+
487+ [ ]{0,'.$less_than_tab.'}
488+ <(hr) # start tag = $2
489+ '.$attr.' # attributes
490+ /?> # the matching end tag
491+ [ ]*
492+ (?=\n{2,}|\Z) # followed by a blank line or end of document
493+
494+ | # Special case for standalone HTML comments:
495+
496+ [ ]{0,'.$less_than_tab.'}
497+ (?s:
498+ <!-- .*? -->
499+ )
500+ [ ]*
501+ (?=\n{2,}|\Z) # followed by a blank line or end of document
502+
503+ | # PHP and ASP-style processor instructions (<? and <%)
504+
505+ [ ]{0,'.$less_than_tab.'}
506+ (?s:
507+ <([?%]) # $2
508+ .*?
509+ \2>
510+ )
511+ [ ]*
512+ (?=\n{2,}|\Z) # followed by a blank line or end of document
513+
514+ )
515+ )}Sxmi',
516+ array(&$this, '_hashHTMLBlocks_callback'),
517+ $text);
518+
519+ return $text;
520+ }
521+ function _hashHTMLBlocks_callback($matches) {
522+ $text = $matches[1];
523+ $key = $this->hashBlock($text);
524+ return "\n\n$key\n\n";
525+ }
526+
527+
528+ function hashPart($text, $boundary = 'X') {
529+ #
530+ # Called whenever a tag must be hashed when a function insert an atomic
531+ # element in the text stream. Passing $text to through this function gives
532+ # a unique text-token which will be reverted back when calling unhash.
533+ #
534+ # The $boundary argument specify what character should be used to surround
535+ # the token. By convension, "B" is used for block elements that needs not
536+ # to be wrapped into paragraph tags at the end, ":" is used for elements
537+ # that are word separators and "X" is used in the general case.
538+ #
539+ # Swap back any tag hash found in $text so we do not have to `unhash`
540+ # multiple times at the end.
541+ $text = $this->unhash($text);
542+
543+ # Then hash the block.
544+ static $i = 0;
545+ $key = "$boundary\x1A" . ++$i . $boundary;
546+ $this->html_hashes[$key] = $text;
547+ return $key; # String that will replace the tag.
548+ }
549+
550+
551+ function hashBlock($text) {
552+ #
553+ # Shortcut function for hashPart with block-level boundaries.
554+ #
555+ return $this->hashPart($text, 'B');
556+ }
557+
558+
559+ var $block_gamut = array(
560+ #
561+ # These are all the transformations that form block-level
562+ # tags like paragraphs, headers, and list items.
563+ #
564+ "doHeaders" => 10,
565+ "doHorizontalRules" => 20,
566+
567+ "doLists" => 40,
568+ "doCodeBlocks" => 50,
569+ "doBlockQuotes" => 60,
570+ );
571+
572+ function runBlockGamut($text) {
573+ #
574+ # Run block gamut tranformations.
575+ #
576+ # We need to escape raw HTML in Markdown source before doing anything
577+ # else. This need to be done for each block, and not only at the
578+ # begining in the Markdown function since hashed blocks can be part of
579+ # list items and could have been indented. Indented blocks would have
580+ # been seen as a code block in a previous pass of hashHTMLBlocks.
581+ $text = $this->hashHTMLBlocks($text);
582+
583+ return $this->runBasicBlockGamut($text);
584+ }
585+
586+ function runBasicBlockGamut($text) {
587+ #
588+ # Run block gamut tranformations, without hashing HTML blocks. This is
589+ # useful when HTML blocks are known to be already hashed, like in the first
590+ # whole-document pass.
591+ #
592+ foreach ($this->block_gamut as $method => $priority) {
593+ $text = $this->$method($text);
594+ }
595+
596+ # Finally form paragraph and restore hashed blocks.
597+ $text = $this->formParagraphs($text);
598+
599+ return $text;
600+ }
601+
602+
603+ function doHorizontalRules($text) {
604+ # Do Horizontal Rules:
605+ return preg_replace(
606+ '{
607+ ^[ ]{0,3} # Leading space
608+ ([-*_]) # $1: First marker
609+ (?> # Repeated marker group
610+ [ ]{0,2} # Zero, one, or two spaces.
611+ \1 # Marker character
612+ ){2,} # Group repeated at least twice
613+ [ ]* # Tailing spaces
614+ $ # End of line.
615+ }mx',
616+ "\n".$this->hashBlock("<hr$this->empty_element_suffix")."\n",
617+ $text);
618+ }
619+
620+
621+ var $span_gamut = array(
622+ #
623+ # These are all the transformations that occur *within* block-level
624+ # tags like paragraphs, headers, and list items.
625+ #
626+ # Process character escapes, code spans, and inline HTML
627+ # in one shot.
628+ "parseSpan" => -30,
629+
630+ # Process anchor and image tags. Images must come first,
631+ # because ![foo][f] looks like an anchor.
632+ "doImages" => 10,
633+ "doAnchors" => 20,
634+
635+ # Make links out of things like `<http://example.com/>`
636+ # Must come after doAnchors, because you can use < and >
637+ # delimiters in inline links like [this](<url>).
638+ "doAutoLinks" => 30,
639+ "encodeAmpsAndAngles" => 40,
640+
641+ "doItalicsAndBold" => 50,
642+ "doHardBreaks" => 60,
643+ );
644+
645+ function runSpanGamut($text) {
646+ #
647+ # Run span gamut tranformations.
648+ #
649+ foreach ($this->span_gamut as $method => $priority) {
650+ $text = $this->$method($text);
651+ }
652+
653+ return $text;
654+ }
655+
656+
657+ function doHardBreaks($text) {
658+ # Do hard breaks:
659+ return preg_replace_callback('/ {2,}\n/',
660+ array(&$this, '_doHardBreaks_callback'), $text);
661+ }
662+ function _doHardBreaks_callback($matches) {
663+ return $this->hashPart("<br$this->empty_element_suffix\n");
664+ }
665+
666+
667+ function doAnchors($text) {
668+ #
669+ # Turn Markdown link shortcuts into XHTML <a> tags.
670+ #
671+ if ($this->in_anchor) return $text;
672+ $this->in_anchor = true;
673+
674+ #
675+ # First, handle reference-style links: [link text] [id]
676+ #
677+ $text = preg_replace_callback('{
678+ ( # wrap whole match in $1
679+ \[
680+ ('.$this->nested_brackets_re.') # link text = $2
681+ \]
682+
683+ [ ]? # one optional space
684+ (?:\n[ ]*)? # one optional newline followed by spaces
685+
686+ \[
687+ (.*?) # id = $3
688+ \]
689+ )
690+ }xs',
691+ array(&$this, '_doAnchors_reference_callback'), $text);
692+
693+ #
694+ # Next, inline-style links: [link text](url "optional title")
695+ #
696+ $text = preg_replace_callback('{
697+ ( # wrap whole match in $1
698+ \[
699+ ('.$this->nested_brackets_re.') # link text = $2
700+ \]
701+ \( # literal paren
702+ [ ]*
703+ (?:
704+ <(\S*)> # href = $3
705+ |
706+ ('.$this->nested_url_parenthesis_re.') # href = $4
707+ )
708+ [ ]*
709+ ( # $5
710+ ([\'"]) # quote char = $6
711+ (.*?) # Title = $7
712+ \6 # matching quote
713+ [ ]* # ignore any spaces/tabs between closing quote and )
714+ )? # title is optional
715+ \)
716+ )
717+ }xs',
718+ array(&$this, '_DoAnchors_inline_callback'), $text);
719+
720+ #
721+ # Last, handle reference-style shortcuts: [link text]
722+ # These must come last in case you've also got [link test][1]
723+ # or [link test](/foo)
724+ #
725+// $text = preg_replace_callback('{
726+// ( # wrap whole match in $1
727+// \[
728+// ([^\[\]]+) # link text = $2; can\'t contain [ or ]
729+// \]
730+// )
731+// }xs',
732+// array(&$this, '_doAnchors_reference_callback'), $text);
733+
734+ $this->in_anchor = false;
735+ return $text;
736+ }
737+ function _doAnchors_reference_callback($matches) {
738+ $whole_match = $matches[1];
739+ $link_text = $matches[2];
740+ $link_id =& $matches[3];
741+
742+ if ($link_id == "") {
743+ # for shortcut links like [this][] or [this].
744+ $link_id = $link_text;
745+ }
746+
747+ # lower-case and turn embedded newlines into spaces
748+ $link_id = strtolower($link_id);
749+ $link_id = preg_replace('{[ ]?\n}', ' ', $link_id);
750+
751+ if (isset($this->urls[$link_id])) {
752+ $url = $this->urls[$link_id];
753+ $url = $this->encodeAttribute($url);
754+
755+ $result = "<a href=\"$url\"";
756+ if ( isset( $this->titles[$link_id] ) ) {
757+ $title = $this->titles[$link_id];
758+ $title = $this->encodeAttribute($title);
759+ $result .= " title=\"$title\"";
760+ }
761+
762+ $link_text = $this->runSpanGamut($link_text);
763+ $result .= ">$link_text</a>";
764+ $result = $this->hashPart($result);
765+ }
766+ else {
767+ $result = $whole_match;
768+ }
769+ return $result;
770+ }
771+ function _doAnchors_inline_callback($matches) {
772+ $whole_match = $matches[1];
773+ $link_text = $this->runSpanGamut($matches[2]);
774+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
775+ $title =& $matches[7];
776+
777+ $url = $this->encodeAttribute($url);
778+
779+ $result = "<a href=\"$url\"";
780+ if (isset($title)) {
781+ $title = $this->encodeAttribute($title);
782+ $result .= " title=\"$title\"";
783+ }
784+
785+ $link_text = $this->runSpanGamut($link_text);
786+ $result .= ">$link_text</a>";
787+
788+ return $this->hashPart($result);
789+ }
790+
791+
792+ function doImages($text) {
793+ #
794+ # Turn Markdown image shortcuts into <img> tags.
795+ #
796+ #
797+ # First, handle reference-style labeled images: ![alt text][id]
798+ #
799+ $text = preg_replace_callback('{
800+ ( # wrap whole match in $1
801+ !\[
802+ ('.$this->nested_brackets_re.') # alt text = $2
803+ \]
804+
805+ [ ]? # one optional space
806+ (?:\n[ ]*)? # one optional newline followed by spaces
807+
808+ \[
809+ (.*?) # id = $3
810+ \]
811+
812+ )
813+ }xs',
814+ array(&$this, '_doImages_reference_callback'), $text);
815+
816+ #
817+ # Next, handle inline images: ![alt text](url "optional title")
818+ # Don't forget: encode * and _
819+ #
820+ $text = preg_replace_callback('{
821+ ( # wrap whole match in $1
822+ !\[
823+ ('.$this->nested_brackets_re.') # alt text = $2
824+ \]
825+ \s? # One optional whitespace character
826+ \( # literal paren
827+ [ ]*
828+ (?:
829+ <(\S*)> # src url = $3
830+ |
831+ ('.$this->nested_url_parenthesis_re.') # src url = $4
832+ )
833+ [ ]*
834+ ( # $5
835+ ([\'"]) # quote char = $6
836+ (.*?) # title = $7
837+ \6 # matching quote
838+ [ ]*
839+ )? # title is optional
840+ \)
841+ )
842+ }xs',
843+ array(&$this, '_doImages_inline_callback'), $text);
844+
845+ return $text;
846+ }
847+ function _doImages_reference_callback($matches) {
848+ $whole_match = $matches[1];
849+ $alt_text = $matches[2];
850+ $link_id = strtolower($matches[3]);
851+
852+ if ($link_id == "") {
853+ $link_id = strtolower($alt_text); # for shortcut links like ![this][].
854+ }
855+
856+ $alt_text = $this->encodeAttribute($alt_text);
857+ if (isset($this->urls[$link_id])) {
858+ $url = $this->encodeAttribute($this->urls[$link_id]);
859+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
860+ if (isset($this->titles[$link_id])) {
861+ $title = $this->titles[$link_id];
862+ $title = $this->encodeAttribute($title);
863+ $result .= " title=\"$title\"";
864+ }
865+ $result .= $this->empty_element_suffix;
866+ $result = $this->hashPart($result);
867+ }
868+ else {
869+ # If there's no such link ID, leave intact:
870+ $result = $whole_match;
871+ }
872+
873+ return $result;
874+ }
875+ function _doImages_inline_callback($matches) {
876+ $whole_match = $matches[1];
877+ $alt_text = $matches[2];
878+ $url = $matches[3] == '' ? $matches[4] : $matches[3];
879+ $title =& $matches[7];
880+
881+ $alt_text = $this->encodeAttribute($alt_text);
882+ $url = $this->encodeAttribute($url);
883+ $result = "<img src=\"$url\" alt=\"$alt_text\"";
884+ if (isset($title)) {
885+ $title = $this->encodeAttribute($title);
886+ $result .= " title=\"$title\""; # $title already quoted
887+ }
888+ $result .= $this->empty_element_suffix;
889+
890+ return $this->hashPart($result);
891+ }
892+
893+
894+ function doHeaders($text) {
895+ # Setext-style headers:
896+ # Header 1
897+ # ========
898+ #
899+ # Header 2
900+ # --------
901+ #
902+ $text = preg_replace_callback('{ ^(.+?)[ ]*\n(=+|-+)[ ]*\n+ }mx',
903+ array(&$this, '_doHeaders_callback_setext'), $text);
904+
905+ # atx-style headers:
906+ # # Header 1
907+ # ## Header 2
908+ # ## Header 2 with closing hashes ##
909+ # ...
910+ # ###### Header 6
911+ #
912+ $text = preg_replace_callback('{
913+ ^(\#{1,6}) # $1 = string of #\'s
914+ [ ]*
915+ (.+?) # $2 = Header text
916+ [ ]*
917+ \#* # optional closing #\'s (not counted)
918+ \n+
919+ }xm',
920+ array(&$this, '_doHeaders_callback_atx'), $text);
921+
922+ return $text;
923+ }
924+ function _doHeaders_callback_setext($matches) {
925+ # Terrible hack to check we haven't found an empty list item.
926+ if ($matches[2] == '-' && preg_match('{^-(?: |$)}', $matches[1]))
927+ return $matches[0];
928+
929+ $level = $matches[2]{0} == '=' ? 1 : 2;
930+ $block = "<h$level>".$this->runSpanGamut($matches[1])."</h$level>";
931+ return "\n" . $this->hashBlock($block) . "\n\n";
932+ }
933+ function _doHeaders_callback_atx($matches) {
934+ $level = strlen($matches[1]);
935+ $block = "<h$level>".$this->runSpanGamut($matches[2])."</h$level>";
936+ return "\n" . $this->hashBlock($block) . "\n\n";
937+ }
938+
939+
940+ function doLists($text) {
941+ #
942+ # Form HTML ordered (numbered) and unordered (bulleted) lists.
943+ #
944+ $less_than_tab = $this->tab_width - 1;
945+
946+ # Re-usable patterns to match list item bullets and number markers:
947+ $marker_ul_re = '[*+-]';
948+ $marker_ol_re = '\d+[.]';
949+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
950+
951+ $markers_relist = array($marker_ul_re, $marker_ol_re);
952+
953+ foreach ($markers_relist as $marker_re) {
954+ # Re-usable pattern to match any entirel ul or ol list:
955+ $whole_list_re = '
956+ ( # $1 = whole list
957+ ( # $2
958+ [ ]{0,'.$less_than_tab.'}
959+ ('.$marker_re.') # $3 = first list item marker
960+ [ ]+
961+ )
962+ (?s:.+?)
963+ ( # $4
964+ \z
965+ |
966+ \n{2,}
967+ (?=\S)
968+ (?! # Negative lookahead for another list item marker
969+ [ ]*
970+ '.$marker_re.'[ ]+
971+ )
972+ )
973+ )
974+ '; // mx
975+
976+ # We use a different prefix before nested lists than top-level lists.
977+ # See extended comment in _ProcessListItems().
978+
979+ if ($this->list_level) {
980+ $text = preg_replace_callback('{
981+ ^
982+ '.$whole_list_re.'
983+ }mx',
984+ array(&$this, '_doLists_callback'), $text);
985+ }
986+ else {
987+ $text = preg_replace_callback('{
988+ (?:(?<=\n)\n|\A\n?) # Must eat the newline
989+ '.$whole_list_re.'
990+ }mx',
991+ array(&$this, '_doLists_callback'), $text);
992+ }
993+ }
994+
995+ return $text;
996+ }
997+ function _doLists_callback($matches) {
998+ # Re-usable patterns to match list item bullets and number markers:
999+ $marker_ul_re = '[*+-]';
1000+ $marker_ol_re = '\d+[.]';
1001+ $marker_any_re = "(?:$marker_ul_re|$marker_ol_re)";
1002+
1003+ $list = $matches[1];
1004+ $list_type = preg_match("/$marker_ul_re/", $matches[3]) ? "ul" : "ol";
1005+
1006+ $marker_any_re = ( $list_type == "ul" ? $marker_ul_re : $marker_ol_re );
1007+
1008+ $list .= "\n";
1009+ $result = $this->processListItems($list, $marker_any_re);
1010+
1011+ $result = $this->hashBlock("<$list_type>\n" . $result . "</$list_type>");
1012+ return "\n". $result ."\n\n";
1013+ }
1014+
1015+ var $list_level = 0;
1016+
1017+ function processListItems($list_str, $marker_any_re) {
1018+ #
1019+ # Process the contents of a single ordered or unordered list, splitting it
1020+ # into individual list items.
1021+ #
1022+ # The $this->list_level global keeps track of when we're inside a list.
1023+ # Each time we enter a list, we increment it; when we leave a list,
1024+ # we decrement. If it's zero, we're not in a list anymore.
1025+ #
1026+ # We do this because when we're not inside a list, we want to treat
1027+ # something like this:
1028+ #
1029+ # I recommend upgrading to version
1030+ # 8. Oops, now this line is treated
1031+ # as a sub-list.
1032+ #
1033+ # As a single paragraph, despite the fact that the second line starts
1034+ # with a digit-period-space sequence.
1035+ #
1036+ # Whereas when we're inside a list (or sub-list), that line will be
1037+ # treated as the start of a sub-list. What a kludge, huh? This is
1038+ # an aspect of Markdown's syntax that's hard to parse perfectly
1039+ # without resorting to mind-reading. Perhaps the solution is to
1040+ # change the syntax rules such that sub-lists must start with a
1041+ # starting cardinal number; e.g. "1." or "a.".
1042+
1043+ $this->list_level++;
1044+
1045+ # trim trailing blank lines:
1046+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
1047+
1048+ $list_str = preg_replace_callback('{
1049+ (\n)? # leading line = $1
1050+ (^[ ]*) # leading whitespace = $2
1051+ ('.$marker_any_re.' # list marker and space = $3
1052+ (?:[ ]+|(?=\n)) # space only required if item is not empty
1053+ )
1054+ ((?s:.*?)) # list item text = $4
1055+ (?:(\n+(?=\n))|\n) # tailing blank line = $5
1056+ (?= \n* (\z | \2 ('.$marker_any_re.') (?:[ ]+|(?=\n))))
1057+ }xm',
1058+ array(&$this, '_processListItems_callback'), $list_str);
1059+
1060+ $this->list_level--;
1061+ return $list_str;
1062+ }
1063+ function _processListItems_callback($matches) {
1064+ $item = $matches[4];
1065+ $leading_line =& $matches[1];
1066+ $leading_space =& $matches[2];
1067+ $marker_space = $matches[3];
1068+ $tailing_blank_line =& $matches[5];
1069+
1070+ if ($leading_line || $tailing_blank_line ||
1071+ preg_match('/\n{2,}/', $item))
1072+ {
1073+ # Replace marker with the appropriate whitespace indentation
1074+ $item = $leading_space . str_repeat(' ', strlen($marker_space)) . $item;
1075+ $item = $this->runBlockGamut($this->outdent($item)."\n");
1076+ }
1077+ else {
1078+ # Recursion for sub-lists:
1079+ $item = $this->doLists($this->outdent($item));
1080+ $item = preg_replace('/\n+$/', '', $item);
1081+ $item = $this->runSpanGamut($item);
1082+ }
1083+
1084+ return "<li>" . $item . "</li>\n";
1085+ }
1086+
1087+
1088+ function doCodeBlocks($text) {
1089+ #
1090+ # Process Markdown `<pre><code>` blocks.
1091+ #
1092+ $text = preg_replace_callback('{
1093+ (?:\n\n|\A\n?)
1094+ ( # $1 = the code block -- one or more lines, starting with a space/tab
1095+ (?>
1096+ [ ]{'.$this->tab_width.'} # Lines must start with a tab or a tab-width of spaces
1097+ .*\n+
1098+ )+
1099+ )
1100+ ((?=^[ ]{0,'.$this->tab_width.'}\S)|\Z) # Lookahead for non-space at line-start, or end of doc
1101+ }xm',
1102+ array(&$this, '_doCodeBlocks_callback'), $text);
1103+
1104+ return $text;
1105+ }
1106+ function _doCodeBlocks_callback($matches) {
1107+ $codeblock = $matches[1];
1108+
1109+ $codeblock = $this->outdent($codeblock);
1110+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
1111+
1112+ # trim leading newlines and trailing newlines
1113+ $codeblock = preg_replace('/\A\n+|\n+\z/', '', $codeblock);
1114+
1115+ $codeblock = "<pre><code>$codeblock\n</code></pre>";
1116+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
1117+ }
1118+
1119+
1120+ function makeCodeSpan($code) {
1121+ #
1122+ # Create a code span markup for $code. Called from handleSpanToken.
1123+ #
1124+ $code = htmlspecialchars(trim($code), ENT_NOQUOTES);
1125+ return $this->hashPart("<code>$code</code>");
1126+ }
1127+
1128+
1129+ var $em_relist = array(
1130+ '' => '(?:(?<!\*)\*(?!\*)|(?<!_)_(?!_))(?=\S)(?![.,:;]\s)',
1131+ '*' => '(?<=\S)(?<!\*)\*(?!\*)',
1132+ '_' => '(?<=\S)(?<!_)_(?!_)',
1133+ );
1134+ var $strong_relist = array(
1135+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<!_)__(?!_))(?=\S)(?![.,:;]\s)',
1136+ '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
1137+ '__' => '(?<=\S)(?<!_)__(?!_)',
1138+ );
1139+ var $em_strong_relist = array(
1140+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<!_)___(?!_))(?=\S)(?![.,:;]\s)',
1141+ '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
1142+ '___' => '(?<=\S)(?<!_)___(?!_)',
1143+ );
1144+ var $em_strong_prepared_relist;
1145+
1146+ function prepareItalicsAndBold() {
1147+ #
1148+ # Prepare regular expressions for seraching emphasis tokens in any
1149+ # context.
1150+ #
1151+ foreach ($this->em_relist as $em => $em_re) {
1152+ foreach ($this->strong_relist as $strong => $strong_re) {
1153+ # Construct list of allowed token expressions.
1154+ $token_relist = array();
1155+ if (isset($this->em_strong_relist["$em$strong"])) {
1156+ $token_relist[] = $this->em_strong_relist["$em$strong"];
1157+ }
1158+ $token_relist[] = $em_re;
1159+ $token_relist[] = $strong_re;
1160+
1161+ # Construct master expression from list.
1162+ $token_re = '{('. implode('|', $token_relist) .')}';
1163+ $this->em_strong_prepared_relist["$em$strong"] = $token_re;
1164+ }
1165+ }
1166+ }
1167+
1168+ function doItalicsAndBold($text) {
1169+ $token_stack = array('');
1170+ $text_stack = array('');
1171+ $em = '';
1172+ $strong = '';
1173+ $tree_char_em = false;
1174+
1175+ while (1) {
1176+ #
1177+ # Get prepared regular expression for seraching emphasis tokens
1178+ # in current context.
1179+ #
1180+ $token_re = $this->em_strong_prepared_relist["$em$strong"];
1181+
1182+ #
1183+ # Each loop iteration seach for the next emphasis token.
1184+ # Each token is then passed to handleSpanToken.
1185+ #
1186+ $parts = preg_split($token_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
1187+ $text_stack[0] .= $parts[0];
1188+ $token =& $parts[1];
1189+ $text =& $parts[2];
1190+
1191+ if (empty($token)) {
1192+ # Reached end of text span: empty stack without emitting.
1193+ # any more emphasis.
1194+ while ($token_stack[0]) {
1195+ $text_stack[1] .= array_shift($token_stack);
1196+ $text_stack[0] .= array_shift($text_stack);
1197+ }
1198+ break;
1199+ }
1200+
1201+ $token_len = strlen($token);
1202+ if ($tree_char_em) {
1203+ # Reached closing marker while inside a three-char emphasis.
1204+ if ($token_len == 3) {
1205+ # Three-char closing marker, close em and strong.
1206+ array_shift($token_stack);
1207+ $span = array_shift($text_stack);
1208+ $span = $this->runSpanGamut($span);
1209+ $span = "<strong><em>$span</em></strong>";
1210+ $text_stack[0] .= $this->hashPart($span);
1211+ $em = '';
1212+ $strong = '';
1213+ } else {
1214+ # Other closing marker: close one em or strong and
1215+ # change current token state to match the other
1216+ $token_stack[0] = str_repeat($token{0}, 3-$token_len);
1217+ $tag = $token_len == 2 ? "strong" : "em";
1218+ $span = $text_stack[0];
1219+ $span = $this->runSpanGamut($span);
1220+ $span = "<$tag>$span</$tag>";
1221+ $text_stack[0] = $this->hashPart($span);
1222+ $$tag = ''; # $$tag stands for $em or $strong
1223+ }
1224+ $tree_char_em = false;
1225+ } else if ($token_len == 3) {
1226+ if ($em) {
1227+ # Reached closing marker for both em and strong.
1228+ # Closing strong marker:
1229+ for ($i = 0; $i < 2; ++$i) {
1230+ $shifted_token = array_shift($token_stack);
1231+ $tag = strlen($shifted_token) == 2 ? "strong" : "em";
1232+ $span = array_shift($text_stack);
1233+ $span = $this->runSpanGamut($span);
1234+ $span = "<$tag>$span</$tag>";
1235+ $text_stack[0] .= $this->hashPart($span);
1236+ $$tag = ''; # $$tag stands for $em or $strong
1237+ }
1238+ } else {
1239+ # Reached opening three-char emphasis marker. Push on token
1240+ # stack; will be handled by the special condition above.
1241+ $em = $token{0};
1242+ $strong = "$em$em";
1243+ array_unshift($token_stack, $token);
1244+ array_unshift($text_stack, '');
1245+ $tree_char_em = true;
1246+ }
1247+ } else if ($token_len == 2) {
1248+ if ($strong) {
1249+ # Unwind any dangling emphasis marker:
1250+ if (strlen($token_stack[0]) == 1) {
1251+ $text_stack[1] .= array_shift($token_stack);
1252+ $text_stack[0] .= array_shift($text_stack);
1253+ }
1254+ # Closing strong marker:
1255+ array_shift($token_stack);
1256+ $span = array_shift($text_stack);
1257+ $span = $this->runSpanGamut($span);
1258+ $span = "<strong>$span</strong>";
1259+ $text_stack[0] .= $this->hashPart($span);
1260+ $strong = '';
1261+ } else {
1262+ array_unshift($token_stack, $token);
1263+ array_unshift($text_stack, '');
1264+ $strong = $token;
1265+ }
1266+ } else {
1267+ # Here $token_len == 1
1268+ if ($em) {
1269+ if (strlen($token_stack[0]) == 1) {
1270+ # Closing emphasis marker:
1271+ array_shift($token_stack);
1272+ $span = array_shift($text_stack);
1273+ $span = $this->runSpanGamut($span);
1274+ $span = "<em>$span</em>";
1275+ $text_stack[0] .= $this->hashPart($span);
1276+ $em = '';
1277+ } else {
1278+ $text_stack[0] .= $token;
1279+ }
1280+ } else {
1281+ array_unshift($token_stack, $token);
1282+ array_unshift($text_stack, '');
1283+ $em = $token;
1284+ }
1285+ }
1286+ }
1287+ return $text_stack[0];
1288+ }
1289+
1290+
1291+ function doBlockQuotes($text) {
1292+ $text = preg_replace_callback('/
1293+ ( # Wrap whole match in $1
1294+ (?>
1295+ ^[ ]*>[ ]? # ">" at the start of a line
1296+ .+\n # rest of the first line
1297+ (.+\n)* # subsequent consecutive lines
1298+ \n* # blanks
1299+ )+
1300+ )
1301+ /xm',
1302+ array(&$this, '_doBlockQuotes_callback'), $text);
1303+
1304+ return $text;
1305+ }
1306+ function _doBlockQuotes_callback($matches) {
1307+ $bq = $matches[1];
1308+ # trim one level of quoting - trim whitespace-only lines
1309+ $bq = preg_replace('/^[ ]*>[ ]?|^[ ]+$/m', '', $bq);
1310+ $bq = $this->runBlockGamut($bq); # recurse
1311+
1312+ $bq = preg_replace('/^/m', " ", $bq);
1313+ # These leading spaces cause problem with <pre> content,
1314+ # so we need to fix that:
1315+ $bq = preg_replace_callback('{(\s*<pre>.+?</pre>)}sx',
1316+ array(&$this, '_DoBlockQuotes_callback2'), $bq);
1317+
1318+ return "\n". $this->hashBlock("<blockquote>\n$bq\n</blockquote>")."\n\n";
1319+ }
1320+ function _doBlockQuotes_callback2($matches) {
1321+ $pre = $matches[1];
1322+ $pre = preg_replace('/^ /m', '', $pre);
1323+ return $pre;
1324+ }
1325+
1326+
1327+ function formParagraphs($text) {
1328+ #
1329+ # Params:
1330+ # $text - string to process with html <p> tags
1331+ #
1332+ # Strip leading and trailing lines:
1333+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
1334+
1335+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
1336+
1337+ #
1338+ # Wrap <p> tags and unhashify HTML blocks
1339+ #
1340+ foreach ($grafs as $key => $value) {
1341+ if (!preg_match('/^B\x1A[0-9]+B$/', $value)) {
1342+ # Is a paragraph.
1343+ $value = $this->runSpanGamut($value);
1344+ $value = preg_replace('/^([ ]*)/', "<p>", $value);
1345+ $value .= "</p>";
1346+ $grafs[$key] = $this->unhash($value);
1347+ }
1348+ else {
1349+ # Is a block.
1350+ # Modify elements of @grafs in-place...
1351+ $graf = $value;
1352+ $block = $this->html_hashes[$graf];
1353+ $graf = $block;
1354+// if (preg_match('{
1355+// \A
1356+// ( # $1 = <div> tag
1357+// <div \s+
1358+// [^>]*
1359+// \b
1360+// markdown\s*=\s* ([\'"]) # $2 = attr quote char
1361+// 1
1362+// \2
1363+// [^>]*
1364+// >
1365+// )
1366+// ( # $3 = contents
1367+// .*
1368+// )
1369+// (</div>) # $4 = closing tag
1370+// \z
1371+// }xs', $block, $matches))
1372+// {
1373+// list(, $div_open, , $div_content, $div_close) = $matches;
1374+//
1375+// # We can't call Markdown(), because that resets the hash;
1376+// # that initialization code should be pulled into its own sub, though.
1377+// $div_content = $this->hashHTMLBlocks($div_content);
1378+//
1379+// # Run document gamut methods on the content.
1380+// foreach ($this->document_gamut as $method => $priority) {
1381+// $div_content = $this->$method($div_content);
1382+// }
1383+//
1384+// $div_open = preg_replace(
1385+// '{\smarkdown\s*=\s*([\'"]).+?\1}', '', $div_open);
1386+//
1387+// $graf = $div_open . "\n" . $div_content . "\n" . $div_close;
1388+// }
1389+ $grafs[$key] = $graf;
1390+ }
1391+ }
1392+
1393+ return implode("\n\n", $grafs);
1394+ }
1395+
1396+
1397+ function encodeAttribute($text) {
1398+ #
1399+ # Encode text for a double-quoted HTML attribute. This function
1400+ # is *not* suitable for attributes enclosed in single quotes.
1401+ #
1402+ $text = $this->encodeAmpsAndAngles($text);
1403+ $text = str_replace('"', '&quot;', $text);
1404+ return $text;
1405+ }
1406+
1407+
1408+ function encodeAmpsAndAngles($text) {
1409+ #
1410+ # Smart processing for ampersands and angle brackets that need to
1411+ # be encoded. Valid character entities are left alone unless the
1412+ # no-entities mode is set.
1413+ #
1414+ if ($this->no_entities) {
1415+ $text = str_replace('&', '&amp;', $text);
1416+ } else {
1417+ # Ampersand-encoding based entirely on Nat Irons's Amputator
1418+ # MT plugin: <http://bumppo.net/projects/amputator/>
1419+ $text = preg_replace('/&(?!#?[xX]?(?:[0-9a-fA-F]+|\w+);)/',
1420+ '&amp;', $text);;
1421+ }
1422+ # Encode remaining <'s
1423+ $text = str_replace('<', '&lt;', $text);
1424+
1425+ return $text;
1426+ }
1427+
1428+
1429+ function doAutoLinks($text) {
1430+ $text = preg_replace_callback('{<((https?|ftp|dict):[^\'">\s]+)>}i',
1431+ array(&$this, '_doAutoLinks_url_callback'), $text);
1432+
1433+ # Email addresses: <address@domain.foo>
1434+ $text = preg_replace_callback('{
1435+ <
1436+ (?:mailto:)?
1437+ (
1438+ [-.\w\x80-\xFF]+
1439+ \@
1440+ [-a-z0-9\x80-\xFF]+(\.[-a-z0-9\x80-\xFF]+)*\.[a-z]+
1441+ )
1442+ >
1443+ }xi',
1444+ array(&$this, '_doAutoLinks_email_callback'), $text);
1445+
1446+ return $text;
1447+ }
1448+ function _doAutoLinks_url_callback($matches) {
1449+ $url = $this->encodeAttribute($matches[1]);
1450+ $link = "<a href=\"$url\">$url</a>";
1451+ return $this->hashPart($link);
1452+ }
1453+ function _doAutoLinks_email_callback($matches) {
1454+ $address = $matches[1];
1455+ $link = $this->encodeEmailAddress($address);
1456+ return $this->hashPart($link);
1457+ }
1458+
1459+
1460+ function encodeEmailAddress($addr) {
1461+ #
1462+ # Input: an email address, e.g. "foo@example.com"
1463+ #
1464+ # Output: the email address as a mailto link, with each character
1465+ # of the address encoded as either a decimal or hex entity, in
1466+ # the hopes of foiling most address harvesting spam bots. E.g.:
1467+ #
1468+ # <p><a href="&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x66;o&#111;
1469+ # &#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;&#101;&#46;&#x63;&#111;
1470+ # &#x6d;">&#x66;o&#111;&#x40;&#101;&#x78;&#97;&#x6d;&#112;&#x6c;
1471+ # &#101;&#46;&#x63;&#111;&#x6d;</a></p>
1472+ #
1473+ # Based by a filter by Matthew Wickline, posted to BBEdit-Talk.
1474+ # With some optimizations by Milian Wolff.
1475+ #
1476+ $addr = "mailto:" . $addr;
1477+ $chars = preg_split('/(?<!^)(?!$)/', $addr);
1478+ $seed = (int)abs(crc32($addr) / strlen($addr)); # Deterministic seed.
1479+
1480+ foreach ($chars as $key => $char) {
1481+ $ord = ord($char);
1482+ # Ignore non-ascii chars.
1483+ if ($ord < 128) {
1484+ $r = ($seed * (1 + $key)) % 100; # Pseudo-random function.
1485+ # roughly 10% raw, 45% hex, 45% dec
1486+ # '@' *must* be encoded. I insist.
1487+ if ($r > 90 && $char != '@') /* do nothing */;
1488+ else if ($r < 45) $chars[$key] = '&#x'.dechex($ord).';';
1489+ else $chars[$key] = '&#'.$ord.';';
1490+ }
1491+ }
1492+
1493+ $addr = implode('', $chars);
1494+ $text = implode('', array_slice($chars, 7)); # text without `mailto:`
1495+ $addr = "<a href=\"$addr\">$text</a>";
1496+
1497+ return $addr;
1498+ }
1499+
1500+
1501+ function parseSpan($str) {
1502+ #
1503+ # Take the string $str and parse it into tokens, hashing embeded HTML,
1504+ # escaped characters and handling code spans.
1505+ #
1506+ $output = '';
1507+
1508+ $span_re = '{
1509+ (
1510+ \\\\'.$this->escape_chars_re.'
1511+ |
1512+ (?<![`\\\\])
1513+ `+ # code span marker
1514+ '.( $this->no_markup ? '' : '
1515+ |
1516+ <!-- .*? --> # comment
1517+ |
1518+ <\?.*?\?> | <%.*?%> # processing instruction
1519+ |
1520+ <[/!$]?[-a-zA-Z0-9:]+ # regular tags
1521+ (?>
1522+ \s
1523+ (?>[^"\'>]+|"[^"]*"|\'[^\']*\')*
1524+ )?
1525+ >
1526+ ').'
1527+ )
1528+ }xs';
1529+
1530+ while (1) {
1531+ #
1532+ # Each loop iteration seach for either the next tag, the next
1533+ # openning code span marker, or the next escaped character.
1534+ # Each token is then passed to handleSpanToken.
1535+ #
1536+ $parts = preg_split($span_re, $str, 2, PREG_SPLIT_DELIM_CAPTURE);
1537+
1538+ # Create token from text preceding tag.
1539+ if ($parts[0] != "") {
1540+ $output .= $parts[0];
1541+ }
1542+
1543+ # Check if we reach the end.
1544+ if (isset($parts[1])) {
1545+ $output .= $this->handleSpanToken($parts[1], $parts[2]);
1546+ $str = $parts[2];
1547+ }
1548+ else {
1549+ break;
1550+ }
1551+ }
1552+
1553+ return $output;
1554+ }
1555+
1556+
1557+ function handleSpanToken($token, &$str) {
1558+ #
1559+ # Handle $token provided by parseSpan by determining its nature and
1560+ # returning the corresponding value that should replace it.
1561+ #
1562+ switch ($token{0}) {
1563+ case "\\":
1564+ return $this->hashPart("&#". ord($token{1}). ";");
1565+ case "`":
1566+ # Search for end marker in remaining text.
1567+ if (preg_match('/^(.*?[^`])'.preg_quote($token).'(?!`)(.*)$/sm',
1568+ $str, $matches))
1569+ {
1570+ $str = $matches[2];
1571+ $codespan = $this->makeCodeSpan($matches[1]);
1572+ return $this->hashPart($codespan);
1573+ }
1574+ return $token; // return as text since no ending marker found.
1575+ default:
1576+ return $this->hashPart($token);
1577+ }
1578+ }
1579+
1580+
1581+ function outdent($text) {
1582+ #
1583+ # Remove one level of line-leading tabs or spaces
1584+ #
1585+ return preg_replace('/^(\t|[ ]{1,'.$this->tab_width.'})/m', '', $text);
1586+ }
1587+
1588+
1589+ # String length function for detab. `_initDetab` will create a function to
1590+ # hanlde UTF-8 if the default function does not exist.
1591+ var $utf8_strlen = 'mb_strlen';
1592+
1593+ function detab($text) {
1594+ #
1595+ # Replace tabs with the appropriate amount of space.
1596+ #
1597+ # For each line we separate the line in blocks delemited by
1598+ # tab characters. Then we reconstruct every line by adding the
1599+ # appropriate number of space between each blocks.
1600+
1601+ $text = preg_replace_callback('/^.*\t.*$/m',
1602+ array(&$this, '_detab_callback'), $text);
1603+
1604+ return $text;
1605+ }
1606+ function _detab_callback($matches) {
1607+ $line = $matches[0];
1608+ $strlen = $this->utf8_strlen; # strlen function for UTF-8.
1609+
1610+ # Split in blocks.
1611+ $blocks = explode("\t", $line);
1612+ # Add each blocks to the line.
1613+ $line = $blocks[0];
1614+ unset($blocks[0]); # Do not add first block twice.
1615+ foreach ($blocks as $block) {
1616+ # Calculate amount of space, insert spaces, insert block.
1617+ $amount = $this->tab_width -
1618+ $strlen($line, 'UTF-8') % $this->tab_width;
1619+ $line .= str_repeat(" ", $amount) . $block;
1620+ }
1621+ return $line;
1622+ }
1623+ function _initDetab() {
1624+ #
1625+ # Check for the availability of the function in the `utf8_strlen` property
1626+ # (initially `mb_strlen`). If the function is not available, create a
1627+ # function that will loosely count the number of UTF-8 characters with a
1628+ # regular expression.
1629+ #
1630+ if (function_exists($this->utf8_strlen)) return;
1631+ $this->utf8_strlen = create_function('$text', 'return preg_match_all(
1632+ "/[\\\\x00-\\\\xBF]|[\\\\xC0-\\\\xFF][\\\\x80-\\\\xBF]*/",
1633+ $text, $m);');
1634+ }
1635+
1636+
1637+ function unhash($text) {
1638+ #
1639+ # Swap back in all the tags hashed by _HashHTMLBlocks.
1640+ #
1641+ return preg_replace_callback('/(.)\x1A[0-9]+\1/',
1642+ array(&$this, '_unhash_callback'), $text);
1643+ }
1644+ function _unhash_callback($matches) {
1645+ return $this->html_hashes[$matches[0]];
1646+ }
1647+
1648+}
1649+
1650+
1651+#
1652+# Markdown Extra Parser Class
1653+#
1654+
1655+class MarkdownExtra_Parser extends Markdown_Parser {
1656+
1657+ # Prefix for footnote ids.
1658+ var $fn_id_prefix = "";
1659+
1660+ # Optional title attribute for footnote links and backlinks.
1661+ var $fn_link_title = MARKDOWN_FN_LINK_TITLE;
1662+ var $fn_backlink_title = MARKDOWN_FN_BACKLINK_TITLE;
1663+
1664+ # Optional class attribute for footnote links and backlinks.
1665+ var $fn_link_class = MARKDOWN_FN_LINK_CLASS;
1666+ var $fn_backlink_class = MARKDOWN_FN_BACKLINK_CLASS;
1667+
1668+ # Predefined abbreviations.
1669+ var $predef_abbr = array();
1670+
1671+
1672+ function MarkdownExtra_Parser() {
1673+ #
1674+ # Constructor function. Initialize the parser object.
1675+ #
1676+ # Add extra escapable characters before parent constructor
1677+ # initialize the table.
1678+ $this->escape_chars .= ':|';
1679+
1680+ # Insert extra document, block, and span transformations.
1681+ # Parent constructor will do the sorting.
1682+ $this->document_gamut += array(
1683+ "doFencedCodeBlocks" => 5,
1684+ "stripFootnotes" => 15,
1685+ "stripAbbreviations" => 25,
1686+ "appendFootnotes" => 50,
1687+ );
1688+ $this->block_gamut += array(
1689+ "doFencedCodeBlocks" => 5,
1690+ "doTables" => 15,
1691+ "doDefLists" => 45,
1692+ );
1693+ $this->span_gamut += array(
1694+ "doFootnotes" => 5,
1695+ "doAbbreviations" => 70,
1696+ );
1697+
1698+ parent::Markdown_Parser();
1699+ }
1700+
1701+
1702+ # Extra variables used during extra transformations.
1703+ var $footnotes = array();
1704+ var $footnotes_ordered = array();
1705+ var $abbr_desciptions = array();
1706+ var $abbr_word_re = '';
1707+
1708+ # Give the current footnote number.
1709+ var $footnote_counter = 1;
1710+
1711+
1712+ function setup() {
1713+ #
1714+ # Setting up Extra-specific variables.
1715+ #
1716+ parent::setup();
1717+
1718+ $this->footnotes = array();
1719+ $this->footnotes_ordered = array();
1720+ $this->abbr_desciptions = array();
1721+ $this->abbr_word_re = '';
1722+ $this->footnote_counter = 1;
1723+
1724+ foreach ($this->predef_abbr as $abbr_word => $abbr_desc) {
1725+ if ($this->abbr_word_re)
1726+ $this->abbr_word_re .= '|';
1727+ $this->abbr_word_re .= preg_quote($abbr_word);
1728+ $this->abbr_desciptions[$abbr_word] = trim($abbr_desc);
1729+ }
1730+ }
1731+
1732+ function teardown() {
1733+ #
1734+ # Clearing Extra-specific variables.
1735+ #
1736+ $this->footnotes = array();
1737+ $this->footnotes_ordered = array();
1738+ $this->abbr_desciptions = array();
1739+ $this->abbr_word_re = '';
1740+
1741+ parent::teardown();
1742+ }
1743+
1744+
1745+ ### HTML Block Parser ###
1746+
1747+ # Tags that are always treated as block tags:
1748+ var $block_tags_re = 'p|div|h[1-6]|blockquote|pre|table|dl|ol|ul|address|form|fieldset|iframe|hr|legend';
1749+
1750+ # Tags treated as block tags only if the opening tag is alone on it's line:
1751+ var $context_block_tags_re = 'script|noscript|math|ins|del';
1752+
1753+ # Tags where markdown="1" default to span mode:
1754+ var $contain_span_tags_re = 'p|h[1-6]|li|dd|dt|td|th|legend|address';
1755+
1756+ # Tags which must not have their contents modified, no matter where
1757+ # they appear:
1758+ var $clean_tags_re = 'script|math';
1759+
1760+ # Tags that do not need to be closed.
1761+ var $auto_close_tags_re = 'hr|img';
1762+
1763+
1764+ function hashHTMLBlocks($text) {
1765+ #
1766+ # Hashify HTML Blocks and "clean tags".
1767+ #
1768+ # We only want to do this for block-level HTML tags, such as headers,
1769+ # lists, and tables. That's because we still want to wrap <p>s around
1770+ # "paragraphs" that are wrapped in non-block-level tags, such as anchors,
1771+ # phrase emphasis, and spans. The list of tags we're looking for is
1772+ # hard-coded.
1773+ #
1774+ # This works by calling _HashHTMLBlocks_InMarkdown, which then calls
1775+ # _HashHTMLBlocks_InHTML when it encounter block tags. When the markdown="1"
1776+ # attribute is found whitin a tag, _HashHTMLBlocks_InHTML calls back
1777+ # _HashHTMLBlocks_InMarkdown to handle the Markdown syntax within the tag.
1778+ # These two functions are calling each other. It's recursive!
1779+ #
1780+ #
1781+ # Call the HTML-in-Markdown hasher.
1782+ #
1783+ list($text, ) = $this->_hashHTMLBlocks_inMarkdown($text);
1784+
1785+ return $text;
1786+ }
1787+ function _hashHTMLBlocks_inMarkdown($text, $indent = 0,
1788+ $enclosing_tag_re = '', $span = false)
1789+ {
1790+ #
1791+ # Parse markdown text, calling _HashHTMLBlocks_InHTML for block tags.
1792+ #
1793+ # * $indent is the number of space to be ignored when checking for code
1794+ # blocks. This is important because if we don't take the indent into
1795+ # account, something like this (which looks right) won't work as expected:
1796+ #
1797+ # <div>
1798+ # <div markdown="1">
1799+ # Hello World. <-- Is this a Markdown code block or text?
1800+ # </div> <-- Is this a Markdown code block or a real tag?
1801+ # <div>
1802+ #
1803+ # If you don't like this, just don't indent the tag on which
1804+ # you apply the markdown="1" attribute.
1805+ #
1806+ # * If $enclosing_tag_re is not empty, stops at the first unmatched closing
1807+ # tag with that name. Nested tags supported.
1808+ #
1809+ # * If $span is true, text inside must treated as span. So any double
1810+ # newline will be replaced by a single newline so that it does not create
1811+ # paragraphs.
1812+ #
1813+ # Returns an array of that form: ( processed text , remaining text )
1814+ #
1815+ if ($text === '') return array('', '');
1816+
1817+ # Regex to check for the presense of newlines around a block tag.
1818+ $newline_before_re = '/(?:^\n?|\n\n)*$/';
1819+ $newline_after_re =
1820+ '{
1821+ ^ # Start of text following the tag.
1822+ (?>[ ]*<!--.*?-->)? # Optional comment.
1823+ [ ]*\n # Must be followed by newline.
1824+ }xs';
1825+
1826+ # Regex to match any tag.
1827+ $block_tag_re =
1828+ '{
1829+ ( # $2: Capture hole tag.
1830+ </? # Any opening or closing tag.
1831+ (?> # Tag name.
1832+ '.$this->block_tags_re.' |
1833+ '.$this->context_block_tags_re.' |
1834+ '.$this->clean_tags_re.' |
1835+ (?!\s)'.$enclosing_tag_re.'
1836+ )
1837+ (?:
1838+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
1839+ (?>
1840+ ".*?" | # Double quotes (can contain `>`)
1841+ \'.*?\' | # Single quotes (can contain `>`)
1842+ .+? # Anything but quotes and `>`.
1843+ )*?
1844+ )?
1845+ > # End of tag.
1846+ |
1847+ <!-- .*? --> # HTML Comment
1848+ |
1849+ <\?.*?\?> | <%.*?%> # Processing instruction
1850+ |
1851+ <!\[CDATA\[.*?\]\]> # CData Block
1852+ |
1853+ # Code span marker
1854+ `+
1855+ '. ( !$span ? ' # If not in span.
1856+ |
1857+ # Indented code block
1858+ (?> ^[ ]*\n? | \n[ ]*\n )
1859+ [ ]{'.($indent+4).'}[^\n]* \n
1860+ (?>
1861+ (?: [ ]{'.($indent+4).'}[^\n]* | [ ]* ) \n
1862+ )*
1863+ |
1864+ # Fenced code block marker
1865+ (?> ^ | \n )
1866+ [ ]{'.($indent).'}~~~+[ ]*\n
1867+ ' : '' ). ' # End (if not is span).
1868+ )
1869+ }xs';
1870+
1871+
1872+ $depth = 0; # Current depth inside the tag tree.
1873+ $parsed = ""; # Parsed text that will be returned.
1874+
1875+ #
1876+ # Loop through every tag until we find the closing tag of the parent
1877+ # or loop until reaching the end of text if no parent tag specified.
1878+ #
1879+ do {
1880+ #
1881+ # Split the text using the first $tag_match pattern found.
1882+ # Text before pattern will be first in the array, text after
1883+ # pattern will be at the end, and between will be any catches made
1884+ # by the pattern.
1885+ #
1886+ $parts = preg_split($block_tag_re, $text, 2,
1887+ PREG_SPLIT_DELIM_CAPTURE);
1888+
1889+ # If in Markdown span mode, add a empty-string span-level hash
1890+ # after each newline to prevent triggering any block element.
1891+ if ($span) {
1892+ $void = $this->hashPart("", ':');
1893+ $newline = "$void\n";
1894+ $parts[0] = $void . str_replace("\n", $newline, $parts[0]) . $void;
1895+ }
1896+
1897+ $parsed .= $parts[0]; # Text before current tag.
1898+
1899+ # If end of $text has been reached. Stop loop.
1900+ if (count($parts) < 3) {
1901+ $text = "";
1902+ break;
1903+ }
1904+
1905+ $tag = $parts[1]; # Tag to handle.
1906+ $text = $parts[2]; # Remaining text after current tag.
1907+ $tag_re = preg_quote($tag); # For use in a regular expression.
1908+
1909+ #
1910+ # Check for: Code span marker
1911+ #
1912+ if ($tag{0} == "`") {
1913+ # Find corresponding end marker.
1914+ $tag_re = preg_quote($tag);
1915+ if (preg_match('{^(?>.+?|\n(?!\n))*?(?<!`)'.$tag_re.'(?!`)}',
1916+ $text, $matches))
1917+ {
1918+ # End marker found: pass text unchanged until marker.
1919+ $parsed .= $tag . $matches[0];
1920+ $text = substr($text, strlen($matches[0]));
1921+ }
1922+ else {
1923+ # Unmatched marker: just skip it.
1924+ $parsed .= $tag;
1925+ }
1926+ }
1927+ #
1928+ # Check for: Indented code block or fenced code block marker.
1929+ #
1930+ else if ($tag{0} == "\n" || $tag{0} == "~") {
1931+ if ($tag{1} == "\n" || $tag{1} == " ") {
1932+ # Indented code block: pass it unchanged, will be handled
1933+ # later.
1934+ $parsed .= $tag;
1935+ }
1936+ else {
1937+ # Fenced code block marker: find matching end marker.
1938+ $tag_re = preg_quote(trim($tag));
1939+ if (preg_match('{^(?>.*\n)+?'.$tag_re.' *\n}', $text,
1940+ $matches))
1941+ {
1942+ # End marker found: pass text unchanged until marker.
1943+ $parsed .= $tag . $matches[0];
1944+ $text = substr($text, strlen($matches[0]));
1945+ }
1946+ else {
1947+ # No end marker: just skip it.
1948+ $parsed .= $tag;
1949+ }
1950+ }
1951+ }
1952+ #
1953+ # Check for: Opening Block level tag or
1954+ # Opening Context Block tag (like ins and del)
1955+ # used as a block tag (tag is alone on it's line).
1956+ #
1957+ else if (preg_match('{^<(?:'.$this->block_tags_re.')\b}', $tag) ||
1958+ ( preg_match('{^<(?:'.$this->context_block_tags_re.')\b}', $tag) &&
1959+ preg_match($newline_before_re, $parsed) &&
1960+ preg_match($newline_after_re, $text) )
1961+ )
1962+ {
1963+ # Need to parse tag and following text using the HTML parser.
1964+ list($block_text, $text) =
1965+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashBlock", true);
1966+
1967+ # Make sure it stays outside of any paragraph by adding newlines.
1968+ $parsed .= "\n\n$block_text\n\n";
1969+ }
1970+ #
1971+ # Check for: Clean tag (like script, math)
1972+ # HTML Comments, processing instructions.
1973+ #
1974+ else if (preg_match('{^<(?:'.$this->clean_tags_re.')\b}', $tag) ||
1975+ $tag{1} == '!' || $tag{1} == '?')
1976+ {
1977+ # Need to parse tag and following text using the HTML parser.
1978+ # (don't check for markdown attribute)
1979+ list($block_text, $text) =
1980+ $this->_hashHTMLBlocks_inHTML($tag . $text, "hashClean", false);
1981+
1982+ $parsed .= $block_text;
1983+ }
1984+ #
1985+ # Check for: Tag with same name as enclosing tag.
1986+ #
1987+ else if ($enclosing_tag_re !== '' &&
1988+ # Same name as enclosing tag.
1989+ preg_match('{^</?(?:'.$enclosing_tag_re.')\b}', $tag))
1990+ {
1991+ #
1992+ # Increase/decrease nested tag count.
1993+ #
1994+ if ($tag{1} == '/') $depth--;
1995+ else if ($tag{strlen($tag)-2} != '/') $depth++;
1996+
1997+ if ($depth < 0) {
1998+ #
1999+ # Going out of parent element. Clean up and break so we
2000+ # return to the calling function.
2001+ #
2002+ $text = $tag . $text;
2003+ break;
2004+ }
2005+
2006+ $parsed .= $tag;
2007+ }
2008+ else {
2009+ $parsed .= $tag;
2010+ }
2011+ } while ($depth >= 0);
2012+
2013+ return array($parsed, $text);
2014+ }
2015+ function _hashHTMLBlocks_inHTML($text, $hash_method, $md_attr) {
2016+ #
2017+ # Parse HTML, calling _HashHTMLBlocks_InMarkdown for block tags.
2018+ #
2019+ # * Calls $hash_method to convert any blocks.
2020+ # * Stops when the first opening tag closes.
2021+ # * $md_attr indicate if the use of the `markdown="1"` attribute is allowed.
2022+ # (it is not inside clean tags)
2023+ #
2024+ # Returns an array of that form: ( processed text , remaining text )
2025+ #
2026+ if ($text === '') return array('', '');
2027+
2028+ # Regex to match `markdown` attribute inside of a tag.
2029+ $markdown_attr_re = '
2030+ {
2031+ \s* # Eat whitespace before the `markdown` attribute
2032+ markdown
2033+ \s*=\s*
2034+ (?>
2035+ (["\']) # $1: quote delimiter
2036+ (.*?) # $2: attribute value
2037+ \1 # matching delimiter
2038+ |
2039+ ([^\s>]*) # $3: unquoted attribute value
2040+ )
2041+ () # $4: make $3 always defined (avoid warnings)
2042+ }xs';
2043+
2044+ # Regex to match any tag.
2045+ $tag_re = '{
2046+ ( # $2: Capture hole tag.
2047+ </? # Any opening or closing tag.
2048+ [\w:$]+ # Tag name.
2049+ (?:
2050+ (?=[\s"\'/a-zA-Z0-9]) # Allowed characters after tag name.
2051+ (?>
2052+ ".*?" | # Double quotes (can contain `>`)
2053+ \'.*?\' | # Single quotes (can contain `>`)
2054+ .+? # Anything but quotes and `>`.
2055+ )*?
2056+ )?
2057+ > # End of tag.
2058+ |
2059+ <!-- .*? --> # HTML Comment
2060+ |
2061+ <\?.*?\?> | <%.*?%> # Processing instruction
2062+ |
2063+ <!\[CDATA\[.*?\]\]> # CData Block
2064+ )
2065+ }xs';
2066+
2067+ $original_text = $text; # Save original text in case of faliure.
2068+
2069+ $depth = 0; # Current depth inside the tag tree.
2070+ $block_text = ""; # Temporary text holder for current text.
2071+ $parsed = ""; # Parsed text that will be returned.
2072+
2073+ #
2074+ # Get the name of the starting tag.
2075+ # (This pattern makes $base_tag_name_re safe without quoting.)
2076+ #
2077+ if (preg_match('/^<([\w:$]*)\b/', $text, $matches))
2078+ $base_tag_name_re = $matches[1];
2079+
2080+ #
2081+ # Loop through every tag until we find the corresponding closing tag.
2082+ #
2083+ do {
2084+ #
2085+ # Split the text using the first $tag_match pattern found.
2086+ # Text before pattern will be first in the array, text after
2087+ # pattern will be at the end, and between will be any catches made
2088+ # by the pattern.
2089+ #
2090+ $parts = preg_split($tag_re, $text, 2, PREG_SPLIT_DELIM_CAPTURE);
2091+
2092+ if (count($parts) < 3) {
2093+ #
2094+ # End of $text reached with unbalenced tag(s).
2095+ # In that case, we return original text unchanged and pass the
2096+ # first character as filtered to prevent an infinite loop in the
2097+ # parent function.
2098+ #
2099+ return array($original_text{0}, substr($original_text, 1));
2100+ }
2101+
2102+ $block_text .= $parts[0]; # Text before current tag.
2103+ $tag = $parts[1]; # Tag to handle.
2104+ $text = $parts[2]; # Remaining text after current tag.
2105+
2106+ #
2107+ # Check for: Auto-close tag (like <hr/>)
2108+ # Comments and Processing Instructions.
2109+ #
2110+ if (preg_match('{^</?(?:'.$this->auto_close_tags_re.')\b}', $tag) ||
2111+ $tag{1} == '!' || $tag{1} == '?')
2112+ {
2113+ # Just add the tag to the block as if it was text.
2114+ $block_text .= $tag;
2115+ }
2116+ else {
2117+ #
2118+ # Increase/decrease nested tag count. Only do so if
2119+ # the tag's name match base tag's.
2120+ #
2121+ if (preg_match('{^</?'.$base_tag_name_re.'\b}', $tag)) {
2122+ if ($tag{1} == '/') $depth--;
2123+ else if ($tag{strlen($tag)-2} != '/') $depth++;
2124+ }
2125+
2126+ #
2127+ # Check for `markdown="1"` attribute and handle it.
2128+ #
2129+ if ($md_attr &&
2130+ preg_match($markdown_attr_re, $tag, $attr_m) &&
2131+ preg_match('/^1|block|span$/', $attr_m[2] . $attr_m[3]))
2132+ {
2133+ # Remove `markdown` attribute from opening tag.
2134+ $tag = preg_replace($markdown_attr_re, '', $tag);
2135+
2136+ # Check if text inside this tag must be parsed in span mode.
2137+ $this->mode = $attr_m[2] . $attr_m[3];
2138+ $span_mode = $this->mode == 'span' || $this->mode != 'block' &&
2139+ preg_match('{^<(?:'.$this->contain_span_tags_re.')\b}', $tag);
2140+
2141+ # Calculate indent before tag.
2142+ if (preg_match('/(?:^|\n)( *?)(?! ).*?$/', $block_text, $matches)) {
2143+ $strlen = $this->utf8_strlen;
2144+ $indent = $strlen($matches[1], 'UTF-8');
2145+ } else {
2146+ $indent = 0;
2147+ }
2148+
2149+ # End preceding block with this tag.
2150+ $block_text .= $tag;
2151+ $parsed .= $this->$hash_method($block_text);
2152+
2153+ # Get enclosing tag name for the ParseMarkdown function.
2154+ # (This pattern makes $tag_name_re safe without quoting.)
2155+ preg_match('/^<([\w:$]*)\b/', $tag, $matches);
2156+ $tag_name_re = $matches[1];
2157+
2158+ # Parse the content using the HTML-in-Markdown parser.
2159+ list ($block_text, $text)
2160+ = $this->_hashHTMLBlocks_inMarkdown($text, $indent,
2161+ $tag_name_re, $span_mode);
2162+
2163+ # Outdent markdown text.
2164+ if ($indent > 0) {
2165+ $block_text = preg_replace("/^[ ]{1,$indent}/m", "",
2166+ $block_text);
2167+ }
2168+
2169+ # Append tag content to parsed text.
2170+ if (!$span_mode) $parsed .= "\n\n$block_text\n\n";
2171+ else $parsed .= "$block_text";
2172+
2173+ # Start over a new block.
2174+ $block_text = "";
2175+ }
2176+ else $block_text .= $tag;
2177+ }
2178+
2179+ } while ($depth > 0);
2180+
2181+ #
2182+ # Hash last block text that wasn't processed inside the loop.
2183+ #
2184+ $parsed .= $this->$hash_method($block_text);
2185+
2186+ return array($parsed, $text);
2187+ }
2188+
2189+
2190+ function hashClean($text) {
2191+ #
2192+ # Called whenever a tag must be hashed when a function insert a "clean" tag
2193+ # in $text, it pass through this function and is automaticaly escaped,
2194+ # blocking invalid nested overlap.
2195+ #
2196+ return $this->hashPart($text, 'C');
2197+ }
2198+
2199+
2200+ function doHeaders($text) {
2201+ #
2202+ # Redefined to add id attribute support.
2203+ #
2204+ # Setext-style headers:
2205+ # Header 1 {#header1}
2206+ # ========
2207+ #
2208+ # Header 2 {#header2}
2209+ # --------
2210+ #
2211+ $text = preg_replace_callback(
2212+ '{
2213+ (^.+?) # $1: Header text
2214+ (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # $2: Id attribute
2215+ [ ]*\n(=+|-+)[ ]*\n+ # $3: Header footer
2216+ }mx',
2217+ array(&$this, '_doHeaders_callback_setext'), $text);
2218+
2219+ # atx-style headers:
2220+ # # Header 1 {#header1}
2221+ # ## Header 2 {#header2}
2222+ # ## Header 2 with closing hashes ## {#header3}
2223+ # ...
2224+ # ###### Header 6 {#header2}
2225+ #
2226+ $text = preg_replace_callback('{
2227+ ^(\#{1,6}) # $1 = string of #\'s
2228+ [ ]*
2229+ (.+?) # $2 = Header text
2230+ [ ]*
2231+ \#* # optional closing #\'s (not counted)
2232+ (?:[ ]+\{\#([-_:a-zA-Z0-9]+)\})? # id attribute
2233+ [ ]*
2234+ \n+
2235+ }xm',
2236+ array(&$this, '_doHeaders_callback_atx'), $text);
2237+
2238+ return $text;
2239+ }
2240+ function _doHeaders_attr($attr) {
2241+ if (empty($attr)) return "";
2242+ return " id=\"$attr\"";
2243+ }
2244+ function _doHeaders_callback_setext($matches) {
2245+ if ($matches[3] == '-' && preg_match('{^- }', $matches[1]))
2246+ return $matches[0];
2247+ $level = $matches[3]{0} == '=' ? 1 : 2;
2248+ $attr = $this->_doHeaders_attr($id =& $matches[2]);
2249+ $block = "<h$level$attr>".$this->runSpanGamut($matches[1])."</h$level>";
2250+ return "\n" . $this->hashBlock($block) . "\n\n";
2251+ }
2252+ function _doHeaders_callback_atx($matches) {
2253+ $level = strlen($matches[1]);
2254+ $attr = $this->_doHeaders_attr($id =& $matches[3]);
2255+ $block = "<h$level$attr>".$this->runSpanGamut($matches[2])."</h$level>";
2256+ return "\n" . $this->hashBlock($block) . "\n\n";
2257+ }
2258+
2259+
2260+ function doTables($text) {
2261+ #
2262+ # Form HTML tables.
2263+ #
2264+ $less_than_tab = $this->tab_width - 1;
2265+ #
2266+ # Find tables with leading pipe.
2267+ #
2268+ # | Header 1 | Header 2
2269+ # | -------- | --------
2270+ # | Cell 1 | Cell 2
2271+ # | Cell 3 | Cell 4
2272+ #
2273+ $text = preg_replace_callback('
2274+ {
2275+ ^ # Start of a line
2276+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
2277+ [|] # Optional leading pipe (present)
2278+ (.+) \n # $1: Header row (at least one pipe)
2279+
2280+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
2281+ [|] ([ ]*[-:]+[-| :]*) \n # $2: Header underline
2282+
2283+ ( # $3: Cells
2284+ (?>
2285+ [ ]* # Allowed whitespace.
2286+ [|] .* \n # Row content.
2287+ )*
2288+ )
2289+ (?=\n|\Z) # Stop at final double newline.
2290+ }xm',
2291+ array(&$this, '_doTable_leadingPipe_callback'), $text);
2292+
2293+ #
2294+ # Find tables without leading pipe.
2295+ #
2296+ # Header 1 | Header 2
2297+ # -------- | --------
2298+ # Cell 1 | Cell 2
2299+ # Cell 3 | Cell 4
2300+ #
2301+ $text = preg_replace_callback('
2302+ {
2303+ ^ # Start of a line
2304+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
2305+ (\S.*[|].*) \n # $1: Header row (at least one pipe)
2306+
2307+ [ ]{0,'.$less_than_tab.'} # Allowed whitespace.
2308+ ([-:]+[ ]*[|][-| :]*) \n # $2: Header underline
2309+
2310+ ( # $3: Cells
2311+ (?>
2312+ .* [|] .* \n # Row content
2313+ )*
2314+ )
2315+ (?=\n|\Z) # Stop at final double newline.
2316+ }xm',
2317+ array(&$this, '_DoTable_callback'), $text);
2318+
2319+ return $text;
2320+ }
2321+ function _doTable_leadingPipe_callback($matches) {
2322+ $head = $matches[1];
2323+ $underline = $matches[2];
2324+ $content = $matches[3];
2325+
2326+ # Remove leading pipe for each row.
2327+ $content = preg_replace('/^ *[|]/m', '', $content);
2328+
2329+ return $this->_doTable_callback(array($matches[0], $head, $underline, $content));
2330+ }
2331+ function _doTable_callback($matches) {
2332+ $head = $matches[1];
2333+ $underline = $matches[2];
2334+ $content = $matches[3];
2335+
2336+ # Remove any tailing pipes for each line.
2337+ $head = preg_replace('/[|] *$/m', '', $head);
2338+ $underline = preg_replace('/[|] *$/m', '', $underline);
2339+ $content = preg_replace('/[|] *$/m', '', $content);
2340+
2341+ # Reading alignement from header underline.
2342+ $separators = preg_split('/ *[|] */', $underline);
2343+ foreach ($separators as $n => $s) {
2344+ if (preg_match('/^ *-+: *$/', $s)) $attr[$n] = ' align="right"';
2345+ else if (preg_match('/^ *:-+: *$/', $s))$attr[$n] = ' align="center"';
2346+ else if (preg_match('/^ *:-+ *$/', $s)) $attr[$n] = ' align="left"';
2347+ else $attr[$n] = '';
2348+ }
2349+
2350+ # Parsing span elements, including code spans, character escapes,
2351+ # and inline HTML tags, so that pipes inside those gets ignored.
2352+ $head = $this->parseSpan($head);
2353+ $headers = preg_split('/ *[|] */', $head);
2354+ $col_count = count($headers);
2355+
2356+ # Write column headers.
2357+ $text = "<table>\n";
2358+ $text .= "<thead>\n";
2359+ $text .= "<tr>\n";
2360+ foreach ($headers as $n => $header)
2361+ $text .= " <th$attr[$n]>".$this->runSpanGamut(trim($header))."</th>\n";
2362+ $text .= "</tr>\n";
2363+ $text .= "</thead>\n";
2364+
2365+ # Split content by row.
2366+ $rows = explode("\n", trim($content, "\n"));
2367+
2368+ $text .= "<tbody>\n";
2369+ foreach ($rows as $row) {
2370+ # Parsing span elements, including code spans, character escapes,
2371+ # and inline HTML tags, so that pipes inside those gets ignored.
2372+ $row = $this->parseSpan($row);
2373+
2374+ # Split row by cell.
2375+ $row_cells = preg_split('/ *[|] */', $row, $col_count);
2376+ $row_cells = array_pad($row_cells, $col_count, '');
2377+
2378+ $text .= "<tr>\n";
2379+ foreach ($row_cells as $n => $cell)
2380+ $text .= " <td$attr[$n]>".$this->runSpanGamut(trim($cell))."</td>\n";
2381+ $text .= "</tr>\n";
2382+ }
2383+ $text .= "</tbody>\n";
2384+ $text .= "</table>";
2385+
2386+ return $this->hashBlock($text) . "\n";
2387+ }
2388+
2389+
2390+ function doDefLists($text) {
2391+ #
2392+ # Form HTML definition lists.
2393+ #
2394+ $less_than_tab = $this->tab_width - 1;
2395+
2396+ # Re-usable pattern to match any entire dl list:
2397+ $whole_list_re = '(?>
2398+ ( # $1 = whole list
2399+ ( # $2
2400+ [ ]{0,'.$less_than_tab.'}
2401+ ((?>.*\S.*\n)+) # $3 = defined term
2402+ \n?
2403+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2404+ )
2405+ (?s:.+?)
2406+ ( # $4
2407+ \z
2408+ |
2409+ \n{2,}
2410+ (?=\S)
2411+ (?! # Negative lookahead for another term
2412+ [ ]{0,'.$less_than_tab.'}
2413+ (?: \S.*\n )+? # defined term
2414+ \n?
2415+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2416+ )
2417+ (?! # Negative lookahead for another definition
2418+ [ ]{0,'.$less_than_tab.'}:[ ]+ # colon starting definition
2419+ )
2420+ )
2421+ )
2422+ )'; // mx
2423+
2424+ $text = preg_replace_callback('{
2425+ (?>\A\n?|(?<=\n\n))
2426+ '.$whole_list_re.'
2427+ }mx',
2428+ array(&$this, '_doDefLists_callback'), $text);
2429+
2430+ return $text;
2431+ }
2432+ function _doDefLists_callback($matches) {
2433+ # Re-usable patterns to match list item bullets and number markers:
2434+ $list = $matches[1];
2435+
2436+ # Turn double returns into triple returns, so that we can make a
2437+ # paragraph for the last item in a list, if necessary:
2438+ $result = trim($this->processDefListItems($list));
2439+ $result = "<dl>\n" . $result . "\n</dl>";
2440+ return $this->hashBlock($result) . "\n\n";
2441+ }
2442+
2443+
2444+ function processDefListItems($list_str) {
2445+ #
2446+ # Process the contents of a single definition list, splitting it
2447+ # into individual term and definition list items.
2448+ #
2449+ $less_than_tab = $this->tab_width - 1;
2450+
2451+ # trim trailing blank lines:
2452+ $list_str = preg_replace("/\n{2,}\\z/", "\n", $list_str);
2453+
2454+ # Process definition terms.
2455+ $list_str = preg_replace_callback('{
2456+ (?>\A\n?|\n\n+) # leading line
2457+ ( # definition terms = $1
2458+ [ ]{0,'.$less_than_tab.'} # leading whitespace
2459+ (?![:][ ]|[ ]) # negative lookahead for a definition
2460+ # mark (colon) or more whitespace.
2461+ (?> \S.* \n)+? # actual term (not whitespace).
2462+ )
2463+ (?=\n?[ ]{0,3}:[ ]) # lookahead for following line feed
2464+ # with a definition mark.
2465+ }xm',
2466+ array(&$this, '_processDefListItems_callback_dt'), $list_str);
2467+
2468+ # Process actual definitions.
2469+ $list_str = preg_replace_callback('{
2470+ \n(\n+)? # leading line = $1
2471+ ( # marker space = $2
2472+ [ ]{0,'.$less_than_tab.'} # whitespace before colon
2473+ [:][ ]+ # definition mark (colon)
2474+ )
2475+ ((?s:.+?)) # definition text = $3
2476+ (?= \n+ # stop at next definition mark,
2477+ (?: # next term or end of text
2478+ [ ]{0,'.$less_than_tab.'} [:][ ] |
2479+ <dt> | \z
2480+ )
2481+ )
2482+ }xm',
2483+ array(&$this, '_processDefListItems_callback_dd'), $list_str);
2484+
2485+ return $list_str;
2486+ }
2487+ function _processDefListItems_callback_dt($matches) {
2488+ $terms = explode("\n", trim($matches[1]));
2489+ $text = '';
2490+ foreach ($terms as $term) {
2491+ $term = $this->runSpanGamut(trim($term));
2492+ $text .= "\n<dt>" . $term . "</dt>";
2493+ }
2494+ return $text . "\n";
2495+ }
2496+ function _processDefListItems_callback_dd($matches) {
2497+ $leading_line = $matches[1];
2498+ $marker_space = $matches[2];
2499+ $def = $matches[3];
2500+
2501+ if ($leading_line || preg_match('/\n{2,}/', $def)) {
2502+ # Replace marker with the appropriate whitespace indentation
2503+ $def = str_repeat(' ', strlen($marker_space)) . $def;
2504+ $def = $this->runBlockGamut($this->outdent($def . "\n\n"));
2505+ $def = "\n". $def ."\n";
2506+ }
2507+ else {
2508+ $def = rtrim($def);
2509+ $def = $this->runSpanGamut($this->outdent($def));
2510+ }
2511+
2512+ return "\n<dd>" . $def . "</dd>\n";
2513+ }
2514+
2515+
2516+ function doFencedCodeBlocks($text) {
2517+ #
2518+ # Adding the fenced code block syntax to regular Markdown:
2519+ #
2520+ # ~~~
2521+ # Code block
2522+ # ~~~
2523+ #
2524+ $less_than_tab = $this->tab_width;
2525+
2526+ $text = preg_replace_callback('{
2527+ (?:\n|\A)
2528+ # 1: Opening marker
2529+ (
2530+ ~{3,} # Marker: three tilde or more.
2531+ )
2532+ [ ]* \n # Whitespace and newline following marker.
2533+
2534+ # 2: Content
2535+ (
2536+ (?>
2537+ (?!\1 [ ]* \n) # Not a closing marker.
2538+ .*\n+
2539+ )+
2540+ )
2541+
2542+ # Closing marker.
2543+ \1 [ ]* \n
2544+ }xm',
2545+ array(&$this, '_doFencedCodeBlocks_callback'), $text);
2546+
2547+ return $text;
2548+ }
2549+ function _doFencedCodeBlocks_callback($matches) {
2550+ $codeblock = $matches[2];
2551+ $codeblock = htmlspecialchars($codeblock, ENT_NOQUOTES);
2552+ $codeblock = preg_replace_callback('/^\n+/',
2553+ array(&$this, '_doFencedCodeBlocks_newlines'), $codeblock);
2554+ $codeblock = "<pre><code>$codeblock</code></pre>";
2555+ return "\n\n".$this->hashBlock($codeblock)."\n\n";
2556+ }
2557+ function _doFencedCodeBlocks_newlines($matches) {
2558+ return str_repeat("<br$this->empty_element_suffix",
2559+ strlen($matches[0]));
2560+ }
2561+
2562+
2563+ #
2564+ # Redefining emphasis markers so that emphasis by underscore does not
2565+ # work in the middle of a word.
2566+ #
2567+ var $em_relist = array(
2568+ '' => '(?:(?<!\*)\*(?!\*)|(?<![a-zA-Z0-9_])_(?!_))(?=\S)(?![.,:;]\s)',
2569+ '*' => '(?<=\S)(?<!\*)\*(?!\*)',
2570+ '_' => '(?<=\S)(?<!_)_(?![a-zA-Z0-9_])',
2571+ );
2572+ var $strong_relist = array(
2573+ '' => '(?:(?<!\*)\*\*(?!\*)|(?<![a-zA-Z0-9_])__(?!_))(?=\S)(?![.,:;]\s)',
2574+ '**' => '(?<=\S)(?<!\*)\*\*(?!\*)',
2575+ '__' => '(?<=\S)(?<!_)__(?![a-zA-Z0-9_])',
2576+ );
2577+ var $em_strong_relist = array(
2578+ '' => '(?:(?<!\*)\*\*\*(?!\*)|(?<![a-zA-Z0-9_])___(?!_))(?=\S)(?![.,:;]\s)',
2579+ '***' => '(?<=\S)(?<!\*)\*\*\*(?!\*)',
2580+ '___' => '(?<=\S)(?<!_)___(?![a-zA-Z0-9_])',
2581+ );
2582+
2583+
2584+ function formParagraphs($text) {
2585+ #
2586+ # Params:
2587+ # $text - string to process with html <p> tags
2588+ #
2589+ # Strip leading and trailing lines:
2590+ $text = preg_replace('/\A\n+|\n+\z/', '', $text);
2591+
2592+ $grafs = preg_split('/\n{2,}/', $text, -1, PREG_SPLIT_NO_EMPTY);
2593+
2594+ #
2595+ # Wrap <p> tags and unhashify HTML blocks
2596+ #
2597+ foreach ($grafs as $key => $value) {
2598+ $value = trim($this->runSpanGamut($value));
2599+
2600+ # Check if this should be enclosed in a paragraph.
2601+ # Clean tag hashes & block tag hashes are left alone.
2602+ $is_p = !preg_match('/^B\x1A[0-9]+B|^C\x1A[0-9]+C$/', $value);
2603+
2604+ if ($is_p) {
2605+ $value = "<p>$value</p>";
2606+ }
2607+ $grafs[$key] = $value;
2608+ }
2609+
2610+ # Join grafs in one text, then unhash HTML tags.
2611+ $text = implode("\n\n", $grafs);
2612+
2613+ # Finish by removing any tag hashes still present in $text.
2614+ $text = $this->unhash($text);
2615+
2616+ return $text;
2617+ }
2618+
2619+
2620+ ### Footnotes
2621+
2622+ function stripFootnotes($text) {
2623+ #
2624+ # Strips link definitions from text, stores the URLs and titles in
2625+ # hash references.
2626+ #
2627+ $less_than_tab = $this->tab_width - 1;
2628+
2629+ # Link defs are in the form: [^id]: url "optional title"
2630+ $text = preg_replace_callback('{
2631+ ^[ ]{0,'.$less_than_tab.'}\[\^(.+?)\][ ]?: # note_id = $1
2632+ [ ]*
2633+ \n? # maybe *one* newline
2634+ ( # text = $2 (no blank lines allowed)
2635+ (?:
2636+ .+ # actual text
2637+ |
2638+ \n # newlines but
2639+ (?!\[\^.+?\]:\s)# negative lookahead for footnote marker.
2640+ (?!\n+[ ]{0,3}\S)# ensure line is not blank and followed
2641+ # by non-indented content
2642+ )*
2643+ )
2644+ }xm',
2645+ array(&$this, '_stripFootnotes_callback'),
2646+ $text);
2647+ return $text;
2648+ }
2649+ function _stripFootnotes_callback($matches) {
2650+ $note_id = $this->fn_id_prefix . $matches[1];
2651+ $this->footnotes[$note_id] = $this->outdent($matches[2]);
2652+ return ''; # String that will replace the block
2653+ }
2654+
2655+
2656+ function doFootnotes($text) {
2657+ #
2658+ # Replace footnote references in $text [^id] with a special text-token
2659+ # which will be replaced by the actual footnote marker in appendFootnotes.
2660+ #
2661+ if (!$this->in_anchor) {
2662+ $text = preg_replace('{\[\^(.+?)\]}', "F\x1Afn:\\1\x1A:", $text);
2663+ }
2664+ return $text;
2665+ }
2666+
2667+
2668+ function appendFootnotes($text) {
2669+ #
2670+ # Append footnote list to text.
2671+ #
2672+ $text = preg_replace_callback('{F\x1Afn:(.*?)\x1A:}',
2673+ array(&$this, '_appendFootnotes_callback'), $text);
2674+
2675+ if (!empty($this->footnotes_ordered)) {
2676+ $text .= "\n\n";
2677+ $text .= "<div class=\"footnotes\">\n";
2678+ $text .= "<hr". MARKDOWN_EMPTY_ELEMENT_SUFFIX ."\n";
2679+ $text .= "<ol>\n\n";
2680+
2681+ $attr = " rev=\"footnote\"";
2682+ if ($this->fn_backlink_class != "") {
2683+ $class = $this->fn_backlink_class;
2684+ $class = $this->encodeAttribute($class);
2685+ $attr .= " class=\"$class\"";
2686+ }
2687+ if ($this->fn_backlink_title != "") {
2688+ $title = $this->fn_backlink_title;
2689+ $title = $this->encodeAttribute($title);
2690+ $attr .= " title=\"$title\"";
2691+ }
2692+ $num = 0;
2693+

216 more lines aren’t shown here.

examples/includes/PHP-Markdown-Extra-1.2.3/markdown.php.orig+2909−0

This diff is large: its 2910 lines aren’t shown here.

examples/includes/PHP-SmartyPants-1.5.1e/PHP SmartyPants Readme.txt+394−0

This diff is large: its 395 lines aren’t shown here.

examples/includes/PHP-SmartyPants-1.5.1e/smartypants.php+860−0

This diff is large: its 861 lines aren’t shown here.

examples/includes/geshi/contrib/aliased.php+124−0

This diff is large: its 125 lines aren’t shown here.

examples/includes/geshi/contrib/cssgen.php+456−0

This diff is large: its 457 lines aren’t shown here.

examples/includes/geshi/contrib/cssgen2.php+59−0

This diff is large: its 60 lines aren’t shown here.

examples/includes/geshi/contrib/example.php+217−0

This diff is large: its 218 lines aren’t shown here.

examples/includes/geshi/contrib/langcheck.php+666−0

This diff is large: its 667 lines aren’t shown here.

examples/includes/geshi/docs/BUGS+29−0

This diff is large: its 30 lines aren’t shown here.

examples/includes/geshi/docs/CHANGES+682−0

This diff is large: its 683 lines aren’t shown here.

examples/includes/geshi/docs/COPYING+340−0

This diff is large: its 341 lines aren’t shown here.

examples/includes/geshi/docs/README+33−0

This diff is large: its 34 lines aren’t shown here.

examples/includes/geshi/docs/THANKS+163−0

This diff is large: its 164 lines aren’t shown here.

examples/includes/geshi/docs/TODO+71−0

This diff is large: its 72 lines aren’t shown here.

examples/includes/geshi/docs/api/__filesource/fsource_geshi_core_geshi.php.html+4616−0

This diff is large: its 4617 lines aren’t shown here.

examples/includes/geshi/docs/api/blank.html+13−0

This diff is large: its 14 lines aren’t shown here.

examples/includes/geshi/docs/api/classtrees_geshi.html+24−0

This diff is large: its 25 lines aren’t shown here.

examples/includes/geshi/docs/api/elementindex.html+867−0

This diff is large: its 868 lines aren’t shown here.

examples/includes/geshi/docs/api/elementindex_geshi.html+864−0

This diff is large: its 865 lines aren’t shown here.

examples/includes/geshi/docs/api/errors.html+20−0

This diff is large: its 21 lines aren’t shown here.

examples/includes/geshi/docs/api/geshi/core/GeSHi.html+2676−0

This diff is large: its 2677 lines aren’t shown here.

examples/includes/geshi/docs/api/geshi/core/_geshi.php.html+478−0

This diff is large: its 479 lines aren’t shown here.

examples/includes/geshi/docs/api/index.html+24−0

This diff is large: its 25 lines aren’t shown here.

examples/includes/geshi/docs/api/li_geshi.html+46−0

This diff is large: its 47 lines aren’t shown here.

examples/includes/geshi/docs/api/media/banner.css+33−0

This diff is large: its 34 lines aren’t shown here.

examples/includes/geshi/docs/api/media/images/AbstractClass.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/AbstractClass_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/AbstractMethod.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/AbstractPrivateClass.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/AbstractPrivateClass_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/AbstractPrivateMethod.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Class.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Class_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Constant.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Constructor.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Destructor.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Function.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Global.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/I.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Index.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Interface.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Interface_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/L.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Lminus.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Lplus.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Method.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Page.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Page_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/PrivateClass.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/PrivateClass_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/PrivateMethod.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/PrivateVariable.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/StaticMethod.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/StaticVariable.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/T.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Tminus.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Tplus.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/Variable.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/blank.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/class_folder.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/empty.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/file.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/folder.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/function_folder.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/next_button.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/next_button_disabled.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/package.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/package_folder.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/previous_button.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/previous_button_disabled.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/private_class_logo.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/tutorial.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/tutorial_folder.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/images/up_button.png+0−0

Binary file not shown.

examples/includes/geshi/docs/api/media/stylesheet.css+145−0

This diff is large: its 146 lines aren’t shown here.

examples/includes/geshi/docs/api/packages.html+29−0

This diff is large: its 30 lines aren’t shown here.

examples/includes/geshi/docs/api/todolist.html+42−0

This diff is large: its 43 lines aren’t shown here.

examples/includes/geshi/docs/geshi-doc.html+4051−0

This diff is large: its 4052 lines aren’t shown here.

examples/includes/geshi/docs/geshi-doc.txt+1740−0

This diff is large: its 1741 lines aren’t shown here.

examples/includes/geshi/docs/phpdoc.ini+90−0

This diff is large: its 91 lines aren’t shown here.

examples/includes/geshi/geshi.php+4619−0

This diff is large: its 4620 lines aren’t shown here.

examples/includes/geshi/geshi/abap.php+1419−0

This diff is large: its 1420 lines aren’t shown here.

examples/includes/geshi/geshi/actionscript.php+197−0

This diff is large: its 198 lines aren’t shown here.

examples/includes/geshi/geshi/actionscript3.php+467−0

This diff is large: its 468 lines aren’t shown here.

examples/includes/geshi/geshi/ada.php+133−0

This diff is large: its 134 lines aren’t shown here.

examples/includes/geshi/geshi/apache.php+206−0

This diff is large: its 207 lines aren’t shown here.

examples/includes/geshi/geshi/applescript.php+157−0

This diff is large: its 158 lines aren’t shown here.

examples/includes/geshi/geshi/apt_sources.php+144−0

This diff is large: its 145 lines aren’t shown here.

examples/includes/geshi/geshi/asm.php+225−0

This diff is large: its 226 lines aren’t shown here.

examples/includes/geshi/geshi/asp.php+164−0

This diff is large: its 165 lines aren’t shown here.

examples/includes/geshi/geshi/autoit.php+1171−0

This diff is large: its 1172 lines aren’t shown here.

examples/includes/geshi/geshi/avisynth.php+194−0

This diff is large: its 195 lines aren’t shown here.

examples/includes/geshi/geshi/bash.php+282−0

This diff is large: its 283 lines aren’t shown here.

examples/includes/geshi/geshi/basic4gl.php+341−0

This diff is large: its 342 lines aren’t shown here.

examples/includes/geshi/geshi/bf.php+114−0

This diff is large: its 115 lines aren’t shown here.

examples/includes/geshi/geshi/blitzbasic.php+185−0

This diff is large: its 186 lines aren’t shown here.

examples/includes/geshi/geshi/bnf.php+110−0

This diff is large: its 111 lines aren’t shown here.

examples/includes/geshi/geshi/boo.php+217−0

This diff is large: its 218 lines aren’t shown here.

examples/includes/geshi/geshi/c.php+188−0

This diff is large: its 189 lines aren’t shown here.

examples/includes/geshi/geshi/c_mac.php+212−0

This diff is large: its 213 lines aren’t shown here.

examples/includes/geshi/geshi/caddcl.php+126−0

This diff is large: its 127 lines aren’t shown here.

examples/includes/geshi/geshi/cadlisp.php+186−0

This diff is large: its 187 lines aren’t shown here.

examples/includes/geshi/geshi/cfdg.php+124−0

This diff is large: its 125 lines aren’t shown here.

examples/includes/geshi/geshi/cfm.php+299−0

This diff is large: its 300 lines aren’t shown here.

examples/includes/geshi/geshi/cil.php+196−0

This diff is large: its 197 lines aren’t shown here.

examples/includes/geshi/geshi/cobol.php+244−0

This diff is large: its 245 lines aren’t shown here.

examples/includes/geshi/geshi/cpp-qt.php+315−0

This diff is large: its 316 lines aren’t shown here.

examples/includes/geshi/geshi/cpp.php+226−0

This diff is large: its 227 lines aren’t shown here.

examples/includes/geshi/geshi/csharp.php+249−0

This diff is large: its 250 lines aren’t shown here.

examples/includes/geshi/geshi/css.php+212−0

This diff is large: its 213 lines aren’t shown here.

examples/includes/geshi/geshi/d.php+272−0

This diff is large: its 273 lines aren’t shown here.

examples/includes/geshi/geshi/dcs.php+185−0

This diff is large: its 186 lines aren’t shown here.

examples/includes/geshi/geshi/delphi.php+289−0

This diff is large: its 290 lines aren’t shown here.

examples/includes/geshi/geshi/diff.php+196−0

This diff is large: its 197 lines aren’t shown here.

examples/includes/geshi/geshi/div.php+126−0

This diff is large: its 127 lines aren’t shown here.

examples/includes/geshi/geshi/dos.php+198−0

This diff is large: its 199 lines aren’t shown here.

examples/includes/geshi/geshi/dot.php+164−0

This diff is large: its 165 lines aren’t shown here.

examples/includes/geshi/geshi/eiffel.php+395−0

This diff is large: its 396 lines aren’t shown here.

examples/includes/geshi/geshi/email.php+209−0

This diff is large: its 210 lines aren’t shown here.

examples/includes/geshi/geshi/fortran.php+160−0

This diff is large: its 161 lines aren’t shown here.

examples/includes/geshi/geshi/freebasic.php+141−0

This diff is large: its 142 lines aren’t shown here.

examples/includes/geshi/geshi/genero.php+463−0

This diff is large: its 464 lines aren’t shown here.

examples/includes/geshi/geshi/gettext.php+97−0

This diff is large: its 98 lines aren’t shown here.

examples/includes/geshi/geshi/glsl.php+205−0

This diff is large: its 206 lines aren’t shown here.

examples/includes/geshi/geshi/gml.php+506−0

This diff is large: its 507 lines aren’t shown here.

examples/includes/geshi/geshi/gnuplot.php+296−0

This diff is large: its 297 lines aren’t shown here.

examples/includes/geshi/geshi/groovy.php+1011−0

This diff is large: its 1012 lines aren’t shown here.

examples/includes/geshi/geshi/haskell.php+198−0

This diff is large: its 199 lines aren’t shown here.

examples/includes/geshi/geshi/hq9plus.php+104−0

This diff is large: its 105 lines aren’t shown here.

examples/includes/geshi/geshi/html4strict.php+203−0

This diff is large: its 204 lines aren’t shown here.

examples/includes/geshi/geshi/idl.php+123−0

This diff is large: its 124 lines aren’t shown here.

examples/includes/geshi/geshi/ini.php+128−0

This diff is large: its 129 lines aren’t shown here.

examples/includes/geshi/geshi/inno.php+212−0

This diff is large: its 213 lines aren’t shown here.

examples/includes/geshi/geshi/intercal.php+122−0

This diff is large: its 123 lines aren’t shown here.

examples/includes/geshi/geshi/io.php+138−0

This diff is large: its 139 lines aren’t shown here.

examples/includes/geshi/geshi/java.php+983−0

This diff is large: its 984 lines aren’t shown here.

examples/includes/geshi/geshi/java5.php+1031−0

This diff is large: its 1032 lines aren’t shown here.

examples/includes/geshi/geshi/javascript.php+150−0

This diff is large: its 151 lines aren’t shown here.

examples/includes/geshi/geshi/kixtart.php+329−0

This diff is large: its 330 lines aren’t shown here.

examples/includes/geshi/geshi/klonec.php+282−0

This diff is large: its 283 lines aren’t shown here.

examples/includes/geshi/geshi/klonecpp.php+310−0

This diff is large: its 311 lines aren’t shown here.

examples/includes/geshi/geshi/latex.php+209−0

This diff is large: its 210 lines aren’t shown here.

examples/includes/geshi/geshi/lisp.php+144−0

This diff is large: its 145 lines aren’t shown here.

examples/includes/geshi/geshi/locobasic.php+130−0

This diff is large: its 131 lines aren’t shown here.

examples/includes/geshi/geshi/lolcode.php+152−0

This diff is large: its 153 lines aren’t shown here.

examples/includes/geshi/geshi/lotusformulas.php+318−0

This diff is large: its 319 lines aren’t shown here.

examples/includes/geshi/geshi/lotusscript.php+191−0

This diff is large: its 192 lines aren’t shown here.

examples/includes/geshi/geshi/lscript.php+387−0

This diff is large: its 388 lines aren’t shown here.

examples/includes/geshi/geshi/lsl2.php+898−0

This diff is large: its 899 lines aren’t shown here.

examples/includes/geshi/geshi/lua.php+137−0

This diff is large: its 138 lines aren’t shown here.

examples/includes/geshi/geshi/m68k.php+143−0

This diff is large: its 144 lines aren’t shown here.

examples/includes/geshi/geshi/make.php+151−0

This diff is large: its 152 lines aren’t shown here.

examples/includes/geshi/geshi/matlab.php+227−0

This diff is large: its 228 lines aren’t shown here.

examples/includes/geshi/geshi/mirc.php+173−0

This diff is large: its 174 lines aren’t shown here.

examples/includes/geshi/geshi/modula3.php+135−0

This diff is large: its 136 lines aren’t shown here.

examples/includes/geshi/geshi/mpasm.php+164−0

This diff is large: its 165 lines aren’t shown here.

examples/includes/geshi/geshi/mxml.php+145−0

This diff is large: its 146 lines aren’t shown here.

examples/includes/geshi/geshi/mysql.php+475−0

This diff is large: its 476 lines aren’t shown here.

examples/includes/geshi/geshi/nsis.php+351−0

This diff is large: its 352 lines aren’t shown here.

examples/includes/geshi/geshi/objc.php+358−0

This diff is large: its 359 lines aren’t shown here.

examples/includes/geshi/geshi/ocaml-brief.php+112−0

This diff is large: its 113 lines aren’t shown here.

examples/includes/geshi/geshi/ocaml.php+174−0

This diff is large: its 175 lines aren’t shown here.

examples/includes/geshi/geshi/oobas.php+135−0

This diff is large: its 136 lines aren’t shown here.

examples/includes/geshi/geshi/oracle11.php+614−0

This diff is large: its 615 lines aren’t shown here.

examples/includes/geshi/geshi/oracle8.php+496−0

This diff is large: its 497 lines aren’t shown here.

examples/includes/geshi/geshi/pascal.php+152−0

This diff is large: its 153 lines aren’t shown here.

examples/includes/geshi/geshi/per.php+302−0

This diff is large: its 303 lines aren’t shown here.

examples/includes/geshi/geshi/perl.php+213−0

This diff is large: its 214 lines aren’t shown here.

examples/includes/geshi/geshi/php-brief.php+202−0

This diff is large: its 203 lines aren’t shown here.

examples/includes/geshi/geshi/php.php+1094−0

This diff is large: its 1095 lines aren’t shown here.

examples/includes/geshi/geshi/pic16.php+141−0

This diff is large: its 142 lines aren’t shown here.

examples/includes/geshi/geshi/pixelbender.php+176−0

This diff is large: its 177 lines aren’t shown here.

examples/includes/geshi/geshi/plsql.php+256−0

This diff is large: its 257 lines aren’t shown here.

examples/includes/geshi/geshi/povray.php+199−0

This diff is large: its 200 lines aren’t shown here.

examples/includes/geshi/geshi/powershell.php+279−0

This diff is large: its 280 lines aren’t shown here.

examples/includes/geshi/geshi/progress.php+479−0

This diff is large: its 480 lines aren’t shown here.

examples/includes/geshi/geshi/prolog.php+143−0

This diff is large: its 144 lines aren’t shown here.

examples/includes/geshi/geshi/providex.php+299−0

This diff is large: its 300 lines aren’t shown here.

examples/includes/geshi/geshi/python.php+237−0

This diff is large: its 238 lines aren’t shown here.

examples/includes/geshi/geshi/qbasic.php+151−0

This diff is large: its 152 lines aren’t shown here.

examples/includes/geshi/geshi/rails.php+406−0

This diff is large: its 407 lines aren’t shown here.

examples/includes/geshi/geshi/rebol.php+196−0

This diff is large: its 197 lines aren’t shown here.

examples/includes/geshi/geshi/reg.php+233−0

This diff is large: its 234 lines aren’t shown here.

examples/includes/geshi/geshi/robots.php+98−0

This diff is large: its 99 lines aren’t shown here.

examples/includes/geshi/geshi/ruby.php+226−0

This diff is large: its 227 lines aren’t shown here.

examples/includes/geshi/geshi/sas.php+290−0

This diff is large: its 291 lines aren’t shown here.

examples/includes/geshi/geshi/scala.php+122−0

This diff is large: its 123 lines aren’t shown here.

examples/includes/geshi/geshi/scheme.php+170−0

This diff is large: its 171 lines aren’t shown here.

examples/includes/geshi/geshi/scilab.php+295−0

This diff is large: its 296 lines aren’t shown here.

examples/includes/geshi/geshi/sdlbasic.php+165−0

This diff is large: its 166 lines aren’t shown here.

examples/includes/geshi/geshi/smalltalk.php+160−0

This diff is large: its 161 lines aren’t shown here.

examples/includes/geshi/geshi/smarty.php+192−0

This diff is large: its 193 lines aren’t shown here.

examples/includes/geshi/geshi/sql.php+140−0

This diff is large: its 141 lines aren’t shown here.

examples/includes/geshi/geshi/tcl.php+194−0

This diff is large: its 195 lines aren’t shown here.

examples/includes/geshi/geshi/teraterm.php+317−0

This diff is large: its 318 lines aren’t shown here.

examples/includes/geshi/geshi/text.php+84−0

This diff is large: its 85 lines aren’t shown here.

examples/includes/geshi/geshi/thinbasic.php+868−0

This diff is large: its 869 lines aren’t shown here.

examples/includes/geshi/geshi/tsql.php+378−0

This diff is large: its 379 lines aren’t shown here.

examples/includes/geshi/geshi/typoscript.php+300−0

This diff is large: its 301 lines aren’t shown here.

examples/includes/geshi/geshi/vb.php+133−0

This diff is large: its 134 lines aren’t shown here.

examples/includes/geshi/geshi/vbnet.php+201−0

This diff is large: its 202 lines aren’t shown here.

examples/includes/geshi/geshi/verilog.php+173−0

This diff is large: its 174 lines aren’t shown here.

examples/includes/geshi/geshi/vhdl.php+144−0

This diff is large: its 145 lines aren’t shown here.

examples/includes/geshi/geshi/vim.php+185−0

This diff is large: its 186 lines aren’t shown here.

examples/includes/geshi/geshi/visualfoxpro.php+456−0

This diff is large: its 457 lines aren’t shown here.

examples/includes/geshi/geshi/visualprolog.php+129−0

This diff is large: its 130 lines aren’t shown here.

examples/includes/geshi/geshi/whitespace.php+121−0

This diff is large: its 122 lines aren’t shown here.

examples/includes/geshi/geshi/winbatch.php+369−0

This diff is large: its 370 lines aren’t shown here.

examples/includes/geshi/geshi/xml.php+157−0

This diff is large: its 158 lines aren’t shown here.

examples/includes/geshi/geshi/xorg_conf.php+124−0

This diff is large: its 125 lines aren’t shown here.

examples/includes/geshi/geshi/xpp.php+436−0

This diff is large: its 437 lines aren’t shown here.

examples/includes/geshi/geshi/z80.php+144−0

This diff is large: its 145 lines aren’t shown here.

examples/includes/vp8_doc_tools.php+207−0

This diff is large: its 208 lines aren’t shown here.

examples/postproc.txt+67−0

This diff is large: its 68 lines aren’t shown here.

examples/simple_decoder.txt+96−0

This diff is large: its 97 lines aren’t shown here.

examples/simple_encoder.txt+105−0

This diff is large: its 106 lines aren’t shown here.

examples/twopass_encoder.txt+75−0

This diff is large: its 76 lines aren’t shown here.

examples/vp8_scalable_patterns.txt+143−0

This diff is large: its 144 lines aren’t shown here.

examples/vp8_set_maps.txt+96−0

This diff is large: its 97 lines aren’t shown here.

examples/vp8cx_set_ref.txt+73−0

This diff is large: its 74 lines aren’t shown here.

ivfdec.c+593−0

This diff is large: its 594 lines aren’t shown here.

ivfenc.c+1059−0

This diff is large: its 1060 lines aren’t shown here.

keywords.dox+51−0

This diff is large: its 52 lines aren’t shown here.

libs.doxy_template+1307−0

This diff is large: its 1308 lines aren’t shown here.

libs.mk+225−0

This diff is large: its 226 lines aren’t shown here.

mainpage.dox+45−0

This diff is large: its 46 lines aren’t shown here.

md5_utils.c+298−0

This diff is large: its 299 lines aren’t shown here.

md5_utils.h+51−0

This diff is large: its 52 lines aren’t shown here.

release.sh+209−0

This diff is large: its 210 lines aren’t shown here.

solution.mk+54−0

This diff is large: its 55 lines aren’t shown here.

usage.dox+203−0

This diff is large: its 204 lines aren’t shown here.

usage_cx.dox+14−0

This diff is large: its 15 lines aren’t shown here.

usage_dx.dox+62−0

This diff is large: its 63 lines aren’t shown here.

vp8/common/alloccommon.c+251−0

This diff is large: its 252 lines aren’t shown here.

vp8/common/alloccommon.h+22−0

This diff is large: its 23 lines aren’t shown here.

vp8/common/arm/armv6/bilinearfilter_v6.asm+237−0

This diff is large: its 238 lines aren’t shown here.

vp8/common/arm/armv6/copymem16x16_v6.asm+181−0

This diff is large: its 182 lines aren’t shown here.

vp8/common/arm/armv6/copymem8x4_v6.asm+127−0

This diff is large: its 128 lines aren’t shown here.

vp8/common/arm/armv6/copymem8x8_v6.asm+127−0

This diff is large: its 128 lines aren’t shown here.

vp8/common/arm/armv6/filter_v6.asm+383−0

This diff is large: its 384 lines aren’t shown here.

vp8/common/arm/armv6/idct_v6.asm+376−0

This diff is large: its 377 lines aren’t shown here.

vp8/common/arm/armv6/iwalsh_v6.asm+151−0

This diff is large: its 152 lines aren’t shown here.

vp8/common/arm/armv6/loopfilter_v6.asm+1263−0

This diff is large: its 1264 lines aren’t shown here.

vp8/common/arm/armv6/recon_v6.asm+280−0

This diff is large: its 281 lines aren’t shown here.

vp8/common/arm/armv6/simpleloopfilter_v6.asm+321−0

This diff is large: its 322 lines aren’t shown here.

vp8/common/arm/armv6/sixtappredict8x4_v6.asm+277−0

This diff is large: its 278 lines aren’t shown here.

vp8/common/arm/bilinearfilter_arm.c+211−0

This diff is large: its 212 lines aren’t shown here.

vp8/common/arm/filter_arm.c+234−0

This diff is large: its 235 lines aren’t shown here.

vp8/common/arm/idct_arm.h+60−0

This diff is large: its 61 lines aren’t shown here.

vp8/common/arm/loopfilter_arm.c+246−0

This diff is large: its 247 lines aren’t shown here.

vp8/common/arm/loopfilter_arm.h+84−0

This diff is large: its 85 lines aren’t shown here.

vp8/common/arm/neon/bilinearpredict16x16_neon.asm+361−0

This diff is large: its 362 lines aren’t shown here.

vp8/common/arm/neon/bilinearpredict4x4_neon.asm+134−0

This diff is large: its 135 lines aren’t shown here.

vp8/common/arm/neon/bilinearpredict8x4_neon.asm+139−0

This diff is large: its 140 lines aren’t shown here.

vp8/common/arm/neon/bilinearpredict8x8_neon.asm+187−0

This diff is large: its 188 lines aren’t shown here.

vp8/common/arm/neon/buildintrapredictorsmby_neon.asm+583−0

This diff is large: its 584 lines aren’t shown here.

vp8/common/arm/neon/copymem16x16_neon.asm+58−0

This diff is large: its 59 lines aren’t shown here.

vp8/common/arm/neon/copymem8x4_neon.asm+33−0

This diff is large: its 34 lines aren’t shown here.

vp8/common/arm/neon/copymem8x8_neon.asm+42−0

This diff is large: its 43 lines aren’t shown here.

vp8/common/arm/neon/iwalsh_neon.asm+95−0

This diff is large: its 96 lines aren’t shown here.

vp8/common/arm/neon/loopfilterhorizontaledge_uv_neon.asm+205−0

This diff is large: its 206 lines aren’t shown here.

vp8/common/arm/neon/loopfilterhorizontaledge_y_neon.asm+188−0

This diff is large: its 189 lines aren’t shown here.

vp8/common/arm/neon/loopfiltersimplehorizontaledge_neon.asm+117−0

This diff is large: its 118 lines aren’t shown here.

vp8/common/arm/neon/loopfiltersimpleverticaledge_neon.asm+158−0

This diff is large: its 159 lines aren’t shown here.

vp8/common/arm/neon/loopfilterverticaledge_uv_neon.asm+231−0

This diff is large: its 232 lines aren’t shown here.

vp8/common/arm/neon/loopfilterverticaledge_y_neon.asm+235−0

This diff is large: its 236 lines aren’t shown here.

vp8/common/arm/neon/mbloopfilterhorizontaledge_uv_neon.asm+257−0

This diff is large: its 258 lines aren’t shown here.

vp8/common/arm/neon/mbloopfilterhorizontaledge_y_neon.asm+236−0

This diff is large: its 237 lines aren’t shown here.

vp8/common/arm/neon/mbloopfilterverticaledge_uv_neon.asm+296−0

This diff is large: its 297 lines aren’t shown here.

vp8/common/arm/neon/mbloopfilterverticaledge_y_neon.asm+303−0

This diff is large: its 304 lines aren’t shown here.

vp8/common/arm/neon/recon16x16mb_neon.asm+130−0

This diff is large: its 131 lines aren’t shown here.

vp8/common/arm/neon/recon2b_neon.asm+53−0

This diff is large: its 54 lines aren’t shown here.

vp8/common/arm/neon/recon4b_neon.asm+68−0

This diff is large: its 69 lines aren’t shown here.

vp8/common/arm/neon/reconb_neon.asm+60−0

This diff is large: its 61 lines aren’t shown here.

vp8/common/arm/neon/save_neon_reg.asm+35−0

This diff is large: its 36 lines aren’t shown here.

vp8/common/arm/neon/shortidct4x4llm_1_neon.asm+66−0

This diff is large: its 67 lines aren’t shown here.

vp8/common/arm/neon/shortidct4x4llm_neon.asm+126−0

This diff is large: its 127 lines aren’t shown here.

vp8/common/arm/neon/sixtappredict16x16_neon.asm+494−0

This diff is large: its 495 lines aren’t shown here.

vp8/common/arm/neon/sixtappredict4x4_neon.asm+425−0

This diff is large: its 426 lines aren’t shown here.

vp8/common/arm/neon/sixtappredict8x4_neon.asm+476−0

This diff is large: its 477 lines aren’t shown here.

vp8/common/arm/neon/sixtappredict8x8_neon.asm+527−0

This diff is large: its 528 lines aren’t shown here.

vp8/common/arm/recon_arm.c+108−0

This diff is large: its 109 lines aren’t shown here.

vp8/common/arm/recon_arm.h+70−0

This diff is large: its 71 lines aren’t shown here.

vp8/common/arm/reconintra4x4_arm.c+408−0

This diff is large: its 409 lines aren’t shown here.

vp8/common/arm/reconintra_arm.c+61−0

This diff is large: its 62 lines aren’t shown here.

vp8/common/arm/subpixel_arm.h+84−0

This diff is large: its 85 lines aren’t shown here.

vp8/common/arm/systemdependent.c+148−0

This diff is large: its 149 lines aren’t shown here.

vp8/common/arm/vpx_asm_offsets.c+91−0

This diff is large: its 92 lines aren’t shown here.

vp8/common/bigend.h+31−0

This diff is large: its 32 lines aren’t shown here.

vp8/common/blockd.c+23−0

This diff is large: its 24 lines aren’t shown here.

vp8/common/blockd.h+299−0

This diff is large: its 300 lines aren’t shown here.

vp8/common/boolcoder.h+569−0

This diff is large: its 570 lines aren’t shown here.

vp8/common/codec_common_interface.h+92−0

This diff is large: its 93 lines aren’t shown here.

vp8/common/coefupdateprobs.h+184−0

This diff is large: its 185 lines aren’t shown here.

vp8/common/common.h+41−0

This diff is large: its 42 lines aren’t shown here.

vp8/common/common_types.h+17−0

This diff is large: its 18 lines aren’t shown here.

vp8/common/context.c+398−0

This diff is large: its 399 lines aren’t shown here.

vp8/common/debugmodes.c+156−0

This diff is large: its 157 lines aren’t shown here.

vp8/common/defaultcoefcounts.h+220−0

This diff is large: its 221 lines aren’t shown here.

vp8/common/dma_desc.h+124−0

This diff is large: its 125 lines aren’t shown here.

vp8/common/duck_io.h+115−0

This diff is large: its 116 lines aren’t shown here.

vp8/common/entropy.c+161−0

This diff is large: its 162 lines aren’t shown here.

vp8/common/entropy.h+101−0

This diff is large: its 102 lines aren’t shown here.

vp8/common/entropymode.c+270−0

This diff is large: its 271 lines aren’t shown here.

vp8/common/entropymode.h+71−0

This diff is large: its 72 lines aren’t shown here.

vp8/common/entropymv.c+48−0

This diff is large: its 49 lines aren’t shown here.

vp8/common/entropymv.h+41−0

This diff is large: its 42 lines aren’t shown here.

vp8/common/extend.c+120−0

This diff is large: its 121 lines aren’t shown here.

vp8/common/extend.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/common/filter_c.c+539−0

This diff is large: its 540 lines aren’t shown here.

vp8/common/findnearmv.c+207−0

This diff is large: its 208 lines aren’t shown here.

vp8/common/findnearmv.h+41−0

This diff is large: its 42 lines aren’t shown here.

vp8/common/fourcc.hpp+120−0

This diff is large: its 121 lines aren’t shown here.

vp8/common/g_common.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/common/generic/systemdependent.c+79−0

This diff is large: its 80 lines aren’t shown here.

vp8/common/header.h+42−0

This diff is large: its 43 lines aren’t shown here.

vp8/common/idct.h+77−0

This diff is large: its 78 lines aren’t shown here.

vp8/common/idctllm.c+189−0

This diff is large: its 190 lines aren’t shown here.

vp8/common/invtrans.c+86−0

This diff is large: its 87 lines aren’t shown here.

vp8/common/invtrans.h+22−0

This diff is large: its 23 lines aren’t shown here.

vp8/common/littlend.h+32−0

This diff is large: its 33 lines aren’t shown here.

vp8/common/loopfilter.c+601−0

This diff is large: its 602 lines aren’t shown here.

vp8/common/loopfilter.h+120−0

This diff is large: its 121 lines aren’t shown here.

vp8/common/loopfilter_filters.c+368−0

This diff is large: its 369 lines aren’t shown here.

vp8/common/mac_specs.h+30−0

This diff is large: its 31 lines aren’t shown here.

vp8/common/mbpitch.c+128−0

This diff is large: its 129 lines aren’t shown here.

vp8/common/modecont.c+39−0

This diff is large: its 40 lines aren’t shown here.

vp8/common/modecont.h+16−0

This diff is large: its 17 lines aren’t shown here.

vp8/common/modecontext.c+145−0

This diff is large: its 146 lines aren’t shown here.

vp8/common/mv.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/common/onyx.h+222−0

This diff is large: its 223 lines aren’t shown here.

vp8/common/onyxc_int.h+205−0

This diff is large: its 206 lines aren’t shown here.

vp8/common/onyxd.h+67−0

This diff is large: its 68 lines aren’t shown here.

vp8/common/partialgfupdate.h+18−0

This diff is large: its 19 lines aren’t shown here.

vp8/common/postproc.c+641−0

This diff is large: its 642 lines aren’t shown here.

vp8/common/postproc.h+90−0

This diff is large: its 91 lines aren’t shown here.

vp8/common/ppc/copy_altivec.asm+46−0

This diff is large: its 47 lines aren’t shown here.

vp8/common/ppc/filter_altivec.asm+1012−0

This diff is large: its 1013 lines aren’t shown here.

vp8/common/ppc/filter_bilinear_altivec.asm+676−0

This diff is large: its 677 lines aren’t shown here.

vp8/common/ppc/idctllm_altivec.asm+188−0

This diff is large: its 189 lines aren’t shown here.

vp8/common/ppc/loopfilter_altivec.c+142−0

This diff is large: its 143 lines aren’t shown here.

vp8/common/ppc/loopfilter_filters_altivec.asm+1252−0

This diff is large: its 1253 lines aren’t shown here.

vp8/common/ppc/platform_altivec.asm+58−0

This diff is large: its 59 lines aren’t shown here.

vp8/common/ppc/recon_altivec.asm+174−0

This diff is large: its 175 lines aren’t shown here.

vp8/common/ppc/systemdependent.c+170−0

This diff is large: its 171 lines aren’t shown here.

vp8/common/ppflags.h+25−0

This diff is large: its 26 lines aren’t shown here.

vp8/common/pragmas.h+18−0

This diff is large: its 19 lines aren’t shown here.

vp8/common/predictdc.c+43−0

This diff is large: its 44 lines aren’t shown here.

vp8/common/predictdc.h+17−0

This diff is large: its 18 lines aren’t shown here.

vp8/common/preproc.h+45−0

This diff is large: its 46 lines aren’t shown here.

vp8/common/preprocif.h+75−0

This diff is large: its 76 lines aren’t shown here.

vp8/common/proposed.h+70−0

This diff is large: its 71 lines aren’t shown here.

vp8/common/quant_common.c+131−0

This diff is large: its 132 lines aren’t shown here.

vp8/common/quant_common.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/common/recon.c+137−0

This diff is large: its 138 lines aren’t shown here.

vp8/common/recon.h+81−0

This diff is large: its 82 lines aren’t shown here.

vp8/common/reconinter.c+680−0

This diff is large: its 681 lines aren’t shown here.

vp8/common/reconinter.h+22−0

This diff is large: its 23 lines aren’t shown here.

vp8/common/reconintra.c+555−0

This diff is large: its 556 lines aren’t shown here.

vp8/common/reconintra.h+28−0

This diff is large: its 29 lines aren’t shown here.

vp8/common/reconintra4x4.c+330−0

This diff is large: its 331 lines aren’t shown here.

vp8/common/reconintra4x4.h+16−0

This diff is large: its 17 lines aren’t shown here.

vp8/common/segmentation_common.c+63−0

This diff is large: its 64 lines aren’t shown here.

vp8/common/segmentation_common.h+15−0

This diff is large: its 16 lines aren’t shown here.

vp8/common/setupintrarecon.c+37−0

This diff is large: its 38 lines aren’t shown here.

vp8/common/setupintrarecon.h+12−0

This diff is large: its 13 lines aren’t shown here.

vp8/common/subpixel.h+85−0

This diff is large: its 86 lines aren’t shown here.

vp8/common/swapyv12buffer.c+33−0

This diff is large: its 34 lines aren’t shown here.

vp8/common/swapyv12buffer.h+18−0

This diff is large: its 19 lines aren’t shown here.

vp8/common/systemdependent.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/common/textblit.c+52−0

This diff is large: its 53 lines aren’t shown here.

vp8/common/threading.h+89−0

This diff is large: its 90 lines aren’t shown here.

vp8/common/treecoder.c+136−0

This diff is large: its 137 lines aren’t shown here.

vp8/common/treecoder.h+87−0

This diff is large: its 88 lines aren’t shown here.

vp8/common/type_aliases.h+116−0

This diff is large: its 117 lines aren’t shown here.

vp8/common/vfwsetting.hpp+75−0

This diff is large: its 76 lines aren’t shown here.

vp8/common/vpx_ref_build_prefix.h+23−0

This diff is large: its 24 lines aren’t shown here.

vp8/common/vpxblit.h+111−0

This diff is large: its 112 lines aren’t shown here.

vp8/common/vpxblit_c64.h+47−0

This diff is large: its 48 lines aren’t shown here.

vp8/common/vpxerrors.h+12−0

This diff is large: its 13 lines aren’t shown here.

vp8/common/x86/boolcoder.cxx+493−0

This diff is large: its 494 lines aren’t shown here.

vp8/common/x86/idct_x86.h+63−0

This diff is large: its 64 lines aren’t shown here.

vp8/common/x86/idctllm_mmx.asm+265−0

This diff is large: its 266 lines aren’t shown here.

vp8/common/x86/iwalsh_mmx.asm+172−0

This diff is large: its 173 lines aren’t shown here.

vp8/common/x86/iwalsh_sse2.asm+116−0

This diff is large: its 117 lines aren’t shown here.

vp8/common/x86/loopfilter_mmx.asm+1776−0

This diff is large: its 1777 lines aren’t shown here.

vp8/common/x86/loopfilter_sse2.asm+1978−0

This diff is large: its 1979 lines aren’t shown here.

vp8/common/x86/loopfilter_x86.c+274−0

This diff is large: its 275 lines aren’t shown here.

vp8/common/x86/loopfilter_x86.h+99−0

This diff is large: its 100 lines aren’t shown here.

vp8/common/x86/postproc_mmx.asm+533−0

This diff is large: its 534 lines aren’t shown here.

vp8/common/x86/postproc_mmx.c+1507−0

This diff is large: its 1508 lines aren’t shown here.

vp8/common/x86/postproc_sse2.asm+688−0

This diff is large: its 689 lines aren’t shown here.

vp8/common/x86/postproc_x86.h+63−0

This diff is large: its 64 lines aren’t shown here.

vp8/common/x86/recon_mmx.asm+320−0

This diff is large: its 321 lines aren’t shown here.

vp8/common/x86/recon_sse2.asm+228−0

This diff is large: its 229 lines aren’t shown here.

vp8/common/x86/recon_x86.h+61−0

This diff is large: its 62 lines aren’t shown here.

vp8/common/x86/subpixel_mmx.asm+817−0

This diff is large: its 818 lines aren’t shown here.

vp8/common/x86/subpixel_sse2.asm+1032−0

This diff is large: its 1033 lines aren’t shown here.

vp8/common/x86/subpixel_x86.h+88−0

This diff is large: its 89 lines aren’t shown here.

vp8/common/x86/vp8_asm_stubs.c+342−0

This diff is large: its 343 lines aren’t shown here.

vp8/common/x86/x86_systemdependent.c+117−0

This diff is large: its 118 lines aren’t shown here.

vp8/decoder/arm/armv5/dequantize_v5.asm+51−0

This diff is large: its 52 lines aren’t shown here.

vp8/decoder/arm/armv6/dboolhuff_v6.asm+162−0

This diff is large: its 163 lines aren’t shown here.

vp8/decoder/arm/armv6/dequantdcidct_v6.asm+202−0

This diff is large: its 203 lines aren’t shown here.

vp8/decoder/arm/armv6/dequantidct_v6.asm+183−0

This diff is large: its 184 lines aren’t shown here.

vp8/decoder/arm/armv6/dequantize_v6.asm+68−0

This diff is large: its 69 lines aren’t shown here.

vp8/decoder/arm/dboolhuff_arm.h+49−0

This diff is large: its 50 lines aren’t shown here.

vp8/decoder/arm/dequantize_arm.c+48−0

This diff is large: its 49 lines aren’t shown here.

vp8/decoder/arm/dequantize_arm.h+44−0

This diff is large: its 45 lines aren’t shown here.

vp8/decoder/arm/detokenizearm_sjl.c+730−0

This diff is large: its 731 lines aren’t shown here.

vp8/decoder/arm/detokenizearm_v6.asm+364−0

This diff is large: its 365 lines aren’t shown here.

vp8/decoder/arm/dsystemdependent.c+44−0

This diff is large: its 45 lines aren’t shown here.

vp8/decoder/arm/neon/dboolhuff_neon.asm+159−0

This diff is large: its 160 lines aren’t shown here.

vp8/decoder/arm/neon/dequantdcidct_neon.asm+133−0

This diff is large: its 134 lines aren’t shown here.

vp8/decoder/arm/neon/dequantidct_neon.asm+128−0

This diff is large: its 129 lines aren’t shown here.

vp8/decoder/arm/neon/dequantizeb_neon.asm+33−0

This diff is large: its 34 lines aren’t shown here.

vp8/decoder/dboolhuff.c+174−0

This diff is large: its 175 lines aren’t shown here.

vp8/decoder/dboolhuff.h+226−0

This diff is large: its 227 lines aren’t shown here.

vp8/decoder/decodemv.c+418−0

This diff is large: its 419 lines aren’t shown here.

vp8/decoder/decodemv.h+13−0

This diff is large: its 14 lines aren’t shown here.

vp8/decoder/decoderthreading.h+24−0

This diff is large: its 25 lines aren’t shown here.

vp8/decoder/decodframe.c+907−0

This diff is large: its 908 lines aren’t shown here.

vp8/decoder/demode.c+149−0

This diff is large: its 150 lines aren’t shown here.

vp8/decoder/demode.h+32−0

This diff is large: its 33 lines aren’t shown here.

vp8/decoder/dequantize.c+60−0

This diff is large: its 61 lines aren’t shown here.

vp8/decoder/dequantize.h+64−0

This diff is large: its 65 lines aren’t shown here.

vp8/decoder/detokenize.c+374−0

This diff is large: its 375 lines aren’t shown here.

vp8/decoder/detokenize.h+19−0

This diff is large: its 20 lines aren’t shown here.

vp8/decoder/generic/dsystemdependent.c+37−0

This diff is large: its 38 lines aren’t shown here.

vp8/decoder/onyxd_if.c+451−0

This diff is large: its 452 lines aren’t shown here.

vp8/decoder/onyxd_if_sjl.c+398−0

This diff is large: its 399 lines aren’t shown here.

vp8/decoder/onyxd_int.h+149−0

This diff is large: its 150 lines aren’t shown here.

vp8/decoder/threading.c+596−0

This diff is large: its 597 lines aren’t shown here.

vp8/decoder/treereader.h+63−0

This diff is large: its 64 lines aren’t shown here.

vp8/decoder/x86/dequantize_mmx.asm+410−0

This diff is large: its 411 lines aren’t shown here.

vp8/decoder/x86/dequantize_x86.h+40−0

This diff is large: its 41 lines aren’t shown here.

vp8/decoder/x86/onyxdxv.c+1079−0

This diff is large: its 1080 lines aren’t shown here.

vp8/decoder/x86/x86_dsystemdependent.c+51−0

This diff is large: its 52 lines aren’t shown here.

vp8/decoder/xprintf.c+163−0

This diff is large: its 164 lines aren’t shown here.

vp8/decoder/xprintf.h+32−0

This diff is large: its 33 lines aren’t shown here.

vp8/encoder/arm/armv6/walsh_v6.asm+144−0

This diff is large: its 145 lines aren’t shown here.

vp8/encoder/arm/boolhuff_arm.c+33−0

This diff is large: its 34 lines aren’t shown here.

vp8/encoder/arm/csystemdependent.c+159−0

This diff is large: its 160 lines aren’t shown here.

vp8/encoder/arm/dct_arm.h+45−0

This diff is large: its 46 lines aren’t shown here.

vp8/encoder/arm/encodemb_arm.c+30−0

This diff is large: its 31 lines aren’t shown here.

vp8/encoder/arm/encodemb_arm.h+43−0

This diff is large: its 44 lines aren’t shown here.

vp8/encoder/arm/mcomp_arm.c+1662−0

This diff is large: its 1663 lines aren’t shown here.

vp8/encoder/arm/neon/boolhuff_armv7.asm+292−0

This diff is large: its 293 lines aren’t shown here.

vp8/encoder/arm/neon/fastfdct4x4_neon.asm+126−0

This diff is large: its 127 lines aren’t shown here.

vp8/encoder/arm/neon/fastfdct8x4_neon.asm+179−0

This diff is large: its 180 lines aren’t shown here.

vp8/encoder/arm/neon/fastquantizeb_neon.asm+117−0

This diff is large: its 118 lines aren’t shown here.

vp8/encoder/arm/neon/sad16_neon.asm+206−0

This diff is large: its 207 lines aren’t shown here.

vp8/encoder/arm/neon/sad8_neon.asm+208−0

This diff is large: its 209 lines aren’t shown here.

vp8/encoder/arm/neon/shortfdct_neon.asm+146−0

This diff is large: its 147 lines aren’t shown here.

vp8/encoder/arm/neon/subtract_neon.asm+171−0

This diff is large: its 172 lines aren’t shown here.

vp8/encoder/arm/neon/variance_neon.asm+275−0

This diff is large: its 276 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_memcpy_neon.asm+67−0

This diff is large: its 68 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_mse16x16_neon.asm+172−0

This diff is large: its 173 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_packtokens_armv7.asm+300−0

This diff is large: its 301 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_packtokens_mbrow_armv7.asm+335−0

This diff is large: its 336 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_packtokens_partitions_armv7.asm+471−0

This diff is large: its 472 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_shortwalsh4x4_neon.asm+75−0

This diff is large: its 76 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_subpixelvariance16x16_neon.asm+427−0

This diff is large: its 428 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_subpixelvariance16x16s_neon.asm+571−0

This diff is large: its 572 lines aren’t shown here.

vp8/encoder/arm/neon/vp8_subpixelvariance8x8_neon.asm+226−0

This diff is large: its 227 lines aren’t shown here.

vp8/encoder/arm/picklpf_arm.c+49−0

This diff is large: its 50 lines aren’t shown here.

vp8/encoder/arm/quantize_arm.c+79−0

This diff is large: its 80 lines aren’t shown here.

vp8/encoder/arm/quantize_arm.h+22−0

This diff is large: its 23 lines aren’t shown here.

vp8/encoder/arm/variance_arm.h+105−0

This diff is large: its 106 lines aren’t shown here.

vp8/encoder/arm/vpx_vp8_enc_asm_offsets.c+77−0

This diff is large: its 78 lines aren’t shown here.

vp8/encoder/bitstream.c+1719−0

This diff is large: its 1720 lines aren’t shown here.

vp8/encoder/bitstream.h+38−0

This diff is large: its 39 lines aren’t shown here.

vp8/encoder/block.h+115−0

This diff is large: its 116 lines aren’t shown here.

vp8/encoder/boolhuff.c+147−0

This diff is large: its 148 lines aren’t shown here.

vp8/encoder/boolhuff.h+42−0

This diff is large: its 43 lines aren’t shown here.

vp8/encoder/dct.c+223−0

This diff is large: its 224 lines aren’t shown here.

vp8/encoder/dct.h+65−0

This diff is large: its 66 lines aren’t shown here.

vp8/encoder/encodeframe.c+1223−0

This diff is large: its 1224 lines aren’t shown here.

vp8/encoder/encodeintra.c+236−0

This diff is large: its 237 lines aren’t shown here.

vp8/encoder/encodeintra.h+24−0

This diff is large: its 25 lines aren’t shown here.

vp8/encoder/encodemb.c+1129−0

This diff is large: its 1130 lines aren’t shown here.

vp8/encoder/encodemb.h+112−0

This diff is large: its 113 lines aren’t shown here.

vp8/encoder/encodemv.c+445−0

This diff is large: its 446 lines aren’t shown here.

vp8/encoder/encodemv.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/encoder/ethreading.c+510−0

This diff is large: its 511 lines aren’t shown here.

vp8/encoder/firstpass.c+2512−0

This diff is large: its 2513 lines aren’t shown here.

vp8/encoder/firstpass.h+22−0

This diff is large: its 23 lines aren’t shown here.

vp8/encoder/generic/csystemdependent.c+96−0

This diff is large: its 97 lines aren’t shown here.

vp8/encoder/mcomp.c+1467−0

This diff is large: its 1468 lines aren’t shown here.

vp8/encoder/mcomp.h+121−0

This diff is large: its 122 lines aren’t shown here.

vp8/encoder/modecosts.c+46−0

This diff is large: its 47 lines aren’t shown here.

vp8/encoder/modecosts.h+16−0

This diff is large: its 17 lines aren’t shown here.

vp8/encoder/onyx_if.c+5428−0

This diff is large: its 5429 lines aren’t shown here.

vp8/encoder/onyx_int.h+670−0

This diff is large: its 671 lines aren’t shown here.

vp8/encoder/parms.cpp+106−0

This diff is large: its 107 lines aren’t shown here.

vp8/encoder/pickinter.c+923−0

This diff is large: its 924 lines aren’t shown here.

vp8/encoder/pickinter.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/encoder/picklpf.c+435−0

This diff is large: its 436 lines aren’t shown here.

vp8/encoder/ppc/csystemdependent.c+168−0

This diff is large: its 169 lines aren’t shown here.

vp8/encoder/ppc/encodemb_altivec.asm+152−0

This diff is large: its 153 lines aren’t shown here.

vp8/encoder/ppc/fdct_altivec.asm+204−0

This diff is large: its 205 lines aren’t shown here.

vp8/encoder/ppc/rdopt_altivec.asm+50−0

This diff is large: its 51 lines aren’t shown here.

vp8/encoder/ppc/sad_altivec.asm+276−0

This diff is large: its 277 lines aren’t shown here.

vp8/encoder/ppc/variance_altivec.asm+374−0

This diff is large: its 375 lines aren’t shown here.

vp8/encoder/ppc/variance_subpixel_altivec.asm+864−0

This diff is large: its 865 lines aren’t shown here.

vp8/encoder/preproc.c+250−0

This diff is large: its 251 lines aren’t shown here.

vp8/encoder/psnr.c+116−0

This diff is large: its 117 lines aren’t shown here.

vp8/encoder/psnr.h+17−0

This diff is large: its 18 lines aren’t shown here.

vp8/encoder/quantize.c+249−0

This diff is large: its 250 lines aren’t shown here.

vp8/encoder/quantize.h+52−0

This diff is large: its 53 lines aren’t shown here.

vp8/encoder/ratectrl.c+1552−0

This diff is large: its 1553 lines aren’t shown here.

vp8/encoder/ratectrl.h+26−0

This diff is large: its 27 lines aren’t shown here.

vp8/encoder/rdopt.c+2212−0

This diff is large: its 2213 lines aren’t shown here.

vp8/encoder/rdopt.h+20−0

This diff is large: its 21 lines aren’t shown here.

vp8/encoder/sad_c.c+248−0

This diff is large: its 249 lines aren’t shown here.

vp8/encoder/ssim.c+521−0

This diff is large: its 522 lines aren’t shown here.

vp8/encoder/tokenize.c+636−0

This diff is large: its 637 lines aren’t shown here.

vp8/encoder/tokenize.h+38−0

This diff is large: its 39 lines aren’t shown here.

vp8/encoder/treewriter.c+38−0

This diff is large: its 39 lines aren’t shown here.

vp8/encoder/treewriter.h+121−0

This diff is large: its 122 lines aren’t shown here.

vp8/encoder/variance.h+327−0

This diff is large: its 328 lines aren’t shown here.

vp8/encoder/variance_c.c+527−0

This diff is large: its 528 lines aren’t shown here.

vp8/encoder/x86/csystemdependent.c+289−0

This diff is large: its 290 lines aren’t shown here.

vp8/encoder/x86/dct_mmx.asm+846−0

This diff is large: its 847 lines aren’t shown here.

vp8/encoder/x86/dct_sse2.asm+260−0

This diff is large: its 261 lines aren’t shown here.

vp8/encoder/x86/dct_x86.h+73−0

This diff is large: its 74 lines aren’t shown here.

vp8/encoder/x86/encodemb_x86.h+73−0

This diff is large: its 74 lines aren’t shown here.

vp8/encoder/x86/encodeopt.asm+393−0

This diff is large: its 394 lines aren’t shown here.

vp8/encoder/x86/fwalsh_sse2.asm+117−0

This diff is large: its 118 lines aren’t shown here.

vp8/encoder/x86/mcomp_x86.h+27−0

This diff is large: its 28 lines aren’t shown here.

vp8/encoder/x86/preproc_mmx.c+297−0

This diff is large: its 298 lines aren’t shown here.

This diff is larger than a page shows: the files after these aren’t listed. Clone the repository to see all of it.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t